diff options
-rw-r--r-- | drivers/firewire/net.c | 153 | ||||
-rw-r--r-- | include/linux/if_arp.h | 12 | ||||
-rw-r--r-- | include/net/firewire.h | 25 | ||||
-rw-r--r-- | net/ipv4/arp.c | 27 |
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 | |||
62 | struct 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 | ||
82 | struct fwnet_header { | ||
83 | u8 h_dest[FWNET_ALEN]; /* destination address */ | ||
84 | __be16 h_proto; /* packet type ID field */ | ||
85 | } __packed; | ||
86 | |||
87 | static bool fwnet_hwaddr_is_multicast(u8 *ha) | 61 | static 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 | */ | ||
204 | static __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 | ||
34 | static inline int arp_hdr_len(struct net_device *dev) | 34 | static 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 | ||
6 | union 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 | ||
20 | struct 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 |