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 <linux/config.h>
19 #include <asm/segment.h>
20 #include <asm/system.h>
21 #include <asm/bitops.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 <net/ip.h>
37 #include <net/route.h>
38 #include <net/protocol.h>
39 #include <net/tcp.h>
40 #include <linux/skbuff.h>
41 #include <net/sock.h>
42 #include <net/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 * Check the address for our address, broadcasts, etc.
72 *
73 * I intend to fix this to at the very least cache the last
74 * resolved entry.
75 */
76
77 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)
*/
78 {
79 struct device *dev;
80 unsigned long mask;
81
82 /*
83 * Accept both `all ones' and `all zeros' as BROADCAST.
84 * (Support old BSD in other words). This old BSD
85 * support will go very soon as it messes other things
86 * up.
87 * Also accept `loopback broadcast' as BROADCAST.
88 */
89
90 if (addr == INADDR_ANY || addr == INADDR_BROADCAST ||
91 addr == htonl(0x7FFFFFFFL))
92 return IS_BROADCAST;
93
94 mask = ip_get_mask(addr);
95
96 /*
97 * Accept all of the `loopback' class A net.
98 */
99
100 if ((addr & mask) == htonl(0x7F000000L))
101 return IS_MYADDR;
102
103 /*
104 * OK, now check the interface addresses. We could
105 * speed this by keeping a dev and a dev_up chain.
106 */
107
108 for (dev = dev_base; dev != NULL; dev = dev->next)
109 {
110 if (!(dev->flags & IFF_UP))
111 continue;
112 /*
113 * If the protocol address of the device is 0 this is special
114 * and means we are address hunting (eg bootp).
115 */
116
117 if ((dev->pa_addr == 0)/* || (dev->flags&IFF_PROMISC)*/)
118 return IS_MYADDR;
119 /*
120 * Is it the exact IP address?
121 */
122
123 if (addr == dev->pa_addr)
124 return IS_MYADDR;
125 /*
126 * Is it our broadcast address?
127 */
128
129 if ((dev->flags & IFF_BROADCAST) && addr == dev->pa_brdaddr)
130 return IS_BROADCAST;
131 /*
132 * Nope. Check for a subnetwork broadcast.
133 */
134
135 if (((addr ^ dev->pa_addr) & dev->pa_mask) == 0)
136 {
137 if ((addr & ~dev->pa_mask) == 0)
138 return IS_BROADCAST;
139 if ((addr & ~dev->pa_mask) == ~dev->pa_mask)
140 return IS_BROADCAST;
141 }
142
143 /*
144 * Nope. Check for Network broadcast.
145 */
146
147 if (((addr ^ dev->pa_addr) & mask) == 0)
148 {
149 if ((addr & ~mask) == 0)
150 return IS_BROADCAST;
151 if ((addr & ~mask) == ~mask)
152 return IS_BROADCAST;
153 }
154 }
155 if(IN_MULTICAST(ntohl(addr)))
156 return IS_MULTICAST;
157 return 0; /* no match at all */
158 }
159
160
161 /*
162 * Retrieve our own address.
163 *
164 * Because the loopback address (127.0.0.1) is already recognized
165 * automatically, we can use the loopback interface's address as
166 * our "primary" interface. This is the address used by IP et
167 * al when it doesn't know which address to use (i.e. it does not
168 * yet know from or to which interface to go...).
169 */
170
171 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)
*/
172 {
173 struct device *dev;
174
175 for (dev = dev_base; dev != NULL; dev = dev->next)
176 {
177 if (dev->flags & IFF_LOOPBACK)
178 return(dev->pa_addr);
179 }
180 return(0);
181 }
182
183 /*
184 * Find an interface that can handle addresses for a certain address.
185 *
186 * This needs optimising, since it's relatively trivial to collapse
187 * the two loops into one.
188 */
189
190 struct device * ip_dev_check(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)
*/
191 {
192 struct device *dev;
193
194 for (dev = dev_base; dev; dev = dev->next)
195 {
196 if (!(dev->flags & IFF_UP))
197 continue;
198 if (!(dev->flags & IFF_POINTOPOINT))
199 continue;
200 if (addr != dev->pa_dstaddr)
201 continue;
202 return dev;
203 }
204 for (dev = dev_base; dev; dev = dev->next)
205 {
206 if (!(dev->flags & IFF_UP))
207 continue;
208 if (dev->flags & IFF_POINTOPOINT)
209 continue;
210 if (dev->pa_mask & (addr ^ dev->pa_addr))
211 continue;
212 return dev;
213 }
214 return NULL;
215 }
216
217 /*
218 * Find the first device with a given source address.
219 */
220
221 struct device *ip_dev_find(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)
*/
222 {
223 struct device *dev;
224 for(dev = dev_base; dev; dev=dev->next)
225 {
226 if((dev->flags&IFF_UP) && dev->pa_addr==addr)
227 return dev;
228 }
229 return NULL;
230 }