root/net/inet/eth.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. eth_print
  2. eth_dump
  3. eth_header
  4. eth_rebuild_header
  5. eth_add_arp
  6. eth_type_trans

   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.28    20/12/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  * 
  14  * Fixes:
  15  *              Mr Linux        : Arp problems.
  16  *              Alan Cox        : Generic queue tidyup (very tiny here).
  17  *              Alan Cox        : eth_header ntohs should be htons.
  18  *              Alan Cox        : eth_rebuild_header missing an htons and
  19  *                                minor other things.
  20  *              Tegge           : Arp bug fixes.
  21  *              Alan Cox        : Tidy up ready for the big day.
  22  *
  23  *              This program is free software; you can redistribute it and/or
  24  *              modify it under the terms of the GNU General Public License
  25  *              as published by the Free Software Foundation; either version
  26  *              2 of the License, or (at your option) any later version.
  27  */
  28 
  29 #include <asm/segment.h>
  30 #include <asm/system.h>
  31 #include <linux/types.h>
  32 #include <linux/kernel.h>
  33 #include <linux/sched.h>
  34 #include <linux/string.h>
  35 #include <linux/mm.h>
  36 #include <linux/socket.h>
  37 #include <linux/in.h>
  38 #include "inet.h"
  39 #include "devinet.h"
  40 #include "eth.h"
  41 #include "ip.h"
  42 #include "route.h"
  43 #include "protocol.h"
  44 #include "tcp.h"
  45 #include "skbuff.h"
  46 #include "sockinet.h"
  47 #include <linux/errno.h>
  48 #include "arp.h"
  49 
  50 
  51 #ifdef ETH_DEBUG
  52 /* Display an Ethernet address in readable format. */
  53 char *eth_print(unsigned char *ptr)
     /* [previous][next][first][last][top][bottom][index][help] */
  54 {
  55   static char buff[64];
  56 
  57   if (ptr == NULL) return("[NONE]");
  58   sprintf(buff, "%02X:%02X:%02X:%02X:%02X:%02X",
  59         (ptr[0] & 255), (ptr[1] & 255), (ptr[2] & 255),
  60         (ptr[3] & 255), (ptr[4] & 255), (ptr[5] & 255)
  61   );
  62   return(buff);
  63 }
  64 #endif
  65 
  66 
  67 #ifdef ETH_DEBUG
  68 
  69 /*
  70  *      Display the contents of the Ethernet MAC header. 
  71  */
  72 
  73 void eth_dump(struct ethhdr *eth)
     /* [previous][next][first][last][top][bottom][index][help] */
  74 {
  75   if (inet_debug != DBG_ETH) return;
  76 
  77   printk("eth: SRC = %s ", eth_print(eth->h_source));
  78   printk("DST = %s ", eth_print(eth->h_dest));
  79   printk("TYPE = %04X\n", ntohs(eth->h_proto));
  80 }
  81 
  82 #endif
  83 
  84 
  85 /*
  86  *      Create the Ethernet MAC header. 
  87  *
  88  *      ARP might prevent this from working all in one go. See also
  89  *      the rebuild header function.
  90  */
  91  
  92 int eth_header(unsigned char *buff, struct device *dev, unsigned short type,
     /* [previous][next][first][last][top][bottom][index][help] */
  93            unsigned long daddr, unsigned long saddr, unsigned len)
  94 {
  95         struct ethhdr *eth;
  96 
  97         DPRINTF((DBG_DEV, "ETH: header(%s, ", in_ntoa(saddr)));
  98         DPRINTF((DBG_DEV, "%s, 0x%X)\n", in_ntoa(daddr), type));
  99 
 100         /* Fill in the basic Ethernet MAC header. */
 101         eth = (struct ethhdr *) buff;
 102         eth->h_proto = htons(type);
 103 
 104         /* We don't ARP for the LOOPBACK device... */
 105         if (dev->flags & IFF_LOOPBACK) 
 106         {
 107                 DPRINTF((DBG_DEV, "ETH: No header for loopback\n"));
 108                 memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
 109                 memset(eth->h_dest, 0, dev->addr_len);
 110                 return(dev->hard_header_len);
 111         }
 112 
 113         /* Check if we can use the MAC BROADCAST address. */
 114         if (chk_addr(daddr) == IS_BROADCAST) 
 115         {
 116                 DPRINTF((DBG_DEV, "ETH: Using MAC Broadcast\n"));
 117                 memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
 118                 memcpy(eth->h_dest, dev->broadcast, dev->addr_len);
 119                 return(dev->hard_header_len);
 120         }
 121         /*
 122          *      We disable interrupts here to avoid a race if the ARP
 123          *      reply is too quick.
 124          */
 125         cli();
 126         memcpy(eth->h_source, &saddr, 4);
 127         /* No. Ask ARP to resolve the Ethernet address. */
 128         if (arp_find(eth->h_dest, daddr, dev, dev->pa_addr/* saddr */)) 
 129         {
 130                 sti();
 131                 if(type!=ETH_P_IP)
 132                         printk("Erk: protocol %X got into an arp request state!\n",type);
 133                 return(-dev->hard_header_len);
 134         } 
 135         else
 136         {
 137                 memcpy(eth->h_source,dev->dev_addr,dev->addr_len);      /* This was missing causing chaos if the
 138                                                                            header built correctly! */
 139                 sti();
 140                 return(dev->hard_header_len);
 141         }
 142 }
 143 
 144 
 145 /*
 146  *      Rebuild the Ethernet MAC header.
 147  *
 148  *      We've got a 'stuck' packet that failed to go out before. See if
 149  *      the arp is resolved and we can finally shift it.
 150  */
 151  
 152 int eth_rebuild_header(void *buff, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 153 {
 154         struct ethhdr *eth;
 155         unsigned long src, dst;
 156 
 157         DPRINTF((DBG_DEV, "ETH: Using MAC Broadcast\n"));
 158         eth = (struct ethhdr *) buff;
 159         src = *(unsigned long *) eth->h_source;
 160         dst = *(unsigned long *) eth->h_dest;
 161         DPRINTF((DBG_DEV, "ETH: RebuildHeader: SRC=%s ", in_ntoa(src)));
 162         DPRINTF((DBG_DEV, "DST=%s\n", in_ntoa(dst)));
 163         if(eth->h_proto!=htons(ETH_P_ARP))      /* This ntohs kind of helps a bit! */
 164                 if (arp_find(eth->h_dest, dst, dev, dev->pa_addr /* src */)) 
 165                         /* Still not known */
 166                         return(1);
 167         memcpy(eth->h_source, dev->dev_addr, dev->addr_len);
 168         return(0);
 169 }
 170 
 171 
 172 /* 
 173  *      Add an ARP entry for a host on this interface.
 174  */
 175  
 176 void eth_add_arp(unsigned long addr, struct sk_buff *skb, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 177 {
 178         struct ethhdr *eth;
 179 
 180         eth = (struct ethhdr *) (skb + 1);
 181         arp_add(addr, eth->h_source, dev);
 182 }
 183 
 184 
 185 /*
 186  *      Determine the packet's protocol ID. 
 187  *
 188  * Ethernet comes in two 'species' DIX (Digitial Intel Xerox) and IEE802.3
 189  * needless to say they are different. Fortunately there is a way of telling
 190  * them apart. All 'normal' modern DIX service ID's are >1536.
 191  * All IEE802.3 frames have a length at this position and that cannot be 
 192  * >=1536. Note IEE802.3 frames have a second 802.2 header normally. We don't
 193  * deal with this bit in the current kernel, but a user using SOCK_PACKET
 194  * for 802.3 frames can do so.
 195  */
 196  
 197 unsigned short eth_type_trans(struct sk_buff *skb, struct device *dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 198 {
 199         struct ethhdr *eth;
 200 
 201         eth = (struct ethhdr *) (skb + 1);
 202 
 203         if(ntohs(eth->h_proto)<1536)
 204                 return(htons(ETH_P_802_3));
 205         return(eth->h_proto);
 206 }

/* [previous][next][first][last][top][bottom][index][help] */