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 #ifdefETH_DEBUG 52 /* Display an Ethernet address in readable format. */ 53 char *eth_print(unsignedchar *ptr)
/* */ 54 { 55 staticcharbuff[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 #ifdefETH_DEBUG 68
69 /* 70 * Display the contents of the Ethernet MAC header. 71 */ 72
73 voideth_dump(structethhdr *eth)
/* */ 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 inteth_header(unsignedchar *buff, structdevice *dev, unsignedshorttype,
/* */ 93 unsignedlongdaddr, unsignedlongsaddr, unsignedlen)
94 { 95 structethhdr *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 = (structethhdr *) 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 inteth_rebuild_header(void *buff, structdevice *dev)
/* */ 153 { 154 structethhdr *eth;
155 unsignedlongsrc, dst;
156
157 DPRINTF((DBG_DEV, "ETH: Using MAC Broadcast\n"));
158 eth = (structethhdr *) buff;
159 src = *(unsignedlong *) eth->h_source;
160 dst = *(unsignedlong *) 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 voideth_add_arp(unsignedlongaddr, structsk_buff *skb, structdevice *dev)
/* */ 177 { 178 structethhdr *eth;
179
180 eth = (structethhdr *) (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 unsignedshorteth_type_trans(structsk_buff *skb, structdevice *dev)
/* */ 198 { 199 structethhdr *eth;
200
201 eth = (structethhdr *) (skb + 1);
202
203 if(ntohs(eth->h_proto)<1536)
204 return(htons(ETH_P_802_3));
205 return(eth->h_proto);
206 }