1 /* 2 * NET3 IP device support routines. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 7 * 2 of the License, or (at your option) any later version. 8 * 9 * Derived from the IP parts of dev.c 1.0.19 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 * Additional Authors: 15 * Alan Cox, <gw4pts@gw4pts.ampr.org> 16 */ 17
18 #include <asm/segment.h>
19 #include <asm/system.h>
20 #include <asm/bitops.h>
21 #include <linux/config.h>
22 #include <linux/types.h>
23 #include <linux/kernel.h>
24 #include <linux/sched.h>
25 #include <linux/string.h>
26 #include <linux/mm.h>
27 #include <linux/socket.h>
28 #include <linux/sockios.h>
29 #include <linux/in.h>
30 #include <linux/errno.h>
31 #include <linux/interrupt.h>
32 #include <linux/if_ether.h>
33 #include <linux/inet.h>
34 #include <linux/netdevice.h>
35 #include <linux/etherdevice.h>
36 #include "ip.h"
37 #include "route.h"
38 #include "protocol.h"
39 #include "tcp.h"
40 #include <linux/skbuff.h>
41 #include "sock.h"
42 #include "arp.h"
43
44 /* 45 * Determine a default network mask, based on the IP address. 46 */ 47
48 unsignedlongip_get_mask(unsignedlongaddr)
/* */ 49 { 50 unsignedlongdst;
51
52 if (addr == 0L)
53 return(0L); /* special case */ 54
55 dst = ntohl(addr);
56 if (IN_CLASSA(dst))
57 return(htonl(IN_CLASSA_NET));
58 if (IN_CLASSB(dst))
59 return(htonl(IN_CLASSB_NET));
60 if (IN_CLASSC(dst))
61 return(htonl(IN_CLASSC_NET));
62
63 /* 64 * Something else, probably a multicast. 65 */ 66
67 return(0);
68 } 69
70 /* 71 * Perform an IP address matching operation 72 */ 73
74 intip_addr_match(unsignedlongme, unsignedlonghim)
/* */ 75 { 76 inti;
77 unsignedlongmask=0xFFFFFFFF;
78 DPRINTF((DBG_DEV, "ip_addr_match(%s, ", in_ntoa(me)));
79 DPRINTF((DBG_DEV, "%s)\n", in_ntoa(him)));
80
81 /* 82 * Simple case 83 */ 84 if (me == him)
85 return(1);
86
87 /* 88 * Look for a match ending in all 1's 89 */ 90
91 for (i = 0; i < 4; i++, me >>= 8, him >>= 8, mask >>= 8)
92 { 93 if ((me & 0xFF) != (him & 0xFF))
94 { 95 /* 96 * The only way this could be a match is for 97 * the rest of addr1 to be 0 or 255. 98 */ 99 if (me != 0 && me != mask)
100 return(0);
101 return(1);
102 } 103 } 104 return(1);
105 } 106
107
108 /* 109 * Check the address for our address, broadcasts, etc. 110 * 111 * I intend to fix this to at the very least cache the last 112 * resolved entry. 113 */ 114
115 intip_chk_addr(unsignedlongaddr)
/* */ 116 { 117 structdevice *dev;
118 unsignedlongmask;
119
120 /* 121 * Accept both `all ones' and `all zeros' as BROADCAST. 122 * (Support old BSD in other words). This old BSD 123 * support will go very soon as it messes other things 124 * up. 125 */ 126
127 if (addr == INADDR_ANY || addr == INADDR_BROADCAST)
128 returnIS_BROADCAST;
129
130 mask = ip_get_mask(addr);
131
132 /* 133 * Accept all of the `loopback' class A net. 134 */ 135
136 if ((addr & mask) == htonl(0x7F000000L))
137 returnIS_MYADDR;
138
139 /* 140 * OK, now check the interface addresses. 141 */ 142
143 for (dev = dev_base; dev != NULL; dev = dev->next)
144 { 145 if (!(dev->flags & IFF_UP))
146 continue;
147 /* 148 * If the protocol address of the device is 0 this is special 149 * and means we are address hunting (eg bootp). 150 */ 151
152 if ((dev->pa_addr == 0)/* || (dev->flags&IFF_PROMISC)*/)
153 returnIS_MYADDR;
154 /* 155 * Is it the exact IP address? 156 */ 157
158 if (addr == dev->pa_addr)
159 returnIS_MYADDR;
160 /* 161 * Is it our broadcast address? 162 */ 163
164 if ((dev->flags & IFF_BROADCAST) && addr == dev->pa_brdaddr)
165 returnIS_BROADCAST;
166 /* 167 * Nope. Check for a subnetwork broadcast. 168 */ 169
170 if (((addr ^ dev->pa_addr) & dev->pa_mask) == 0)
171 { 172 if ((addr & ~dev->pa_mask) == 0)
173 returnIS_BROADCAST;
174 if ((addr & ~dev->pa_mask) == ~dev->pa_mask)
175 returnIS_BROADCAST;
176 } 177
178 /* 179 * Nope. Check for Network broadcast. 180 */ 181
182 if (((addr ^ dev->pa_addr) & mask) == 0)
183 { 184 if ((addr & ~mask) == 0)
185 returnIS_BROADCAST;
186 if ((addr & ~mask) == ~mask)
187 returnIS_BROADCAST;
188 } 189 } 190 return 0; /* no match at all */ 191 } 192
193
194 /* 195 * Retrieve our own address. 196 * 197 * Because the loopback address (127.0.0.1) is already recognized 198 * automatically, we can use the loopback interface's address as 199 * our "primary" interface. This is the addressed used by IP et 200 * al when it doesn't know which address to use (i.e. it does not 201 * yet know from or to which interface to go...). 202 */ 203
204 unsignedlongip_my_addr(void)
/* */ 205 { 206 structdevice *dev;
207
208 for (dev = dev_base; dev != NULL; dev = dev->next)
209 { 210 if (dev->flags & IFF_LOOPBACK)
211 return(dev->pa_addr);
212 } 213 return(0);
214 } 215
216 /* 217 * Find an interface that can handle addresses for a certain address. 218 * 219 * This needs optimising, since its relatively trivial to collapse 220 * the two loops into one. 221 */ 222
223 structdevice * ip_dev_check(unsignedlongaddr)
/* */ 224 { 225 structdevice *dev;
226
227 for (dev = dev_base; dev; dev = dev->next)
228 { 229 if (!(dev->flags & IFF_UP))
230 continue;
231 if (!(dev->flags & IFF_POINTOPOINT))
232 continue;
233 if (addr != dev->pa_dstaddr)
234 continue;
235 returndev;
236 } 237 for (dev = dev_base; dev; dev = dev->next)
238 { 239 if (!(dev->flags & IFF_UP))
240 continue;
241 if (dev->flags & IFF_POINTOPOINT)
242 continue;
243 if (dev->pa_mask & (addr ^ dev->pa_addr))
244 continue;
245 returndev;
246 } 247 returnNULL;
248 }