diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv6/addrconf.c | 91 |
1 files changed, 53 insertions, 38 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index c92f3d6a8f13..8a8895ef09a7 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -1299,52 +1299,67 @@ static void addrconf_leave_anycast(struct inet6_ifaddr *ifp) | |||
1299 | __ipv6_dev_ac_dec(ifp->idev, &addr); | 1299 | __ipv6_dev_ac_dec(ifp->idev, &addr); |
1300 | } | 1300 | } |
1301 | 1301 | ||
1302 | static int addrconf_ifid_eui48(u8 *eui, struct net_device *dev) | ||
1303 | { | ||
1304 | if (dev->addr_len != ETH_ALEN) | ||
1305 | return -1; | ||
1306 | memcpy(eui, dev->dev_addr, 3); | ||
1307 | memcpy(eui + 5, dev->dev_addr + 3, 3); | ||
1308 | |||
1309 | /* | ||
1310 | * The zSeries OSA network cards can be shared among various | ||
1311 | * OS instances, but the OSA cards have only one MAC address. | ||
1312 | * This leads to duplicate address conflicts in conjunction | ||
1313 | * with IPv6 if more than one instance uses the same card. | ||
1314 | * | ||
1315 | * The driver for these cards can deliver a unique 16-bit | ||
1316 | * identifier for each instance sharing the same card. It is | ||
1317 | * placed instead of 0xFFFE in the interface identifier. The | ||
1318 | * "u" bit of the interface identifier is not inverted in this | ||
1319 | * case. Hence the resulting interface identifier has local | ||
1320 | * scope according to RFC2373. | ||
1321 | */ | ||
1322 | if (dev->dev_id) { | ||
1323 | eui[3] = (dev->dev_id >> 8) & 0xFF; | ||
1324 | eui[4] = dev->dev_id & 0xFF; | ||
1325 | } else { | ||
1326 | eui[3] = 0xFF; | ||
1327 | eui[4] = 0xFE; | ||
1328 | eui[0] ^= 2; | ||
1329 | } | ||
1330 | return 0; | ||
1331 | } | ||
1332 | |||
1333 | static int addrconf_ifid_arcnet(u8 *eui, struct net_device *dev) | ||
1334 | { | ||
1335 | /* XXX: inherit EUI-64 from other interface -- yoshfuji */ | ||
1336 | if (dev->addr_len != ARCNET_ALEN) | ||
1337 | return -1; | ||
1338 | memset(eui, 0, 7); | ||
1339 | eui[7] = *(u8*)dev->dev_addr; | ||
1340 | return 0; | ||
1341 | } | ||
1342 | |||
1343 | static int addrconf_ifid_infiniband(u8 *eui, struct net_device *dev) | ||
1344 | { | ||
1345 | if (dev->addr_len != INFINIBAND_ALEN) | ||
1346 | return -1; | ||
1347 | memcpy(eui, dev->dev_addr + 12, 8); | ||
1348 | eui[0] |= 2; | ||
1349 | return 0; | ||
1350 | } | ||
1351 | |||
1302 | static int ipv6_generate_eui64(u8 *eui, struct net_device *dev) | 1352 | static int ipv6_generate_eui64(u8 *eui, struct net_device *dev) |
1303 | { | 1353 | { |
1304 | switch (dev->type) { | 1354 | switch (dev->type) { |
1305 | case ARPHRD_ETHER: | 1355 | case ARPHRD_ETHER: |
1306 | case ARPHRD_FDDI: | 1356 | case ARPHRD_FDDI: |
1307 | case ARPHRD_IEEE802_TR: | 1357 | case ARPHRD_IEEE802_TR: |
1308 | if (dev->addr_len != ETH_ALEN) | 1358 | return addrconf_ifid_eui48(eui, dev); |
1309 | return -1; | ||
1310 | memcpy(eui, dev->dev_addr, 3); | ||
1311 | memcpy(eui + 5, dev->dev_addr + 3, 3); | ||
1312 | |||
1313 | /* | ||
1314 | * The zSeries OSA network cards can be shared among various | ||
1315 | * OS instances, but the OSA cards have only one MAC address. | ||
1316 | * This leads to duplicate address conflicts in conjunction | ||
1317 | * with IPv6 if more than one instance uses the same card. | ||
1318 | * | ||
1319 | * The driver for these cards can deliver a unique 16-bit | ||
1320 | * identifier for each instance sharing the same card. It is | ||
1321 | * placed instead of 0xFFFE in the interface identifier. The | ||
1322 | * "u" bit of the interface identifier is not inverted in this | ||
1323 | * case. Hence the resulting interface identifier has local | ||
1324 | * scope according to RFC2373. | ||
1325 | */ | ||
1326 | if (dev->dev_id) { | ||
1327 | eui[3] = (dev->dev_id >> 8) & 0xFF; | ||
1328 | eui[4] = dev->dev_id & 0xFF; | ||
1329 | } else { | ||
1330 | eui[3] = 0xFF; | ||
1331 | eui[4] = 0xFE; | ||
1332 | eui[0] ^= 2; | ||
1333 | } | ||
1334 | return 0; | ||
1335 | case ARPHRD_ARCNET: | 1359 | case ARPHRD_ARCNET: |
1336 | /* XXX: inherit EUI-64 from other interface -- yoshfuji */ | 1360 | return addrconf_ifid_arcnet(eui, dev); |
1337 | if (dev->addr_len != ARCNET_ALEN) | ||
1338 | return -1; | ||
1339 | memset(eui, 0, 7); | ||
1340 | eui[7] = *(u8*)dev->dev_addr; | ||
1341 | return 0; | ||
1342 | case ARPHRD_INFINIBAND: | 1361 | case ARPHRD_INFINIBAND: |
1343 | if (dev->addr_len != INFINIBAND_ALEN) | 1362 | return addrconf_ifid_infiniband(eui, dev); |
1344 | return -1; | ||
1345 | memcpy(eui, dev->dev_addr + 12, 8); | ||
1346 | eui[0] |= 2; | ||
1347 | return 0; | ||
1348 | } | 1363 | } |
1349 | return -1; | 1364 | return -1; |
1350 | } | 1365 | } |