diff options
Diffstat (limited to 'net/tipc/eth_media.c')
-rw-r--r-- | net/tipc/eth_media.c | 48 |
1 files changed, 30 insertions, 18 deletions
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c index 6230d16020c..6e988ba485f 100644 --- a/net/tipc/eth_media.c +++ b/net/tipc/eth_media.c | |||
@@ -72,17 +72,26 @@ static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr, | |||
72 | { | 72 | { |
73 | struct sk_buff *clone; | 73 | struct sk_buff *clone; |
74 | struct net_device *dev; | 74 | struct net_device *dev; |
75 | int delta; | ||
75 | 76 | ||
76 | clone = skb_clone(buf, GFP_ATOMIC); | 77 | clone = skb_clone(buf, GFP_ATOMIC); |
77 | if (clone) { | 78 | if (!clone) |
78 | skb_reset_network_header(clone); | 79 | return 0; |
79 | dev = ((struct eth_bearer *)(tb_ptr->usr_handle))->dev; | 80 | |
80 | clone->dev = dev; | 81 | dev = ((struct eth_bearer *)(tb_ptr->usr_handle))->dev; |
81 | dev_hard_header(clone, dev, ETH_P_TIPC, | 82 | delta = dev->hard_header_len - skb_headroom(buf); |
82 | &dest->dev_addr.eth_addr, | 83 | |
83 | dev->dev_addr, clone->len); | 84 | if ((delta > 0) && |
84 | dev_queue_xmit(clone); | 85 | pskb_expand_head(clone, SKB_DATA_ALIGN(delta), 0, GFP_ATOMIC)) { |
86 | kfree_skb(clone); | ||
87 | return 0; | ||
85 | } | 88 | } |
89 | |||
90 | skb_reset_network_header(clone); | ||
91 | clone->dev = dev; | ||
92 | dev_hard_header(clone, dev, ETH_P_TIPC, &dest->dev_addr.eth_addr, | ||
93 | dev->dev_addr, clone->len); | ||
94 | dev_queue_xmit(clone); | ||
86 | return 0; | 95 | return 0; |
87 | } | 96 | } |
88 | 97 | ||
@@ -92,15 +101,12 @@ static int send_msg(struct sk_buff *buf, struct tipc_bearer *tb_ptr, | |||
92 | * Accept only packets explicitly sent to this node, or broadcast packets; | 101 | * Accept only packets explicitly sent to this node, or broadcast packets; |
93 | * ignores packets sent using Ethernet multicast, and traffic sent to other | 102 | * ignores packets sent using Ethernet multicast, and traffic sent to other |
94 | * nodes (which can happen if interface is running in promiscuous mode). | 103 | * nodes (which can happen if interface is running in promiscuous mode). |
95 | * Routine truncates any Ethernet padding/CRC appended to the message, | ||
96 | * and ensures message size matches actual length | ||
97 | */ | 104 | */ |
98 | 105 | ||
99 | static int recv_msg(struct sk_buff *buf, struct net_device *dev, | 106 | static int recv_msg(struct sk_buff *buf, struct net_device *dev, |
100 | struct packet_type *pt, struct net_device *orig_dev) | 107 | struct packet_type *pt, struct net_device *orig_dev) |
101 | { | 108 | { |
102 | struct eth_bearer *eb_ptr = (struct eth_bearer *)pt->af_packet_priv; | 109 | struct eth_bearer *eb_ptr = (struct eth_bearer *)pt->af_packet_priv; |
103 | u32 size; | ||
104 | 110 | ||
105 | if (!net_eq(dev_net(dev), &init_net)) { | 111 | if (!net_eq(dev_net(dev), &init_net)) { |
106 | kfree_skb(buf); | 112 | kfree_skb(buf); |
@@ -109,13 +115,9 @@ static int recv_msg(struct sk_buff *buf, struct net_device *dev, | |||
109 | 115 | ||
110 | if (likely(eb_ptr->bearer)) { | 116 | if (likely(eb_ptr->bearer)) { |
111 | if (likely(buf->pkt_type <= PACKET_BROADCAST)) { | 117 | if (likely(buf->pkt_type <= PACKET_BROADCAST)) { |
112 | size = msg_size((struct tipc_msg *)buf->data); | 118 | buf->next = NULL; |
113 | skb_trim(buf, size); | 119 | tipc_recv_msg(buf, eb_ptr->bearer); |
114 | if (likely(buf->len == size)) { | 120 | return 0; |
115 | buf->next = NULL; | ||
116 | tipc_recv_msg(buf, eb_ptr->bearer); | ||
117 | return 0; | ||
118 | } | ||
119 | } | 121 | } |
120 | } | 122 | } |
121 | kfree_skb(buf); | 123 | kfree_skb(buf); |
@@ -133,6 +135,16 @@ static int enable_bearer(struct tipc_bearer *tb_ptr) | |||
133 | struct eth_bearer *eb_ptr = ð_bearers[0]; | 135 | struct eth_bearer *eb_ptr = ð_bearers[0]; |
134 | struct eth_bearer *stop = ð_bearers[MAX_ETH_BEARERS]; | 136 | struct eth_bearer *stop = ð_bearers[MAX_ETH_BEARERS]; |
135 | char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1; | 137 | char *driver_name = strchr((const char *)tb_ptr->name, ':') + 1; |
138 | int pending_dev = 0; | ||
139 | |||
140 | /* Find unused Ethernet bearer structure */ | ||
141 | |||
142 | while (eb_ptr->dev) { | ||
143 | if (!eb_ptr->bearer) | ||
144 | pending_dev++; | ||
145 | if (++eb_ptr == stop) | ||
146 | return pending_dev ? -EAGAIN : -EDQUOT; | ||
147 | } | ||
136 | 148 | ||
137 | /* Find device with specified name */ | 149 | /* Find device with specified name */ |
138 | 150 | ||