1/* 2 * INET An implementation of the TCP/IP protocol suite for the LINUX 3 * operating system. INET is implemented using the BSD Socket 4 * interface as the means of communication with the user level. 5 * 6 * Ethernet-type device handling. 7 * 8 * Version: @(#)eth.c 1.0.7 05/25/93 9 * 10 * Authors: Ross Biro 11 * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG> 12 * Mark Evans, <evansmp@uhura.aston.ac.uk> 13 * Florian La Roche, <rzsfl@rz.uni-sb.de> 14 * Alan Cox, <gw4pts@gw4pts.ampr.org> 15 * 16 * Fixes: 17 * Mr Linux : Arp problems 18 * Alan Cox : Generic queue tidyup (very tiny here) 19 * Alan Cox : eth_header ntohs should be htons 20 * Alan Cox : eth_rebuild_header missing an htons and 21 * minor other things. 22 * Tegge : Arp bug fixes. 23 * Florian : Removed many unnecessary functions, code cleanup 24 * and changes for new arp and skbuff. 25 * Alan Cox : Redid header building to reflect new format. 26 * Alan Cox : ARP only when compiled with CONFIG_INET 27 * Greg Page : 802.2 and SNAP stuff. 28 * Alan Cox : MAC layer pointers/new format. 29 * Paul Gortmaker : eth_copy_and_sum shouldn't csum padding. 30 * Alan Cox : Protect against forwarding explosions with 31 * older network drivers and IFF_ALLMULTI. 32 * Christer Weinigel : Better rebuild header message. 33 * Andrew Morton : 26Feb01: kill ether_setup() - use netdev_boot_setup(). 34 * 35 * This program is free software; you can redistribute it and/or 36 * modify it under the terms of the GNU General Public License 37 * as published by the Free Software Foundation; either version 38 * 2 of the License, or (at your option) any later version. 39 */ 40#include <linux/module.h> 41#include <linux/types.h> 42#include <linux/kernel.h> 43#include <linux/string.h> 44#include <linux/mm.h> 45#include <linux/socket.h> 46#include <linux/in.h> 47#include <linux/inet.h> 48#include <linux/ip.h> 49#include <linux/netdevice.h> 50#include <linux/etherdevice.h> 51#include <linux/skbuff.h> 52#include <linux/errno.h> 53#include <linux/init.h> 54#include <linux/if_ether.h> 55#include <net/dst.h> 56#include <net/arp.h> 57#include <net/sock.h> 58#include <net/ipv6.h> 59#include <net/ip.h> 60#include <asm/uaccess.h> 61#include <asm/system.h> 62 63__setup("ether=",netdev_boot_setup); 64 65/** 66 * eth_header - create the Ethernet header 67 * @skb: buffer to alter 68 * @dev: source device 69 * @type: Ethernet type field 70 * @daddr: destination address (NULL leave destination address) 71 * @saddr: source address (NULL use device source address) 72 * @len: packet length (<= skb->len) 73 * 74 * 75 * Set the protocol type. For a packet of type ETH_P_802_3 we put the length 76 * in here instead. It is up to the 802.2 layer to carry protocol information. 77 */ 78inteth_header(structsk_buff*skb,structnet_device*dev, 79unsignedshorttype, 80constvoid*daddr,constvoid*saddr,unsignedlen) 81{ 82structethhdr*eth=(structethhdr*)skb_push(skb,ETH_HLEN); 83 84if(type!=ETH_P_802_3) 85eth->h_proto=htons(type); 86else 87eth->h_proto=htons(len); 88 89/* 90 * Set the source hardware address. 91 */ 92 93if(!saddr) 94saddr=dev->dev_addr; 95memcpy(eth->h_source,saddr,ETH_ALEN); 96 97if(daddr){ 98memcpy(eth->h_dest,daddr,ETH_ALEN); 99returnETH_HLEN;100}101102/*103 * Anyway, the loopback-device should never use this function...104 */105106if(dev->flags&(IFF_LOOPBACK|IFF_NOARP)){107memset(eth->h_dest,0,ETH_ALEN);108returnETH_HLEN;109}110111return-ETH_HLEN;112}113EXPORT_SYMBOL(eth_header);114115/**116 * eth_rebuild_header- rebuild the Ethernet MAC header.117 * @skb: socket buffer to update118 *119 * This is called after an ARP or IPV6 ndisc it's resolution on this120 * 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 */125inteth_rebuild_header(structsk_buff*skb)126{127structethhdr*eth=(structethhdr*)skb->data;128structnet_device*dev=skb->dev;129130switch(eth->h_proto){131#ifdef CONFIG_INET132case__constant_htons(ETH_P_IP):
133returnarp_find(eth->h_dest,skb);134#endif135default:136printk(KERN_DEBUG137"%s: unable to resolve type %X addresses.\n",138dev->name,(int)eth->h_proto);139140memcpy(eth->h_source,dev->dev_addr,ETH_ALEN);141break;142}143144return0;145}146EXPORT_SYMBOL(eth_rebuild_header);147148/**149 * eth_type_trans - determine the packet's protocol ID.150 * @skb: received socket data151 * @dev: receiving network device152 *153 * The rule here is that we154 * assume 802.3 if the type field is short enough to be a length.155 * This is normal practice and works for any 'now in use' protocol.156 */157__be16eth_type_trans(structsk_buff*skb,structnet_device*dev)158{159structethhdr*eth;160unsignedchar*rawp;161162skb->dev=dev;163skb_reset_mac_header(skb);164skb_pull(skb,ETH_HLEN);165eth=eth_hdr(skb);166167if(is_multicast_ether_addr(eth->h_dest)){168if(!compare_ether_addr(eth->h_dest,dev->broadcast))169skb->pkt_type=PACKET_BROADCAST;170else171skb->pkt_type=PACKET_MULTICAST;172}173174/*175 * This ALLMULTI check should be redundant by 1.4176 * so don't forget to remove it.177 *178 * Seems, you forgot to remove it. All silly devices179 * seems to set IFF_PROMISC.180 */181182elseif(1/*dev->flags&IFF_PROMISC */){183if(unlikely(compare_ether_addr(eth->h_dest,dev->dev_addr)))184skb->pkt_type=PACKET_OTHERHOST;185}186187if(ntohs(eth->h_proto)>=1536)188returneth->h_proto;189190rawp=skb->data;191192/*193 * This is a magic hack to spot IPX packets. Older Novell breaks194 * the protocol design and runs IPX over 802.3 without an 802.2 LLC195 * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This196 * won't work for fault tolerant netware but does for the rest.197 */198if(*(unsignedshort*)rawp==0xFFFF)199returnhtons(ETH_P_802_3);200201/*202 * Real 802.2 LLC203 */204returnhtons(ETH_P_802_2);205}206EXPORT_SYMBOL(eth_type_trans);207208/**209 * eth_header_parse - extract hardware address from packet210 * @skb: packet to extract header from211 * @haddr: destination buffer212 */213inteth_header_parse(conststructsk_buff*skb,unsignedchar*haddr)214{215conststructethhdr*eth=eth_hdr(skb);216memcpy(haddr,eth->h_source,ETH_ALEN);217returnETH_ALEN;218}219EXPORT_SYMBOL(eth_header_parse);220221/**222 * eth_header_cache - fill cache entry from neighbour223 * @neigh: source neighbour224 * @hh: destination cache entry225 * Create an Ethernet header template from the neighbour.226 */227inteth_header_cache(conststructneighbour*neigh,structhh_cache*hh)228{229__be16type=hh->hh_type;230structethhdr*eth;231conststructnet_device*dev=neigh->dev;232233eth=(structethhdr*)234(((u8*)hh->hh_data)+(HH_DATA_OFF(sizeof(*eth))));235236if(type==htons(ETH_P_802_3))237return-1;238239eth->h_proto=type;240memcpy(eth->h_source,dev->dev_addr,ETH_ALEN);241memcpy(eth->h_dest,neigh->ha,ETH_ALEN);242hh->hh_len=ETH_HLEN;243return0;244}245EXPORT_SYMBOL(eth_header_cache);246247/**248 * eth_header_cache_update - update cache entry249 * @hh: destination cache entry250 * @dev: network device251 * @haddr: new hardware address252 *253 * Called by Address Resolution module to notify changes in address.254 */255voideth_header_cache_update(structhh_cache*hh,256conststructnet_device*dev,257constunsignedchar*haddr)258{259memcpy(((u8*)hh->hh_data)+HH_DATA_OFF(sizeof(structethhdr)),260haddr,ETH_ALEN);261}262EXPORT_SYMBOL(eth_header_cache_update);263264/**265 * eth_mac_addr - set new Ethernet hardware address266 * @dev: network device267 * @p: socket address268 * Change hardware address of device.269 *270 * This doesn't change hardware matching, so needs to be overridden271 * for most real devices.272 */273staticinteth_mac_addr(structnet_device*dev,void*p)274{275structsockaddr*addr=p;276277if(netif_running(dev))278return-EBUSY;279if(!is_valid_ether_addr(addr->sa_data))280return-EADDRNOTAVAIL;281memcpy(dev->dev_addr,addr->sa_data,ETH_ALEN);282return0;283}284285/**286 * eth_change_mtu - set new MTU size287 * @dev: network device288 * @new_mtu: new Maximum Transfer Unit289 *290 * Allow changing MTU size. Needs to be overridden for devices291 * supporting jumbo frames.292 */293staticinteth_change_mtu(structnet_device*dev,intnew_mtu)294{295if(new_mtu<68||new_mtu>ETH_DATA_LEN)296return-EINVAL;297dev->mtu=new_mtu;298return0;299}300301staticinteth_validate_addr(structnet_device*dev)302{303if(!is_valid_ether_addr(dev->dev_addr))304return-EINVAL;305306return0;307}308309conststructheader_opseth_header_ops____cacheline_aligned={310.create=eth_header,311.parse=eth_header_parse,312.rebuild=eth_rebuild_header,313.cache=eth_header_cache,314.cache_update=eth_header_cache_update,315};316317/**318 * ether_setup - setup Ethernet network device319 * @dev: network device320 * Fill in the fields of the device structure with Ethernet-generic values.321 */322voidether_setup(structnet_device*dev)323{324dev->header_ops=ð_header_ops;325326dev->change_mtu=eth_change_mtu;327dev->set_mac_address=eth_mac_addr;328dev->validate_addr=eth_validate_addr;329330dev->type=ARPHRD_ETHER;331dev->hard_header_len=ETH_HLEN;332dev->mtu=ETH_DATA_LEN;333dev->addr_len=ETH_ALEN;334dev->tx_queue_len=1000;/* Ethernet wants good queues */335dev->flags=IFF_BROADCAST|IFF_MULTICAST;336337memset(dev->broadcast,0xFF,ETH_ALEN);338339}340EXPORT_SYMBOL(ether_setup);341342/**343 * alloc_etherdev_mq - Allocates and sets up an Ethernet device344 * @sizeof_priv: Size of additional driver-private structure to be allocated345 * for this Ethernet device346 * @queue_count: The number of queues this device has.347 *348 * Fill in the fields of the device structure with Ethernet-generic349 * values. Basically does everything except registering the device.350 *351 * Constructs a new net device, complete with a private data area of352 * size (sizeof_priv). A 32-byte (not bit) alignment is enforced for353 * this private data area.354 */355356structnet_device*alloc_etherdev_mq(intsizeof_priv,unsignedintqueue_count)357{358returnalloc_netdev_mq(sizeof_priv,"eth%d",ether_setup,queue_count);359}360EXPORT_SYMBOL(alloc_etherdev_mq);361362char*print_mac(char*buf,constu8*addr)363{364sprintf(buf,MAC_FMT,365addr[0],addr[1],addr[2],addr[3],addr[4],addr[5]);366returnbuf;367}368EXPORT_SYMBOL(print_mac);