Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

firewire net, ipv6: IPv6 over Firewire (RFC3146) support.

Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

YOSHIFUJI Hideaki / 吉藤英明 and committed by
David S. Miller
cb6bf355 6752c8db

+96 -9
+3 -3
drivers/firewire/Kconfig
··· 47 47 tristate "IP networking over 1394" 48 48 depends on FIREWIRE && INET 49 49 help 50 - This enables IPv4 over IEEE 1394, providing IP connectivity with 51 - other implementations of RFC 2734 as found on several operating 52 - systems. Multicast support is currently limited. 50 + This enables IPv4/IPv6 over IEEE 1394, providing IP connectivity 51 + with other implementations of RFC 2734/3146 as found on several 52 + operating systems. Multicast support is currently limited. 53 53 54 54 To compile this driver as a module, say M here: The module will be 55 55 called firewire-net.
+74 -5
drivers/firewire/net.c
··· 1 1 /* 2 2 * IPv4 over IEEE 1394, per RFC 2734 3 + * IPv6 over IEEE 1394, per RFC 3146 3 4 * 4 5 * Copyright (C) 2009 Jay Fenlason <fenlason@redhat.com> 5 6 * ··· 47 46 48 47 #define IANA_SPECIFIER_ID 0x00005eU 49 48 #define RFC2734_SW_VERSION 0x000001U 49 + #define RFC3146_SW_VERSION 0x000002U 50 50 51 51 #define IEEE1394_GASP_HDR_SIZE 8 52 52 ··· 507 505 switch (ether_type) { 508 506 case ETH_P_ARP: 509 507 case ETH_P_IP: 508 + #if IS_ENABLED(CONFIG_IPV6) 509 + case ETH_P_IPV6: 510 + #endif 510 511 break; 511 512 default: 512 513 goto err; ··· 773 768 ver = be32_to_cpu(buf_ptr[1]) & 0xffffff; 774 769 source_node_id = be32_to_cpu(buf_ptr[0]) >> 16; 775 770 776 - if (specifier_id == IANA_SPECIFIER_ID && ver == RFC2734_SW_VERSION) { 771 + if (specifier_id == IANA_SPECIFIER_ID && 772 + (ver == RFC2734_SW_VERSION 773 + #if IS_ENABLED(CONFIG_IPV6) 774 + || ver == RFC3146_SW_VERSION 775 + #endif 776 + )) { 777 777 buf_ptr += 2; 778 778 length -= IEEE1394_GASP_HDR_SIZE; 779 779 fwnet_incoming_packet(dev, buf_ptr, length, source_node_id, ··· 981 971 u8 *p; 982 972 int generation; 983 973 int node_id; 974 + unsigned int sw_version; 984 975 985 976 /* ptask->generation may not have been set yet */ 986 977 generation = dev->card->generation; 987 978 smp_rmb(); 988 979 node_id = dev->card->node_id; 989 980 981 + switch (ptask->skb->protocol) { 982 + default: 983 + sw_version = RFC2734_SW_VERSION; 984 + break; 985 + #if IS_ENABLED(CONFIG_IPV6) 986 + case htons(ETH_P_IPV6): 987 + sw_version = RFC3146_SW_VERSION; 988 + #endif 989 + } 990 + 990 991 p = skb_push(ptask->skb, IEEE1394_GASP_HDR_SIZE); 991 992 put_unaligned_be32(node_id << 16 | IANA_SPECIFIER_ID >> 8, p); 992 993 put_unaligned_be32((IANA_SPECIFIER_ID & 0xff) << 24 993 - | RFC2734_SW_VERSION, &p[4]); 994 + | sw_version, &p[4]); 994 995 995 996 /* We should not transmit if broadcast_channel.valid == 0. */ 996 997 fw_send_request(dev->card, &ptask->transaction, ··· 1269 1248 switch (proto) { 1270 1249 case htons(ETH_P_ARP): 1271 1250 case htons(ETH_P_IP): 1251 + #if IS_ENABLED(CONFIG_IPV6) 1252 + case htons(ETH_P_IPV6): 1253 + #endif 1272 1254 break; 1273 1255 default: 1274 1256 goto fail; ··· 1514 1490 goto out; 1515 1491 1516 1492 list_add_tail(&dev->dev_link, &fwnet_device_list); 1517 - dev_notice(&net->dev, "IPv4 over IEEE 1394 on card %s\n", 1493 + dev_notice(&net->dev, "IP over IEEE 1394 on card %s\n", 1518 1494 dev_name(card->device)); 1519 1495 have_dev: 1520 1496 ret = fwnet_add_peer(dev, unit, device); ··· 1603 1579 .specifier_id = IANA_SPECIFIER_ID, 1604 1580 .version = RFC2734_SW_VERSION, 1605 1581 }, 1582 + #if IS_ENABLED(CONFIG_IPV6) 1583 + { 1584 + .match_flags = IEEE1394_MATCH_SPECIFIER_ID | 1585 + IEEE1394_MATCH_VERSION, 1586 + .specifier_id = IANA_SPECIFIER_ID, 1587 + .version = RFC3146_SW_VERSION, 1588 + }, 1589 + #endif 1606 1590 { } 1607 1591 }; 1608 1592 ··· 1648 1616 .data = rfc2374_unit_directory_data 1649 1617 }; 1650 1618 1619 + #if IS_ENABLED(CONFIG_IPV6) 1620 + static const u32 rfc3146_unit_directory_data[] = { 1621 + 0x00040000, /* directory_length */ 1622 + 0x1200005e, /* unit_specifier_id: IANA */ 1623 + 0x81000003, /* textual descriptor offset */ 1624 + 0x13000002, /* unit_sw_version: RFC 3146 */ 1625 + 0x81000005, /* textual descriptor offset */ 1626 + 0x00030000, /* descriptor_length */ 1627 + 0x00000000, /* text */ 1628 + 0x00000000, /* minimal ASCII, en */ 1629 + 0x49414e41, /* I A N A */ 1630 + 0x00030000, /* descriptor_length */ 1631 + 0x00000000, /* text */ 1632 + 0x00000000, /* minimal ASCII, en */ 1633 + 0x49507636, /* I P v 6 */ 1634 + }; 1635 + 1636 + static struct fw_descriptor rfc3146_unit_directory = { 1637 + .length = ARRAY_SIZE(rfc3146_unit_directory_data), 1638 + .key = (CSR_DIRECTORY | CSR_UNIT) << 24, 1639 + .data = rfc3146_unit_directory_data 1640 + }; 1641 + #endif 1642 + 1651 1643 static int __init fwnet_init(void) 1652 1644 { 1653 1645 int err; ··· 1680 1624 if (err) 1681 1625 return err; 1682 1626 1627 + #if IS_ENABLED(CONFIG_IPV6) 1628 + err = fw_core_add_descriptor(&rfc3146_unit_directory); 1629 + if (err) 1630 + goto out; 1631 + #endif 1632 + 1683 1633 fwnet_packet_task_cache = kmem_cache_create("packet_task", 1684 1634 sizeof(struct fwnet_packet_task), 0, 0, NULL); 1685 1635 if (!fwnet_packet_task_cache) { 1686 1636 err = -ENOMEM; 1687 - goto out; 1637 + goto out2; 1688 1638 } 1689 1639 1690 1640 err = driver_register(&fwnet_driver.driver); ··· 1698 1636 return 0; 1699 1637 1700 1638 kmem_cache_destroy(fwnet_packet_task_cache); 1639 + out2: 1640 + #if IS_ENABLED(CONFIG_IPV6) 1641 + fw_core_remove_descriptor(&rfc3146_unit_directory); 1701 1642 out: 1643 + #endif 1702 1644 fw_core_remove_descriptor(&rfc2374_unit_directory); 1703 1645 1704 1646 return err; ··· 1713 1647 { 1714 1648 driver_unregister(&fwnet_driver.driver); 1715 1649 kmem_cache_destroy(fwnet_packet_task_cache); 1650 + #if IS_ENABLED(CONFIG_IPV6) 1651 + fw_core_remove_descriptor(&rfc3146_unit_directory); 1652 + #endif 1716 1653 fw_core_remove_descriptor(&rfc2374_unit_directory); 1717 1654 } 1718 1655 module_exit(fwnet_cleanup); 1719 1656 1720 1657 MODULE_AUTHOR("Jay Fenlason <fenlason@redhat.com>"); 1721 - MODULE_DESCRIPTION("IPv4 over IEEE1394 as per RFC 2734"); 1658 + MODULE_DESCRIPTION("IP over IEEE1394 as per RFC 2734/3146"); 1722 1659 MODULE_LICENSE("GPL"); 1723 1660 MODULE_DEVICE_TABLE(ieee1394, fwnet_id_table);
+19 -1
net/ipv6/addrconf.c
··· 70 70 #include <net/snmp.h> 71 71 72 72 #include <net/af_ieee802154.h> 73 + #include <net/firewire.h> 73 74 #include <net/ipv6.h> 74 75 #include <net/protocol.h> 75 76 #include <net/ndisc.h> ··· 1739 1738 return 0; 1740 1739 } 1741 1740 1741 + static int addrconf_ifid_ieee1394(u8 *eui, struct net_device *dev) 1742 + { 1743 + union fwnet_hwaddr *ha; 1744 + 1745 + if (dev->addr_len != FWNET_ALEN) 1746 + return -1; 1747 + 1748 + ha = (union fwnet_hwaddr *)dev->dev_addr; 1749 + 1750 + memcpy(eui, &ha->uc.uniq_id, sizeof(ha->uc.uniq_id)); 1751 + eui[0] ^= 2; 1752 + return 0; 1753 + } 1754 + 1742 1755 static int addrconf_ifid_arcnet(u8 *eui, struct net_device *dev) 1743 1756 { 1744 1757 /* XXX: inherit EUI-64 from other interface -- yoshfuji */ ··· 1817 1802 return addrconf_ifid_gre(eui, dev); 1818 1803 case ARPHRD_IEEE802154: 1819 1804 return addrconf_ifid_eui64(eui, dev); 1805 + case ARPHRD_IEEE1394: 1806 + return addrconf_ifid_ieee1394(eui, dev); 1820 1807 } 1821 1808 return -1; 1822 1809 } ··· 2660 2643 (dev->type != ARPHRD_FDDI) && 2661 2644 (dev->type != ARPHRD_ARCNET) && 2662 2645 (dev->type != ARPHRD_INFINIBAND) && 2663 - (dev->type != ARPHRD_IEEE802154)) { 2646 + (dev->type != ARPHRD_IEEE802154) && 2647 + (dev->type != ARPHRD_IEEE1394)) { 2664 2648 /* Alas, we support only Ethernet autoconfiguration. */ 2665 2649 return; 2666 2650 }