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 * Interface (streams) handling functions. 7 * 8 * Version: @(#)dev.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 * Alan Cox: check_addr returns a value for a wrong subnet 16 * ie not us but don't forward this! 17 * Alan Cox: block timer if the inet_bh handler is running 18 * Alan Cox: generic queue code added. A lot neater now 19 * C.E.Hawkins: SIOCGIFCONF only reports 'upped' interfaces 20 * C.E.Hawkins: IFF_PROMISC support 21 * Alan Cox: Supports Donald Beckers new hardware 22 * multicast layer, but not yet multicast lists. 23 * Alan Cox: ip_addr_match problems with class A/B nets. 24 * C.E.Hawkins IP 0.0.0.0 and also same net route fix. [FIXME: Ought to cause ICMP_REDIRECT] 25 * Alan Cox: Removed bogus subnet check now the subnet code 26 * a) actually works for all A/B nets 27 * b) doesn't forward off the same interface. 28 * Alan Cox: Multiple extra protocols 29 * Alan Cox: A Couple more escaped verify_area calls die 30 * Alan Cox: IP_SET_DEV is gone (forever) as per Fred's comment. 31 * Alan Cox: Grand tidy up ready for the big day. 32 * Alan Cox: Handles dev_open errors correctly. 33 * Alan Cox: IP and generic parts split 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
41 #include <asm/segment.h>
42 #include <asm/system.h>
43 #include <asm/bitops.h>
44 #include <linux/config.h>
45 #include <linux/types.h>
46 #include <linux/kernel.h>
47 #include <linux/sched.h>
48 #include <linux/string.h>
49 #include <linux/mm.h>
50 #include <linux/socket.h>
51 #include <linux/sockios.h>
52 #include <linux/in.h>
53 #include <linux/errno.h>
54 #include <linux/interrupt.h>
55 #include <linux/if_ether.h>
56 #include "inet.h"
57 #include "devinet.h"
58 #include "eth.h"
59 #include "ip.h"
60 #include "route.h"
61 #include "protocol.h"
62 #include "tcp.h"
63 #include "skbuff.h"
64
65
66 /* 67 * Determine a default network mask, based on the IP address. 68 */ 69
70 unsignedlongip_get_mask(unsignedlongaddr)
/* */ 71 { 72 unsignedlongdst;
73
74 if (addr == 0L)
75 return(0L); /* special case */ 76
77 dst = ntohl(addr);
78 if (IN_CLASSA(dst))
79 return(htonl(IN_CLASSA_NET));
80 if (IN_CLASSB(dst))
81 return(htonl(IN_CLASSB_NET));
82 if (IN_CLASSC(dst))
83 return(htonl(IN_CLASSC_NET));
84
85 /* Something else, probably a subnet. */ 86 return(0);
87 } 88
89 /* 90 * See if a pair of addresses match. 91 */ 92
93 intip_addr_match(unsignedlongme, unsignedlonghim)
/* */ 94 { 95 inti;
96 unsignedlongmask=0xFFFFFFFF;
97 DPRINTF((DBG_DEV, "ip_addr_match(%s, ", in_ntoa(me)));
98 DPRINTF((DBG_DEV, "%s)\n", in_ntoa(him)));
99
100 /* Fast path for 99.9% of cases */ 101 if (me == him)
102 return(1);
103
104 for (i = 0; i < 4; i++, me >>= 8, him >>= 8, mask >>= 8)
105 { 106 if ((me & 0xFF) != (him & 0xFF))
107 { 108 /* 109 * The only way this could be a match is for 110 * the rest of addr1 to be 0 or 255. 111 */ 112 if (me != 0 && me != mask)
113 return(0);
114 return(1);
115 } 116 } 117 return(1);
118 } 119
120
121 /* 122 * Check the address for our address, broadcasts, etc. 123 * 124 * This routine is used a lot, and in many time critical 125 * places. It's already _TOO_ slow so be careful how you 126 * alter it. 127 */ 128
129 intchk_addr(unsignedlongaddr)
/* */ 130 { 131 structdevice *dev;
132 unsignedlongdst;
133
134 DPRINTF((DBG_DEV, "chk_addr(%s) --> ", in_ntoa(addr)));
135 dst = ntohl(addr);
136
137 /* 138 * Accept both `all ones' and `all zeros' as BROADCAST. 139 * All 0's is the old BSD broadcast. 140 */ 141
142 if (dst == INADDR_ANY || dst == INADDR_BROADCAST)
143 { 144 DPRINTF((DBG_DEV, "BROADCAST\n"));
145 return(IS_BROADCAST);
146 } 147
148 /* Accept all of the `loopback' class A net. */ 149 if ((dst & IN_CLASSA_NET) == 0x7F000000L)
150 { 151 DPRINTF((DBG_DEV, "LOOPBACK\n"));
152
153 /* 154 * We force `loopback' to be equal to MY_ADDR. 155 */ 156 return(IS_MYADDR);
157 /* return(IS_LOOPBACK); */ 158 } 159
160 /* OK, now check the interface addresses. */ 161 for (dev = dev_base; dev != NULL; dev = dev->next)
162 { 163 if (!(dev->flags&IFF_UP))
164 continue;
165 if ((dev->pa_addr == 0)/* || (dev->flags&IFF_PROMISC)*/)
166 return(IS_MYADDR);
167 /* Is it the exact IP address? */ 168 if (addr == dev->pa_addr)
169 { 170 DPRINTF((DBG_DEV, "MYADDR\n"));
171 return(IS_MYADDR);
172 } 173
174 /* Nope. Check for a subnetwork broadcast. */ 175 if ((addr & dev->pa_mask) == (dev->pa_addr & dev->pa_mask))
176 { 177 if ((addr & ~dev->pa_mask) == 0)
178 { 179 DPRINTF((DBG_DEV, "SUBBROADCAST-0\n"));
180 return(IS_BROADCAST);
181 } 182 if (((addr & ~dev->pa_mask) | dev->pa_mask)
183 == INADDR_BROADCAST)
184 { 185 DPRINTF((DBG_DEV, "SUBBROADCAST-1\n"));
186 return(IS_BROADCAST);
187 } 188 } 189
190 /* Nope. Check for Network broadcast. */ 191 if(IN_CLASSA(dst))
192 { 193 if( addr == (dev->pa_addr | 0xffffff00))
194 { 195 DPRINTF((DBG_DEV, "CLASS A BROADCAST-1\n"));
196 return(IS_BROADCAST);
197 } 198 } 199 elseif(IN_CLASSB(dst))
200 { 201 if( addr == (dev->pa_addr | 0xffff0000))
202 { 203 DPRINTF((DBG_DEV, "CLASS B BROADCAST-1\n"));
204 return(IS_BROADCAST);
205 } 206 } 207 else 208 {/* IN_CLASSC */ 209 if( addr == (dev->pa_addr | 0xff000000))
210 { 211 DPRINTF((DBG_DEV, "CLASS C BROADCAST-1\n"));
212 return(IS_BROADCAST);
213 } 214 } 215 } 216
217 DPRINTF((DBG_DEV, "NONE\n"));
218
219 return(0); /* no match at all */ 220 } 221
222
223 /* 224 * Retrieve our own address. 225 * Because the loopback address (127.0.0.1) is already recognized 226 * automatically, we can use the loopback interface's address as 227 * our "primary" interface. This is the addressed used by IP et 228 * al when it doesn't know which address to use (i.e. it does not 229 * yet know from or to which interface to go...). 230 */ 231
232 unsignedlongmy_addr(void)
/* */ 233 { 234 structdevice *dev;
235
236 for (dev = dev_base; dev != NULL; dev = dev->next)
237 { 238 if (dev->flags & IFF_LOOPBACK)
239 return(dev->pa_addr);
240 } 241 return(0);
242 } 243
244
245
246 /* 247 * Find an interface that can handle addresses for a certain address. 248 */ 249
250 structdevice *dev_check(unsignedlongaddr)
/* */ 251 { 252 structdevice *dev;
253
254 for (dev = dev_base; dev; dev = dev->next)
255 if ((dev->flags & IFF_UP) && (dev->flags & IFF_POINTOPOINT) &&
256 (addr == dev->pa_dstaddr))
257 returndev;
258 for (dev = dev_base; dev; dev = dev->next)
259 if ((dev->flags & IFF_UP) && !(dev->flags & IFF_POINTOPOINT) &&
260 (dev->flags & IFF_LOOPBACK ? (addr == dev->pa_addr) :
261 (dev->pa_mask & addr) == (dev->pa_addr & dev->pa_mask)))
262 break;
263 /* no need to check broadcast addresses */ 264 returndev;
265 } 266