diff options
Diffstat (limited to 'net/ethernet/eth.c')
-rw-r--r-- | net/ethernet/eth.c | 196 |
1 files changed, 115 insertions, 81 deletions
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index 387c71c584ee..43863933f27f 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c | |||
@@ -64,81 +64,79 @@ | |||
64 | 64 | ||
65 | __setup("ether=", netdev_boot_setup); | 65 | __setup("ether=", netdev_boot_setup); |
66 | 66 | ||
67 | /* | 67 | /** |
68 | * Create the Ethernet MAC header for an arbitrary protocol layer | 68 | * eth_header - create the Ethernet header |
69 | * @skb: buffer to alter | ||
70 | * @dev: source device | ||
71 | * @type: Ethernet type field | ||
72 | * @daddr: destination address (NULL leave destination address) | ||
73 | * @saddr: source address (NULL use device source address) | ||
74 | * @len: packet length (<= skb->len) | ||
69 | * | 75 | * |
70 | * saddr=NULL means use device source address | 76 | * |
71 | * daddr=NULL means leave destination address (eg unresolved arp) | 77 | * Set the protocol type. For a packet of type ETH_P_802_3 we put the length |
78 | * in here instead. It is up to the 802.2 layer to carry protocol information. | ||
72 | */ | 79 | */ |
73 | |||
74 | int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, | 80 | int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type, |
75 | void *daddr, void *saddr, unsigned len) | 81 | void *daddr, void *saddr, unsigned len) |
76 | { | 82 | { |
77 | struct ethhdr *eth = (struct ethhdr *)skb_push(skb,ETH_HLEN); | 83 | struct ethhdr *eth = (struct ethhdr *)skb_push(skb, ETH_HLEN); |
78 | 84 | ||
79 | /* | 85 | if (type != ETH_P_802_3) |
80 | * Set the protocol type. For a packet of type ETH_P_802_3 we put the length | ||
81 | * in here instead. It is up to the 802.2 layer to carry protocol information. | ||
82 | */ | ||
83 | |||
84 | if(type!=ETH_P_802_3) | ||
85 | eth->h_proto = htons(type); | 86 | eth->h_proto = htons(type); |
86 | else | 87 | else |
87 | eth->h_proto = htons(len); | 88 | eth->h_proto = htons(len); |
88 | 89 | ||
89 | /* | 90 | /* |
90 | * Set the source hardware address. | 91 | * Set the source hardware address. |
91 | */ | 92 | */ |
92 | 93 | ||
93 | if(!saddr) | 94 | if (!saddr) |
94 | saddr = dev->dev_addr; | 95 | saddr = dev->dev_addr; |
95 | memcpy(eth->h_source,saddr,dev->addr_len); | 96 | memcpy(eth->h_source, saddr, dev->addr_len); |
96 | 97 | ||
97 | if(daddr) | 98 | if (daddr) { |
98 | { | 99 | memcpy(eth->h_dest, daddr, dev->addr_len); |
99 | memcpy(eth->h_dest,daddr,dev->addr_len); | ||
100 | return ETH_HLEN; | 100 | return ETH_HLEN; |
101 | } | 101 | } |
102 | 102 | ||
103 | /* | 103 | /* |
104 | * Anyway, the loopback-device should never use this function... | 104 | * Anyway, the loopback-device should never use this function... |
105 | */ | 105 | */ |
106 | 106 | ||
107 | if (dev->flags & (IFF_LOOPBACK|IFF_NOARP)) | 107 | if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) { |
108 | { | ||
109 | memset(eth->h_dest, 0, dev->addr_len); | 108 | memset(eth->h_dest, 0, dev->addr_len); |
110 | return ETH_HLEN; | 109 | return ETH_HLEN; |
111 | } | 110 | } |
112 | 111 | ||
113 | return -ETH_HLEN; | 112 | return -ETH_HLEN; |
114 | } | 113 | } |
115 | 114 | ||
116 | 115 | /** | |
117 | /* | 116 | * eth_rebuild_header- rebuild the Ethernet MAC header. |
118 | * Rebuild the Ethernet MAC header. This is called after an ARP | 117 | * @skb: socket buffer to update |
119 | * (or in future other address resolution) has completed on this | ||
120 | * sk_buff. We now let ARP fill in the other fields. | ||
121 | * | 118 | * |
122 | * This routine CANNOT use cached dst->neigh! | 119 | * This is called after an ARP or IPV6 ndisc it's resolution on this |
123 | * Really, it is used only when dst->neigh is wrong. | 120 | * sk_buff. We now let protocol (ARP) fill in the other fields. |
121 | * | ||
122 | * This routine CANNOT use cached dst->neigh! | ||
123 | * Really, it is used only when dst->neigh is wrong. | ||
124 | */ | 124 | */ |
125 | |||
126 | int eth_rebuild_header(struct sk_buff *skb) | 125 | int eth_rebuild_header(struct sk_buff *skb) |
127 | { | 126 | { |
128 | struct ethhdr *eth = (struct ethhdr *)skb->data; | 127 | struct ethhdr *eth = (struct ethhdr *)skb->data; |
129 | struct net_device *dev = skb->dev; | 128 | struct net_device *dev = skb->dev; |
130 | 129 | ||
131 | switch (eth->h_proto) | 130 | switch (eth->h_proto) { |
132 | { | ||
133 | #ifdef CONFIG_INET | 131 | #ifdef CONFIG_INET |
134 | case __constant_htons(ETH_P_IP): | 132 | case __constant_htons(ETH_P_IP): |
135 | return arp_find(eth->h_dest, skb); | 133 | return arp_find(eth->h_dest, skb); |
136 | #endif | 134 | #endif |
137 | default: | 135 | default: |
138 | printk(KERN_DEBUG | 136 | printk(KERN_DEBUG |
139 | "%s: unable to resolve type %X addresses.\n", | 137 | "%s: unable to resolve type %X addresses.\n", |
140 | dev->name, (int)eth->h_proto); | 138 | dev->name, (int)eth->h_proto); |
141 | 139 | ||
142 | memcpy(eth->h_source, dev->dev_addr, dev->addr_len); | 140 | memcpy(eth->h_source, dev->dev_addr, dev->addr_len); |
143 | break; | 141 | break; |
144 | } | 142 | } |
@@ -146,62 +144,70 @@ int eth_rebuild_header(struct sk_buff *skb) | |||
146 | return 0; | 144 | return 0; |
147 | } | 145 | } |
148 | 146 | ||
149 | 147 | /** | |
150 | /* | 148 | * eth_type_trans - determine the packet's protocol ID. |
151 | * Determine the packet's protocol ID. The rule here is that we | 149 | * @skb: received socket data |
152 | * assume 802.3 if the type field is short enough to be a length. | 150 | * @dev: receiving network device |
153 | * This is normal practice and works for any 'now in use' protocol. | 151 | * |
152 | * The rule here is that we | ||
153 | * assume 802.3 if the type field is short enough to be a length. | ||
154 | * This is normal practice and works for any 'now in use' protocol. | ||
154 | */ | 155 | */ |
155 | |||
156 | __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev) | 156 | __be16 eth_type_trans(struct sk_buff *skb, struct net_device *dev) |
157 | { | 157 | { |
158 | struct ethhdr *eth; | 158 | struct ethhdr *eth; |
159 | unsigned char *rawp; | 159 | unsigned char *rawp; |
160 | 160 | ||
161 | skb->mac.raw = skb->data; | 161 | skb->mac.raw = skb->data; |
162 | skb_pull(skb,ETH_HLEN); | 162 | skb_pull(skb, ETH_HLEN); |
163 | eth = eth_hdr(skb); | 163 | eth = eth_hdr(skb); |
164 | 164 | ||
165 | if (is_multicast_ether_addr(eth->h_dest)) { | 165 | if (is_multicast_ether_addr(eth->h_dest)) { |
166 | if (!compare_ether_addr(eth->h_dest, dev->broadcast)) | 166 | if (!compare_ether_addr(eth->h_dest, dev->broadcast)) |
167 | skb->pkt_type = PACKET_BROADCAST; | 167 | skb->pkt_type = PACKET_BROADCAST; |
168 | else | 168 | else |
169 | skb->pkt_type = PACKET_MULTICAST; | 169 | skb->pkt_type = PACKET_MULTICAST; |
170 | } | 170 | } |
171 | 171 | ||
172 | /* | 172 | /* |
173 | * This ALLMULTI check should be redundant by 1.4 | 173 | * This ALLMULTI check should be redundant by 1.4 |
174 | * so don't forget to remove it. | 174 | * so don't forget to remove it. |
175 | * | 175 | * |
176 | * Seems, you forgot to remove it. All silly devices | 176 | * Seems, you forgot to remove it. All silly devices |
177 | * seems to set IFF_PROMISC. | 177 | * seems to set IFF_PROMISC. |
178 | */ | 178 | */ |
179 | 179 | ||
180 | else if(1 /*dev->flags&IFF_PROMISC*/) { | 180 | else if (1 /*dev->flags&IFF_PROMISC */ ) { |
181 | if (unlikely(compare_ether_addr(eth->h_dest, dev->dev_addr))) | 181 | if (unlikely(compare_ether_addr(eth->h_dest, dev->dev_addr))) |
182 | skb->pkt_type = PACKET_OTHERHOST; | 182 | skb->pkt_type = PACKET_OTHERHOST; |
183 | } | 183 | } |
184 | 184 | ||
185 | if (ntohs(eth->h_proto) >= 1536) | 185 | if (ntohs(eth->h_proto) >= 1536) |
186 | return eth->h_proto; | 186 | return eth->h_proto; |
187 | 187 | ||
188 | rawp = skb->data; | 188 | rawp = skb->data; |
189 | 189 | ||
190 | /* | 190 | /* |
191 | * This is a magic hack to spot IPX packets. Older Novell breaks | 191 | * This is a magic hack to spot IPX packets. Older Novell breaks |
192 | * the protocol design and runs IPX over 802.3 without an 802.2 LLC | 192 | * the protocol design and runs IPX over 802.3 without an 802.2 LLC |
193 | * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This | 193 | * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This |
194 | * won't work for fault tolerant netware but does for the rest. | 194 | * won't work for fault tolerant netware but does for the rest. |
195 | */ | 195 | */ |
196 | if (*(unsigned short *)rawp == 0xFFFF) | 196 | if (*(unsigned short *)rawp == 0xFFFF) |
197 | return htons(ETH_P_802_3); | 197 | return htons(ETH_P_802_3); |
198 | 198 | ||
199 | /* | 199 | /* |
200 | * Real 802.2 LLC | 200 | * Real 802.2 LLC |
201 | */ | 201 | */ |
202 | return htons(ETH_P_802_2); | 202 | return htons(ETH_P_802_2); |
203 | } | 203 | } |
204 | EXPORT_SYMBOL(eth_type_trans); | ||
204 | 205 | ||
206 | /** | ||
207 | * eth_header_parse - extract hardware address from packet | ||
208 | * @skb: packet to extract header from | ||
209 | * @haddr: destination buffer | ||
210 | */ | ||
205 | static int eth_header_parse(struct sk_buff *skb, unsigned char *haddr) | 211 | static int eth_header_parse(struct sk_buff *skb, unsigned char *haddr) |
206 | { | 212 | { |
207 | struct ethhdr *eth = eth_hdr(skb); | 213 | struct ethhdr *eth = eth_hdr(skb); |
@@ -209,14 +215,20 @@ static int eth_header_parse(struct sk_buff *skb, unsigned char *haddr) | |||
209 | return ETH_ALEN; | 215 | return ETH_ALEN; |
210 | } | 216 | } |
211 | 217 | ||
218 | /** | ||
219 | * eth_header_cache - fill cache entry from neighbour | ||
220 | * @neigh: source neighbour | ||
221 | * @hh: destination cache entry | ||
222 | * Create an Ethernet header template from the neighbour. | ||
223 | */ | ||
212 | int eth_header_cache(struct neighbour *neigh, struct hh_cache *hh) | 224 | int eth_header_cache(struct neighbour *neigh, struct hh_cache *hh) |
213 | { | 225 | { |
214 | unsigned short type = hh->hh_type; | 226 | unsigned short type = hh->hh_type; |
215 | struct ethhdr *eth; | 227 | struct ethhdr *eth; |
216 | struct net_device *dev = neigh->dev; | 228 | struct net_device *dev = neigh->dev; |
217 | 229 | ||
218 | eth = (struct ethhdr*) | 230 | eth = (struct ethhdr *) |
219 | (((u8*)hh->hh_data) + (HH_DATA_OFF(sizeof(*eth)))); | 231 | (((u8 *) hh->hh_data) + (HH_DATA_OFF(sizeof(*eth)))); |
220 | 232 | ||
221 | if (type == __constant_htons(ETH_P_802_3)) | 233 | if (type == __constant_htons(ETH_P_802_3)) |
222 | return -1; | 234 | return -1; |
@@ -228,27 +240,47 @@ int eth_header_cache(struct neighbour *neigh, struct hh_cache *hh) | |||
228 | return 0; | 240 | return 0; |
229 | } | 241 | } |
230 | 242 | ||
231 | /* | 243 | /** |
244 | * eth_header_cache_update - update cache entry | ||
245 | * @hh: destination cache entry | ||
246 | * @dev: network device | ||
247 | * @haddr: new hardware address | ||
248 | * | ||
232 | * Called by Address Resolution module to notify changes in address. | 249 | * Called by Address Resolution module to notify changes in address. |
233 | */ | 250 | */ |
234 | 251 | void eth_header_cache_update(struct hh_cache *hh, struct net_device *dev, | |
235 | void eth_header_cache_update(struct hh_cache *hh, struct net_device *dev, unsigned char * haddr) | 252 | unsigned char *haddr) |
236 | { | 253 | { |
237 | memcpy(((u8*)hh->hh_data) + HH_DATA_OFF(sizeof(struct ethhdr)), | 254 | memcpy(((u8 *) hh->hh_data) + HH_DATA_OFF(sizeof(struct ethhdr)), |
238 | haddr, dev->addr_len); | 255 | haddr, dev->addr_len); |
239 | } | 256 | } |
240 | 257 | ||
241 | EXPORT_SYMBOL(eth_type_trans); | 258 | /** |
242 | 259 | * eth_mac_addr - set new Ethernet hardware address | |
260 | * @dev: network device | ||
261 | * @p: socket address | ||
262 | * Change hardware address of device. | ||
263 | * | ||
264 | * This doesn't change hardware matching, so needs to be overridden | ||
265 | * for most real devices. | ||
266 | */ | ||
243 | static int eth_mac_addr(struct net_device *dev, void *p) | 267 | static int eth_mac_addr(struct net_device *dev, void *p) |
244 | { | 268 | { |
245 | struct sockaddr *addr=p; | 269 | struct sockaddr *addr = p; |
246 | if (netif_running(dev)) | 270 | if (netif_running(dev)) |
247 | return -EBUSY; | 271 | return -EBUSY; |
248 | memcpy(dev->dev_addr, addr->sa_data,dev->addr_len); | 272 | memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); |
249 | return 0; | 273 | return 0; |
250 | } | 274 | } |
251 | 275 | ||
276 | /** | ||
277 | * eth_change_mtu - set new MTU size | ||
278 | * @dev: network device | ||
279 | * @new_mtu: new Maximum Transfer Unit | ||
280 | * | ||
281 | * Allow changing MTU size. Needs to be overridden for devices | ||
282 | * supporting jumbo frames. | ||
283 | */ | ||
252 | static int eth_change_mtu(struct net_device *dev, int new_mtu) | 284 | static int eth_change_mtu(struct net_device *dev, int new_mtu) |
253 | { | 285 | { |
254 | if (new_mtu < 68 || new_mtu > ETH_DATA_LEN) | 286 | if (new_mtu < 68 || new_mtu > ETH_DATA_LEN) |
@@ -257,8 +289,10 @@ static int eth_change_mtu(struct net_device *dev, int new_mtu) | |||
257 | return 0; | 289 | return 0; |
258 | } | 290 | } |
259 | 291 | ||
260 | /* | 292 | /** |
261 | * Fill in the fields of the device structure with ethernet-generic values. | 293 | * ether_setup - setup Ethernet network device |
294 | * @dev: network device | ||
295 | * Fill in the fields of the device structure with Ethernet-generic values. | ||
262 | */ | 296 | */ |
263 | void ether_setup(struct net_device *dev) | 297 | void ether_setup(struct net_device *dev) |
264 | { | 298 | { |
@@ -277,21 +311,21 @@ void ether_setup(struct net_device *dev) | |||
277 | dev->tx_queue_len = 1000; /* Ethernet wants good queues */ | 311 | dev->tx_queue_len = 1000; /* Ethernet wants good queues */ |
278 | dev->flags = IFF_BROADCAST|IFF_MULTICAST; | 312 | dev->flags = IFF_BROADCAST|IFF_MULTICAST; |
279 | 313 | ||
280 | memset(dev->broadcast,0xFF, ETH_ALEN); | 314 | memset(dev->broadcast, 0xFF, ETH_ALEN); |
281 | 315 | ||
282 | } | 316 | } |
283 | EXPORT_SYMBOL(ether_setup); | 317 | EXPORT_SYMBOL(ether_setup); |
284 | 318 | ||
285 | /** | 319 | /** |
286 | * alloc_etherdev - Allocates and sets up an ethernet device | 320 | * alloc_etherdev - Allocates and sets up an Ethernet device |
287 | * @sizeof_priv: Size of additional driver-private structure to be allocated | 321 | * @sizeof_priv: Size of additional driver-private structure to be allocated |
288 | * for this ethernet device | 322 | * for this Ethernet device |
289 | * | 323 | * |
290 | * Fill in the fields of the device structure with ethernet-generic | 324 | * Fill in the fields of the device structure with Ethernet-generic |
291 | * values. Basically does everything except registering the device. | 325 | * values. Basically does everything except registering the device. |
292 | * | 326 | * |
293 | * Constructs a new net device, complete with a private data area of | 327 | * Constructs a new net device, complete with a private data area of |
294 | * size @sizeof_priv. A 32-byte (not bit) alignment is enforced for | 328 | * size (sizeof_priv). A 32-byte (not bit) alignment is enforced for |
295 | * this private data area. | 329 | * this private data area. |
296 | */ | 330 | */ |
297 | 331 | ||