diff options
Diffstat (limited to 'drivers/firewire/net.c')
-rw-r--r-- | drivers/firewire/net.c | 59 |
1 files changed, 39 insertions, 20 deletions
diff --git a/drivers/firewire/net.c b/drivers/firewire/net.c index 309311b1faae..15475892af0c 100644 --- a/drivers/firewire/net.c +++ b/drivers/firewire/net.c | |||
@@ -73,13 +73,13 @@ struct rfc2734_header { | |||
73 | 73 | ||
74 | #define fwnet_get_hdr_lf(h) (((h)->w0 & 0xc0000000) >> 30) | 74 | #define fwnet_get_hdr_lf(h) (((h)->w0 & 0xc0000000) >> 30) |
75 | #define fwnet_get_hdr_ether_type(h) (((h)->w0 & 0x0000ffff)) | 75 | #define fwnet_get_hdr_ether_type(h) (((h)->w0 & 0x0000ffff)) |
76 | #define fwnet_get_hdr_dg_size(h) (((h)->w0 & 0x0fff0000) >> 16) | 76 | #define fwnet_get_hdr_dg_size(h) ((((h)->w0 & 0x0fff0000) >> 16) + 1) |
77 | #define fwnet_get_hdr_fg_off(h) (((h)->w0 & 0x00000fff)) | 77 | #define fwnet_get_hdr_fg_off(h) (((h)->w0 & 0x00000fff)) |
78 | #define fwnet_get_hdr_dgl(h) (((h)->w1 & 0xffff0000) >> 16) | 78 | #define fwnet_get_hdr_dgl(h) (((h)->w1 & 0xffff0000) >> 16) |
79 | 79 | ||
80 | #define fwnet_set_hdr_lf(lf) ((lf) << 30) | 80 | #define fwnet_set_hdr_lf(lf) ((lf) << 30) |
81 | #define fwnet_set_hdr_ether_type(et) (et) | 81 | #define fwnet_set_hdr_ether_type(et) (et) |
82 | #define fwnet_set_hdr_dg_size(dgs) ((dgs) << 16) | 82 | #define fwnet_set_hdr_dg_size(dgs) (((dgs) - 1) << 16) |
83 | #define fwnet_set_hdr_fg_off(fgo) (fgo) | 83 | #define fwnet_set_hdr_fg_off(fgo) (fgo) |
84 | 84 | ||
85 | #define fwnet_set_hdr_dgl(dgl) ((dgl) << 16) | 85 | #define fwnet_set_hdr_dgl(dgl) ((dgl) << 16) |
@@ -578,6 +578,9 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len, | |||
578 | int retval; | 578 | int retval; |
579 | u16 ether_type; | 579 | u16 ether_type; |
580 | 580 | ||
581 | if (len <= RFC2374_UNFRAG_HDR_SIZE) | ||
582 | return 0; | ||
583 | |||
581 | hdr.w0 = be32_to_cpu(buf[0]); | 584 | hdr.w0 = be32_to_cpu(buf[0]); |
582 | lf = fwnet_get_hdr_lf(&hdr); | 585 | lf = fwnet_get_hdr_lf(&hdr); |
583 | if (lf == RFC2374_HDR_UNFRAG) { | 586 | if (lf == RFC2374_HDR_UNFRAG) { |
@@ -602,7 +605,12 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len, | |||
602 | return fwnet_finish_incoming_packet(net, skb, source_node_id, | 605 | return fwnet_finish_incoming_packet(net, skb, source_node_id, |
603 | is_broadcast, ether_type); | 606 | is_broadcast, ether_type); |
604 | } | 607 | } |
608 | |||
605 | /* A datagram fragment has been received, now the fun begins. */ | 609 | /* A datagram fragment has been received, now the fun begins. */ |
610 | |||
611 | if (len <= RFC2374_FRAG_HDR_SIZE) | ||
612 | return 0; | ||
613 | |||
606 | hdr.w1 = ntohl(buf[1]); | 614 | hdr.w1 = ntohl(buf[1]); |
607 | buf += 2; | 615 | buf += 2; |
608 | len -= RFC2374_FRAG_HDR_SIZE; | 616 | len -= RFC2374_FRAG_HDR_SIZE; |
@@ -614,7 +622,10 @@ static int fwnet_incoming_packet(struct fwnet_device *dev, __be32 *buf, int len, | |||
614 | fg_off = fwnet_get_hdr_fg_off(&hdr); | 622 | fg_off = fwnet_get_hdr_fg_off(&hdr); |
615 | } | 623 | } |
616 | datagram_label = fwnet_get_hdr_dgl(&hdr); | 624 | datagram_label = fwnet_get_hdr_dgl(&hdr); |
617 | dg_size = fwnet_get_hdr_dg_size(&hdr); /* ??? + 1 */ | 625 | dg_size = fwnet_get_hdr_dg_size(&hdr); |
626 | |||
627 | if (fg_off + len > dg_size) | ||
628 | return 0; | ||
618 | 629 | ||
619 | spin_lock_irqsave(&dev->lock, flags); | 630 | spin_lock_irqsave(&dev->lock, flags); |
620 | 631 | ||
@@ -722,6 +733,22 @@ static void fwnet_receive_packet(struct fw_card *card, struct fw_request *r, | |||
722 | fw_send_response(card, r, rcode); | 733 | fw_send_response(card, r, rcode); |
723 | } | 734 | } |
724 | 735 | ||
736 | static int gasp_source_id(__be32 *p) | ||
737 | { | ||
738 | return be32_to_cpu(p[0]) >> 16; | ||
739 | } | ||
740 | |||
741 | static u32 gasp_specifier_id(__be32 *p) | ||
742 | { | ||
743 | return (be32_to_cpu(p[0]) & 0xffff) << 8 | | ||
744 | (be32_to_cpu(p[1]) & 0xff000000) >> 24; | ||
745 | } | ||
746 | |||
747 | static u32 gasp_version(__be32 *p) | ||
748 | { | ||
749 | return be32_to_cpu(p[1]) & 0xffffff; | ||
750 | } | ||
751 | |||
725 | static void fwnet_receive_broadcast(struct fw_iso_context *context, | 752 | static void fwnet_receive_broadcast(struct fw_iso_context *context, |
726 | u32 cycle, size_t header_length, void *header, void *data) | 753 | u32 cycle, size_t header_length, void *header, void *data) |
727 | { | 754 | { |
@@ -731,9 +758,6 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context, | |||
731 | __be32 *buf_ptr; | 758 | __be32 *buf_ptr; |
732 | int retval; | 759 | int retval; |
733 | u32 length; | 760 | u32 length; |
734 | u16 source_node_id; | ||
735 | u32 specifier_id; | ||
736 | u32 ver; | ||
737 | unsigned long offset; | 761 | unsigned long offset; |
738 | unsigned long flags; | 762 | unsigned long flags; |
739 | 763 | ||
@@ -750,22 +774,17 @@ static void fwnet_receive_broadcast(struct fw_iso_context *context, | |||
750 | 774 | ||
751 | spin_unlock_irqrestore(&dev->lock, flags); | 775 | spin_unlock_irqrestore(&dev->lock, flags); |
752 | 776 | ||
753 | specifier_id = (be32_to_cpu(buf_ptr[0]) & 0xffff) << 8 | 777 | if (length > IEEE1394_GASP_HDR_SIZE && |
754 | | (be32_to_cpu(buf_ptr[1]) & 0xff000000) >> 24; | 778 | gasp_specifier_id(buf_ptr) == IANA_SPECIFIER_ID && |
755 | ver = be32_to_cpu(buf_ptr[1]) & 0xffffff; | 779 | (gasp_version(buf_ptr) == RFC2734_SW_VERSION |
756 | source_node_id = be32_to_cpu(buf_ptr[0]) >> 16; | ||
757 | |||
758 | if (specifier_id == IANA_SPECIFIER_ID && | ||
759 | (ver == RFC2734_SW_VERSION | ||
760 | #if IS_ENABLED(CONFIG_IPV6) | 780 | #if IS_ENABLED(CONFIG_IPV6) |
761 | || ver == RFC3146_SW_VERSION | 781 | || gasp_version(buf_ptr) == RFC3146_SW_VERSION |
762 | #endif | 782 | #endif |
763 | )) { | 783 | )) |
764 | buf_ptr += 2; | 784 | fwnet_incoming_packet(dev, buf_ptr + 2, |
765 | length -= IEEE1394_GASP_HDR_SIZE; | 785 | length - IEEE1394_GASP_HDR_SIZE, |
766 | fwnet_incoming_packet(dev, buf_ptr, length, source_node_id, | 786 | gasp_source_id(buf_ptr), |
767 | context->card->generation, true); | 787 | context->card->generation, true); |
768 | } | ||
769 | 788 | ||
770 | packet.payload_length = dev->rcv_buffer_size; | 789 | packet.payload_length = dev->rcv_buffer_size; |
771 | packet.interrupt = 1; | 790 | packet.interrupt = 1; |