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 unsigned long ip_get_mask(unsigned long addr)
/* ![[previous]](../icons/n_left.png)
![[next]](../icons/right.png)
![[first]](../icons/n_first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
49 {
50 unsigned long dst;
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 int ip_addr_match(unsigned long me, unsigned long him)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
75 {
76 int i;
77 unsigned long mask=0xFFFFFFFF;
78
79 /*
80 * Simple case
81 */
82 if (me == him)
83 return(1);
84
85 /*
86 * Look for a match ending in all 1's
87 */
88
89 for (i = 0; i < 4; i++, me >>= 8, him >>= 8, mask >>= 8)
90 {
91 if ((me & 0xFF) != (him & 0xFF))
92 {
93 /*
94 * The only way this could be a match is for
95 * the rest of addr1 to be 0 or 255.
96 */
97 if (me != 0 && me != mask)
98 return(0);
99 return(1);
100 }
101 }
102 return(1);
103 }
104
105
106 /*
107 * Check the address for our address, broadcasts, etc.
108 *
109 * I intend to fix this to at the very least cache the last
110 * resolved entry.
111 */
112
113 int ip_chk_addr(unsigned long addr)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
114 {
115 struct device *dev;
116 unsigned long mask;
117
118 /*
119 * Accept both `all ones' and `all zeros' as BROADCAST.
120 * (Support old BSD in other words). This old BSD
121 * support will go very soon as it messes other things
122 * up.
123 * Also accept `loopback broadcast' as BROADCAST.
124 */
125
126 if (addr == INADDR_ANY || addr == INADDR_BROADCAST ||
127 addr == htonl(0x7FFFFFFFL))
128 return IS_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 return IS_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 return IS_MYADDR;
154 /*
155 * Is it the exact IP address?
156 */
157
158 if (addr == dev->pa_addr)
159 return IS_MYADDR;
160 /*
161 * Is it our broadcast address?
162 */
163
164 if ((dev->flags & IFF_BROADCAST) && addr == dev->pa_brdaddr)
165 return IS_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 return IS_BROADCAST;
174 if ((addr & ~dev->pa_mask) == ~dev->pa_mask)
175 return IS_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 return IS_BROADCAST;
186 if ((addr & ~mask) == ~mask)
187 return IS_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 address 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 unsigned long ip_my_addr(void)
/* ![[previous]](../icons/left.png)
![[next]](../icons/right.png)
![[first]](../icons/first.png)
![[last]](../icons/last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
205 {
206 struct device *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 struct device * ip_dev_check(unsigned long addr)
/* ![[previous]](../icons/left.png)
![[next]](../icons/n_right.png)
![[first]](../icons/first.png)
![[last]](../icons/n_last.png)
![[top]](../icons/top.png)
![[bottom]](../icons/bottom.png)
![[index]](../icons/index.png)
*/
224 {
225 struct device *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 return dev;
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 return dev;
246 }
247 return NULL;
248 }