summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYOSHIFUJI Hideaki / 吉藤英明 <yoshfuji@linux-ipv6.org>2013-03-25 04:26:16 -0400
committerDavid S. Miller <davem@davemloft.net>2013-03-26 12:32:13 -0400
commit6752c8db8e0cfedb44ba62806dd15b383ed64000 (patch)
tree96272aed0ff52f72a1d97d8a8d86d90f5f47809e
parent61a7839a19c157d11930fe69697a4c90884bf7c4 (diff)
firewire net, ipv4 arp: Extend hardware address and remove driver-level packet inspection.
Inspection of upper layer protocol is considered harmful, especially if it is about ARP or other stateful upper layer protocol; driver cannot (and should not) have full state of them. IPv4 over Firewire module used to inspect ARP (both in sending path and in receiving path), and record peer's GUID, max packet size, max speed and fifo address. This patch removes such inspection by extending our "hardware address" definition to include other information as well: max packet size, max speed and fifo. By doing this, The neighbour module in networking subsystem can cache them. Note: As we have started ignoring sspd and max_rec in ARP/NDP, those information will not be used in the driver when sending. When a packet is being sent, the IP layer fills our pseudo header with the extended "hardware address", including GUID and fifo. The driver can look-up node-id (the real but rather volatile low-level address) by GUID, and then the module can send the packet to the wire using parameters provided in the extendedn hardware address. This approach is realistic because IP over IEEE1394 (RFC2734) and IPv6 over IEEE1394 (RFC3146) share same "hardware address" format in their address resolution protocols. Here, extended "hardware address" is defined as follows: union fwnet_hwaddr { u8 u[16]; struct { __be64 uniq_id; /* EUI-64 */ u8 max_rec; /* max packet size */ u8 sspd; /* max speed */ __be16 fifo_hi; /* hi 16bits of FIFO addr */ __be32 fifo_lo; /* lo 32bits of FIFO addr */ } __packed uc; }; Note that Hardware address is declared as union, so that we can map full IP address into this, when implementing MCAP (Multicast Cannel Allocation Protocol) for IPv6, but IP and ARP subsystem do not need to know this format in detail. One difference between original ARP (RFC826) and 1394 ARP (RFC2734) is that 1394 ARP Request/Reply do not contain the target hardware address field (aka ar$tha). This difference is handled in the ARP subsystem. CC: Stephan Gatzka <stephan.gatzka@gmail.com> Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/firewire/net.c153
-rw-r--r--include/linux/if_arp.h12
-rw-r--r--include/net/firewire.h25
-rw-r--r--net/ipv4/arp.c27
4 files changed, 82 insertions, 135 deletions
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c
index cb8aa865ff88..790017eb5051 100644
--- a/drivers/firewire/net.c
+++ b/drivers/firewire/net.c
@@ -28,6 +28,7 @@
28 28
29#include <asm/unaligned.h> 29#include <asm/unaligned.h>
30#include <net/arp.h> 30#include <net/arp.h>
31#include <net/firewire.h>
31 32
32/* rx limits */ 33/* rx limits */
33#define FWNET_MAX_FRAGMENTS 30 /* arbitrary, > TX queue depth */ 34#define FWNET_MAX_FRAGMENTS 30 /* arbitrary, > TX queue depth */
@@ -57,33 +58,6 @@
57#define RFC2374_HDR_LASTFRAG 2 /* last fragment */ 58#define RFC2374_HDR_LASTFRAG 2 /* last fragment */
58#define RFC2374_HDR_INTFRAG 3 /* interior fragment */ 59#define RFC2374_HDR_INTFRAG 3 /* interior fragment */
59 60
60#define RFC2734_HW_ADDR_LEN 16
61
62struct rfc2734_arp {
63 __be16 hw_type; /* 0x0018 */
64 __be16 proto_type; /* 0x0806 */
65 u8 hw_addr_len; /* 16 */
66 u8 ip_addr_len; /* 4 */
67 __be16 opcode; /* ARP Opcode */
68 /* Above is exactly the same format as struct arphdr */
69
70 __be64 s_uniq_id; /* Sender's 64bit EUI */
71 u8 max_rec; /* Sender's max packet size */
72 u8 sspd; /* Sender's max speed */
73 __be16 fifo_hi; /* hi 16bits of sender's FIFO addr */
74 __be32 fifo_lo; /* lo 32bits of sender's FIFO addr */
75 __be32 sip; /* Sender's IP Address */
76 __be32 tip; /* IP Address of requested hw addr */
77} __packed;
78
79/* This header format is specific to this driver implementation. */
80#define FWNET_ALEN 8
81#define FWNET_HLEN 10
82struct fwnet_header {
83 u8 h_dest[FWNET_ALEN]; /* destination address */
84 __be16 h_proto; /* packet type ID field */
85} __packed;
86
87static bool fwnet_hwaddr_is_multicast(u8 *ha) 61static bool fwnet_hwaddr_is_multicast(u8 *ha)
88{ 62{
89 return !!(*ha & 1); 63 return !!(*ha & 1);
@@ -196,8 +170,6 @@ struct fwnet_peer {
196 struct list_head peer_link; 170 struct list_head peer_link;
197 struct fwnet_device *dev; 171 struct fwnet_device *dev;
198 u64 guid; 172 u64 guid;
199 u64 fifo;
200 __be32 ip;
201 173
202 /* guarded by dev->lock */ 174 /* guarded by dev->lock */
203 struct list_head pd_list; /* received partial datagrams */ 175 struct list_head pd_list; /* received partial datagrams */
@@ -227,6 +199,15 @@ struct fwnet_packet_task {
227}; 199};
228 200
229/* 201/*
202 * Get fifo address embedded in hwaddr
203 */
204static __u64 fwnet_hwaddr_fifo(union fwnet_hwaddr *ha)
205{
206 return (u64)get_unaligned_be16(&ha->uc.fifo_hi) << 32
207 | get_unaligned_be32(&ha->uc.fifo_lo);
208}
209
210/*
230 * saddr == NULL means use device source address. 211 * saddr == NULL means use device source address.
231 * daddr == NULL means leave destination address (eg unresolved arp). 212 * daddr == NULL means leave destination address (eg unresolved arp).
232 */ 213 */
@@ -518,7 +499,6 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
518 bool is_broadcast, u16 ether_type) 499 bool is_broadcast, u16 ether_type)
519{ 500{
520 struct fwnet_device *dev; 501 struct fwnet_device *dev;
521 static const __be64 broadcast_hw = cpu_to_be64(~0ULL);
522 int status; 502 int status;
523 __be64 guid; 503 __be64 guid;
524 504
@@ -537,76 +517,11 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
537 517
538 /* 518 /*
539 * Parse the encapsulation header. This actually does the job of 519 * Parse the encapsulation header. This actually does the job of
540 * converting to an ethernet frame header, as well as arp 520 * converting to an ethernet-like pseudo frame header.
541 * conversion if needed. ARP conversion is easier in this
542 * direction, since we are using ethernet as our backend.
543 */
544 /*
545 * If this is an ARP packet, convert it. First, we want to make
546 * use of some of the fields, since they tell us a little bit
547 * about the sending machine.
548 */ 521 */
549 if (ether_type == ETH_P_ARP) {
550 struct rfc2734_arp *arp1394;
551 struct arphdr *arp;
552 unsigned char *arp_ptr;
553 u64 fifo_addr;
554 u64 peer_guid;
555 struct fwnet_peer *peer;
556 unsigned long flags;
557
558 arp1394 = (struct rfc2734_arp *)skb->data;
559 arp = (struct arphdr *)skb->data;
560 arp_ptr = (unsigned char *)(arp + 1);
561 peer_guid = get_unaligned_be64(&arp1394->s_uniq_id);
562 fifo_addr = (u64)get_unaligned_be16(&arp1394->fifo_hi) << 32
563 | get_unaligned_be32(&arp1394->fifo_lo);
564
565 spin_lock_irqsave(&dev->lock, flags);
566 peer = fwnet_peer_find_by_guid(dev, peer_guid);
567 if (peer) {
568 peer->fifo = fifo_addr;
569 peer->ip = arp1394->sip;
570 }
571 spin_unlock_irqrestore(&dev->lock, flags);
572
573 if (!peer) {
574 dev_notice(&net->dev,
575 "no peer for ARP packet from %016llx\n",
576 (unsigned long long)peer_guid);
577 goto no_peer;
578 }
579
580 /*
581 * Now that we're done with the 1394 specific stuff, we'll
582 * need to alter some of the data. Believe it or not, all
583 * that needs to be done is sender_IP_address needs to be
584 * moved, the destination hardware address get stuffed
585 * in and the hardware address length set to 8.
586 *
587 * IMPORTANT: The code below overwrites 1394 specific data
588 * needed above so keep the munging of the data for the
589 * higher level IP stack last.
590 */
591
592 arp->ar_hln = 8;
593 /* skip over sender unique id */
594 arp_ptr += arp->ar_hln;
595 /* move sender IP addr */
596 put_unaligned(arp1394->sip, (u32 *)arp_ptr);
597 /* skip over sender IP addr */
598 arp_ptr += arp->ar_pln;
599
600 if (arp->ar_op == htons(ARPOP_REQUEST))
601 memset(arp_ptr, 0, sizeof(u64));
602 else
603 memcpy(arp_ptr, net->dev_addr, sizeof(u64));
604 }
605
606 /* Now add the ethernet header. */
607 guid = cpu_to_be64(dev->card->guid); 522 guid = cpu_to_be64(dev->card->guid);
608 if (dev_hard_header(skb, net, ether_type, 523 if (dev_hard_header(skb, net, ether_type,
609 is_broadcast ? &broadcast_hw : &guid, 524 is_broadcast ? net->broadcast : net->dev_addr,
610 NULL, skb->len) >= 0) { 525 NULL, skb->len) >= 0) {
611 struct fwnet_header *eth; 526 struct fwnet_header *eth;
612 u16 *rawp; 527 u16 *rawp;
@@ -649,7 +564,6 @@ static int fwnet_finish_incoming_packet(struct net_device *net,
649 564
650 return 0; 565 return 0;
651 566
652 no_peer:
653 err: 567 err:
654 net->stats.rx_errors++; 568 net->stats.rx_errors++;
655 net->stats.rx_dropped++; 569 net->stats.rx_dropped++;
@@ -1355,11 +1269,12 @@ static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net)
1355 ptask->dest_node = IEEE1394_ALL_NODES; 1269 ptask->dest_node = IEEE1394_ALL_NODES;
1356 ptask->speed = SCODE_100; 1270 ptask->speed = SCODE_100;
1357 } else { 1271 } else {
1358 __be64 guid = get_unaligned((__be64 *)hdr_buf.h_dest); 1272 union fwnet_hwaddr *ha = (union fwnet_hwaddr *)hdr_buf.h_dest;
1273 __be64 guid = get_unaligned(&ha->uc.uniq_id);
1359 u8 generation; 1274 u8 generation;
1360 1275
1361 peer = fwnet_peer_find_by_guid(dev, be64_to_cpu(guid)); 1276 peer = fwnet_peer_find_by_guid(dev, be64_to_cpu(guid));
1362 if (!peer || peer->fifo == FWNET_NO_FIFO_ADDR) 1277 if (!peer)
1363 goto fail; 1278 goto fail;
1364 1279
1365 generation = peer->generation; 1280 generation = peer->generation;
@@ -1367,32 +1282,12 @@ static netdev_tx_t fwnet_tx(struct sk_buff *skb, struct net_device *net)
1367 max_payload = peer->max_payload; 1282 max_payload = peer->max_payload;
1368 datagram_label_ptr = &peer->datagram_label; 1283 datagram_label_ptr = &peer->datagram_label;
1369 1284
1370 ptask->fifo_addr = peer->fifo; 1285 ptask->fifo_addr = fwnet_hwaddr_fifo(ha);
1371 ptask->generation = generation; 1286 ptask->generation = generation;
1372 ptask->dest_node = dest_node; 1287 ptask->dest_node = dest_node;
1373 ptask->speed = peer->speed; 1288 ptask->speed = peer->speed;
1374 } 1289 }
1375 1290
1376 /* If this is an ARP packet, convert it */
1377 if (proto == htons(ETH_P_ARP)) {
1378 struct arphdr *arp = (struct arphdr *)skb->data;
1379 unsigned char *arp_ptr = (unsigned char *)(arp + 1);
1380 struct rfc2734_arp *arp1394 = (struct rfc2734_arp *)skb->data;
1381 __be32 ipaddr;
1382
1383 ipaddr = get_unaligned((__be32 *)(arp_ptr + FWNET_ALEN));
1384
1385 arp1394->hw_addr_len = RFC2734_HW_ADDR_LEN;
1386 arp1394->max_rec = dev->card->max_receive;
1387 arp1394->sspd = dev->card->link_speed;
1388
1389 put_unaligned_be16(dev->local_fifo >> 32,
1390 &arp1394->fifo_hi);
1391 put_unaligned_be32(dev->local_fifo & 0xffffffff,
1392 &arp1394->fifo_lo);
1393 put_unaligned(ipaddr, &arp1394->sip);
1394 }
1395
1396 ptask->hdr.w0 = 0; 1291 ptask->hdr.w0 = 0;
1397 ptask->hdr.w1 = 0; 1292 ptask->hdr.w1 = 0;
1398 ptask->skb = skb; 1293 ptask->skb = skb;
@@ -1507,8 +1402,6 @@ static int fwnet_add_peer(struct fwnet_device *dev,
1507 1402
1508 peer->dev = dev; 1403 peer->dev = dev;
1509 peer->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4]; 1404 peer->guid = (u64)device->config_rom[3] << 32 | device->config_rom[4];
1510 peer->fifo = FWNET_NO_FIFO_ADDR;
1511 peer->ip = 0;
1512 INIT_LIST_HEAD(&peer->pd_list); 1405 INIT_LIST_HEAD(&peer->pd_list);
1513 peer->pdg_size = 0; 1406 peer->pdg_size = 0;
1514 peer->datagram_label = 0; 1407 peer->datagram_label = 0;
@@ -1538,6 +1431,7 @@ static int fwnet_probe(struct device *_dev)
1538 struct fwnet_device *dev; 1431 struct fwnet_device *dev;
1539 unsigned max_mtu; 1432 unsigned max_mtu;
1540 int ret; 1433 int ret;
1434 union fwnet_hwaddr *ha;
1541 1435
1542 mutex_lock(&fwnet_device_mutex); 1436 mutex_lock(&fwnet_device_mutex);
1543 1437
@@ -1582,8 +1476,15 @@ static int fwnet_probe(struct device *_dev)
1582 net->mtu = min(1500U, max_mtu); 1476 net->mtu = min(1500U, max_mtu);
1583 1477
1584 /* Set our hardware address while we're at it */ 1478 /* Set our hardware address while we're at it */
1585 put_unaligned_be64(card->guid, net->dev_addr); 1479 ha = (union fwnet_hwaddr *)net->dev_addr;
1586 put_unaligned_be64(~0ULL, net->broadcast); 1480 put_unaligned_be64(card->guid, &ha->uc.uniq_id);
1481 ha->uc.max_rec = dev->card->max_receive;
1482 ha->uc.sspd = dev->card->link_speed;
1483 put_unaligned_be16(dev->local_fifo >> 32, &ha->uc.fifo_hi);
1484 put_unaligned_be32(dev->local_fifo & 0xffffffff, &ha->uc.fifo_lo);
1485
1486 memset(net->broadcast, -1, net->addr_len);
1487
1587 ret = register_netdev(net); 1488 ret = register_netdev(net);
1588 if (ret) 1489 if (ret)
1589 goto out; 1490 goto out;
@@ -1632,8 +1533,6 @@ static int fwnet_remove(struct device *_dev)
1632 mutex_lock(&fwnet_device_mutex); 1533 mutex_lock(&fwnet_device_mutex);
1633 1534
1634 net = dev->netdev; 1535 net = dev->netdev;
1635 if (net && peer->ip)
1636 arp_invalidate(net, peer->ip);
1637 1536
1638 fwnet_remove_peer(peer, dev); 1537 fwnet_remove_peer(peer, dev);
1639 1538
diff --git a/include/linux/if_arp.h b/include/linux/if_arp.h
index 89b4614a4722..f563907ed776 100644
--- a/include/linux/if_arp.h
+++ b/include/linux/if_arp.h
@@ -33,7 +33,15 @@ static inline struct arphdr *arp_hdr(const struct sk_buff *skb)
33 33
34static inline int arp_hdr_len(struct net_device *dev) 34static inline int arp_hdr_len(struct net_device *dev)
35{ 35{
36 /* ARP header, plus 2 device addresses, plus 2 IP addresses. */ 36 switch (dev->type) {
37 return sizeof(struct arphdr) + (dev->addr_len + sizeof(u32)) * 2; 37#if IS_ENABLED(CONFIG_FIREWIRE_NET)
38 case ARPHRD_IEEE1394:
39 /* ARP header, device address and 2 IP addresses */
40 return sizeof(struct arphdr) + dev->addr_len + sizeof(u32) * 2;
41#endif
42 default:
43 /* ARP header, plus 2 device addresses, plus 2 IP addresses. */
44 return sizeof(struct arphdr) + (dev->addr_len + sizeof(u32)) * 2;
45 }
38} 46}
39#endif /* _LINUX_IF_ARP_H */ 47#endif /* _LINUX_IF_ARP_H */
diff --git a/include/net/firewire.h b/include/net/firewire.h
new file mode 100644
index 000000000000..31bcbfe7a220
--- /dev/null
+++ b/include/net/firewire.h
@@ -0,0 +1,25 @@
1#ifndef _NET_FIREWIRE_H
2#define _NET_FIREWIRE_H
3
4/* Pseudo L2 address */
5#define FWNET_ALEN 16
6union fwnet_hwaddr {
7 u8 u[FWNET_ALEN];
8 /* "Hardware address" defined in RFC2734/RF3146 */
9 struct {
10 __be64 uniq_id; /* EUI-64 */
11 u8 max_rec; /* max packet size */
12 u8 sspd; /* max speed */
13 __be16 fifo_hi; /* hi 16bits of FIFO addr */
14 __be32 fifo_lo; /* lo 32bits of FIFO addr */
15 } __packed uc;
16};
17
18/* Pseudo L2 Header */
19#define FWNET_HLEN 18
20struct fwnet_header {
21 u8 h_dest[FWNET_ALEN]; /* destination address */
22 __be16 h_proto; /* packet type ID field */
23} __packed;
24
25#endif
diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c
index fea4929f6200..247ec1951c35 100644
--- a/net/ipv4/arp.c
+++ b/net/ipv4/arp.c
@@ -654,11 +654,19 @@ struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip,
654 arp_ptr += dev->addr_len; 654 arp_ptr += dev->addr_len;
655 memcpy(arp_ptr, &src_ip, 4); 655 memcpy(arp_ptr, &src_ip, 4);
656 arp_ptr += 4; 656 arp_ptr += 4;
657 if (target_hw != NULL) 657
658 memcpy(arp_ptr, target_hw, dev->addr_len); 658 switch (dev->type) {
659 else 659#if IS_ENABLED(CONFIG_FIREWIRE_NET)
660 memset(arp_ptr, 0, dev->addr_len); 660 case ARPHRD_IEEE1394:
661 arp_ptr += dev->addr_len; 661 break;
662#endif
663 default:
664 if (target_hw != NULL)
665 memcpy(arp_ptr, target_hw, dev->addr_len);
666 else
667 memset(arp_ptr, 0, dev->addr_len);
668 arp_ptr += dev->addr_len;
669 }
662 memcpy(arp_ptr, &dest_ip, 4); 670 memcpy(arp_ptr, &dest_ip, 4);
663 671
664 return skb; 672 return skb;
@@ -781,7 +789,14 @@ static int arp_process(struct sk_buff *skb)
781 arp_ptr += dev->addr_len; 789 arp_ptr += dev->addr_len;
782 memcpy(&sip, arp_ptr, 4); 790 memcpy(&sip, arp_ptr, 4);
783 arp_ptr += 4; 791 arp_ptr += 4;
784 arp_ptr += dev->addr_len; 792 switch (dev_type) {
793#if IS_ENABLED(CONFIG_FIREWIRE_NET)
794 case ARPHRD_IEEE1394:
795 break;
796#endif
797 default:
798 arp_ptr += dev->addr_len;
799 }
785 memcpy(&tip, arp_ptr, 4); 800 memcpy(&tip, arp_ptr, 4);
786/* 801/*
787 * Check for bad requests for 127.x.x.x and requests for multicast 802 * Check for bad requests for 127.x.x.x and requests for multicast