eth.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:6k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  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, <bir7@leland.Stanford.Edu>
  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/types.h>
  41. #include <linux/kernel.h>
  42. #include <linux/sched.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/config.h>
  54. #include <linux/init.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. #include <asm/checksum.h>
  63. extern int __init netdev_boot_setup(char *str);
  64. __setup("ether=", netdev_boot_setup);
  65. /*
  66.  *  Create the Ethernet MAC header for an arbitrary protocol layer 
  67.  *
  68.  * saddr=NULL means use device source address
  69.  * daddr=NULL means leave destination address (eg unresolved arp)
  70.  */
  71. int eth_header(struct sk_buff *skb, struct net_device *dev, unsigned short type,
  72.    void *daddr, void *saddr, unsigned len)
  73. {
  74. struct ethhdr *eth = (struct ethhdr *)skb_push(skb,ETH_HLEN);
  75. /* 
  76.  * Set the protocol type. For a packet of type ETH_P_802_3 we put the length
  77.  * in here instead. It is up to the 802.2 layer to carry protocol information.
  78.  */
  79. if(type!=ETH_P_802_3) 
  80. eth->h_proto = htons(type);
  81. else
  82. eth->h_proto = htons(len);
  83. /*
  84.  * Set the source hardware address. 
  85.  */
  86.  
  87. if(saddr)
  88. memcpy(eth->h_source,saddr,dev->addr_len);
  89. else
  90. memcpy(eth->h_source,dev->dev_addr,dev->addr_len);
  91. /*
  92.  * Anyway, the loopback-device should never use this function... 
  93.  */
  94. if (dev->flags & (IFF_LOOPBACK|IFF_NOARP)) 
  95. {
  96. memset(eth->h_dest, 0, dev->addr_len);
  97. return(dev->hard_header_len);
  98. }
  99. if(daddr)
  100. {
  101. memcpy(eth->h_dest,daddr,dev->addr_len);
  102. return dev->hard_header_len;
  103. }
  104. return -dev->hard_header_len;
  105. }
  106. /*
  107.  * Rebuild the Ethernet MAC header. This is called after an ARP
  108.  * (or in future other address resolution) has completed on this
  109.  * sk_buff. We now let ARP fill in the other fields.
  110.  *
  111.  * This routine CANNOT use cached dst->neigh!
  112.  * Really, it is used only when dst->neigh is wrong.
  113.  */
  114. int eth_rebuild_header(struct sk_buff *skb)
  115. {
  116. struct ethhdr *eth = (struct ethhdr *)skb->data;
  117. struct net_device *dev = skb->dev;
  118. switch (eth->h_proto)
  119. {
  120. #ifdef CONFIG_INET
  121. case __constant_htons(ETH_P_IP):
  122.   return arp_find(eth->h_dest, skb);
  123. #endif
  124. default:
  125. printk(KERN_DEBUG
  126.        "%s: unable to resolve type %X addresses.n", 
  127.        dev->name, (int)eth->h_proto);
  128. memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
  129. break;
  130. }
  131. return 0;
  132. }
  133. /*
  134.  * Determine the packet's protocol ID. The rule here is that we 
  135.  * assume 802.3 if the type field is short enough to be a length.
  136.  * This is normal practice and works for any 'now in use' protocol.
  137.  */
  138.  
  139. unsigned short eth_type_trans(struct sk_buff *skb, struct net_device *dev)
  140. {
  141. struct ethhdr *eth;
  142. unsigned char *rawp;
  143. skb->mac.raw=skb->data;
  144. skb_pull(skb,dev->hard_header_len);
  145. eth= skb->mac.ethernet;
  146. if(*eth->h_dest&1)
  147. {
  148. if(memcmp(eth->h_dest,dev->broadcast, ETH_ALEN)==0)
  149. skb->pkt_type=PACKET_BROADCAST;
  150. else
  151. skb->pkt_type=PACKET_MULTICAST;
  152. }
  153. /*
  154.  * This ALLMULTI check should be redundant by 1.4
  155.  * so don't forget to remove it.
  156.  *
  157.  * Seems, you forgot to remove it. All silly devices
  158.  * seems to set IFF_PROMISC.
  159.  */
  160.  
  161. else if(1 /*dev->flags&IFF_PROMISC*/)
  162. {
  163. if(memcmp(eth->h_dest,dev->dev_addr, ETH_ALEN))
  164. skb->pkt_type=PACKET_OTHERHOST;
  165. }
  166. if (ntohs(eth->h_proto) >= 1536)
  167. return eth->h_proto;
  168. rawp = skb->data;
  169. /*
  170.  * This is a magic hack to spot IPX packets. Older Novell breaks
  171.  * the protocol design and runs IPX over 802.3 without an 802.2 LLC
  172.  * layer. We look for FFFF which isn't a used 802.2 SSAP/DSAP. This
  173.  * won't work for fault tolerant netware but does for the rest.
  174.  */
  175. if (*(unsigned short *)rawp == 0xFFFF)
  176. return htons(ETH_P_802_3);
  177. /*
  178.  * Real 802.2 LLC
  179.  */
  180. return htons(ETH_P_802_2);
  181. }
  182. int eth_header_parse(struct sk_buff *skb, unsigned char *haddr)
  183. {
  184. struct ethhdr *eth = skb->mac.ethernet;
  185. memcpy(haddr, eth->h_source, ETH_ALEN);
  186. return ETH_ALEN;
  187. }
  188. int eth_header_cache(struct neighbour *neigh, struct hh_cache *hh)
  189. {
  190. unsigned short type = hh->hh_type;
  191. struct ethhdr *eth = (struct ethhdr*)(((u8*)hh->hh_data) + 2);
  192. struct net_device *dev = neigh->dev;
  193. if (type == __constant_htons(ETH_P_802_3))
  194. return -1;
  195. eth->h_proto = type;
  196. memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
  197. memcpy(eth->h_dest, neigh->ha, dev->addr_len);
  198. hh->hh_len = ETH_HLEN;
  199. return 0;
  200. }
  201. /*
  202.  * Called by Address Resolution module to notify changes in address.
  203.  */
  204. void eth_header_cache_update(struct hh_cache *hh, struct net_device *dev, unsigned char * haddr)
  205. {
  206. memcpy(((u8*)hh->hh_data) + 2, haddr, dev->addr_len);
  207. }