📄 dev.c
字号:
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.0.19 05/31/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: Fixed ifconfig up of dud device setting the up flag
30 * Alan Cox: Fixed verify_area errors
31 * Alan Cox: Removed IP_SET_DEV as per Fred's comment. I hope this doesn't give
32 * anything away 8)
33 *
34 * This program is free software; you can redistribute it and/or
35 * modify it under the terms of the GNU General Public License
36 * as published by the Free Software Foundation; either version
37 * 2 of the License, or (at your option) any later version.
38 */
39 #include <asm/segment.h>
40 #include <asm/system.h>
41 #include <asm/bitops.h>
42 #include <linux/config.h>
43 #include <linux/types.h>
44 #include <linux/kernel.h>
45 #include <linux/sched.h>
46 #include <linux/string.h>
47 #include <linux/mm.h>
48 #include <linux/socket.h>
49 #include <linux/sockios.h>
50 #include <linux/in.h>
51 #include <linux/errno.h>
52 #include <linux/interrupt.h>
53 #include <linux/if_ether.h>
54 #include "inet.h"
55 #include "dev.h"
56 #include "eth.h"
57 #include "ip.h"
58 #include "route.h"
59 #include "protocol.h"
60 #include "tcp.h"
61 #include "skbuff.h"
62 #include "sock.h"
63 #include "arp.h"
64 #ifdef CONFIG_AX25
65 #include "ax25.h"
66 #endif
67
68
69 #ifdef CONFIG_IPX
70
71 static struct packet_type ipx_8023_type = {
72 NET16(ETH_P_802_3),
73 0,
74 ipx_rcv,
75 NULL,
76 NULL
77 };
78
79 static struct packet_type ipx_packet_type = {
80 NET16(ETH_P_IPX),
81 0,
82 ipx_rcv,
83 NULL,
84 &ipx_8023_type
85 };
86
87 #endif
88
89 #ifdef CONFIG_AX25
90
91 static struct packet_type ax25_packet_type = {
92 NET16(ETH_P_AX25),
93 0,
94 ax25_rcv,
95 NULL,
96 #ifdef CONFIG_IPX
97 &ipx_packet_type
98 #else
99 NULL
100 #endif
101 };
102 #endif
103
104
105 static struct packet_type arp_packet_type = {
106 NET16(ETH_P_ARP),
107 0, /* copy */
108 arp_rcv,
109 NULL,
110 #ifdef CONFIG_IPX
111 #ifndef CONFIG_AX25
112 &ipx_packet_type
113 #else
114 &ax25_packet_type
115 #endif
116 #else
117 #ifdef CONFIG_AX25
118 &ax25_packet_type
119 #else
120 NULL /* next */
121 #endif
122 #endif
123 };
124
125
126 static struct packet_type ip_packet_type = {
127 NET16(ETH_P_IP),
128 0, /* copy */
129 ip_rcv,
130 NULL,
131 &arp_packet_type
132 };
133
134
135 struct packet_type *ptype_base = &ip_packet_type;
136 static struct sk_buff *volatile backlog = NULL;
137 static unsigned long ip_bcast = 0;
138
139
140 /* Return the lesser of the two values. */
141 static unsigned long
142 min(unsigned long a, unsigned long b)
143 {
144 if (a < b) return(a);
145 return(b);
146 }
147
148
149 /* Determine a default network mask, based on the IP address. */
150 static unsigned long
151 get_mask(unsigned long addr)
152 {
153 unsigned long dst;
154
155 if (addr == 0L)
156 return(0L); /* special case */
157
158 dst = ntohl(addr);
159 if (IN_CLASSA(dst))
160 return(htonl(IN_CLASSA_NET));
161 if (IN_CLASSB(dst))
162 return(htonl(IN_CLASSB_NET));
163 if (IN_CLASSC(dst))
164 return(htonl(IN_CLASSC_NET));
165
166 /* Something else, probably a subnet. */
167 return(0);
168 }
169
170
171 int
172 ip_addr_match(unsigned long me, unsigned long him)
173 {
174 int i;
175 unsigned long mask=0xFFFFFFFF;
176 DPRINTF((DBG_DEV, "ip_addr_match(%s, ", in_ntoa(me)));
177 DPRINTF((DBG_DEV, "%s)\n", in_ntoa(him)));
178
179 if (me == him)
180 return(1);
181 for (i = 0; i < 4; i++, me >>= 8, him >>= 8, mask >>= 8) {
182 if ((me & 0xFF) != (him & 0xFF)) {
183 /*
184 * The only way this could be a match is for
185 * the rest of addr1 to be 0 or 255.
186 */
187 if (me != 0 && me != mask) return(0);
188 return(1);
189 }
190 }
191 return(1);
192 }
193
194
195 /* Check the address for our address, broadcasts, etc. */
196 int chk_addr(unsigned long addr)
197 {
198 struct device *dev;
199 unsigned long mask;
200
201 /* Accept both `all ones' and `all zeros' as BROADCAST. */
202 if (addr == INADDR_ANY || addr == INADDR_BROADCAST)
203 return IS_BROADCAST;
204
205 mask = get_mask(addr);
206
207 /* Accept all of the `loopback' class A net. */
208 if ((addr & mask) == htonl(0x7F000000L))
209 return IS_MYADDR;
210
211 /* OK, now check the interface addresses. */
212 for (dev = dev_base; dev != NULL; dev = dev->next) {
213 if (!(dev->flags & IFF_UP))
214 continue;
215 if ((dev->pa_addr == 0)/* || (dev->flags&IFF_PROMISC)*/)
216 return IS_MYADDR;
217 /* Is it the exact IP address? */
218 if (addr == dev->pa_addr)
219 return IS_MYADDR;
220 /* Is it our broadcast address? */
221 if ((dev->flags & IFF_BROADCAST) && addr == dev->pa_brdaddr)
222 return IS_BROADCAST;
223 /* Nope. Check for a subnetwork broadcast. */
224 if (((addr ^ dev->pa_addr) & dev->pa_mask) == 0) {
225 if ((addr & ~dev->pa_mask) == 0)
226 return IS_BROADCAST;
227 if ((addr & ~dev->pa_mask) == ~dev->pa_mask)
228 return IS_BROADCAST;
229 }
230 /* Nope. Check for Network broadcast. */
231 if (((addr ^ dev->pa_addr) & mask) == 0) {
232 if ((addr & ~mask) == 0)
233 return IS_BROADCAST;
234 if ((addr & ~mask) == ~mask)
235 return IS_BROADCAST;
236 }
237 }
238 return 0; /* no match at all */
239 }
240
241
242 /*
243 * Retrieve our own address.
244 * Because the loopback address (127.0.0.1) is already recognized
245 * automatically, we can use the loopback interface's address as
246 * our "primary" interface. This is the addressed used by IP et
247 * al when it doesn't know which address to use (i.e. it does not
248 * yet know from or to which interface to go...).
249 */
250 unsigned long
251 my_addr(void)
252 {
253 struct device *dev;
254
255 for (dev = dev_base; dev != NULL; dev = dev->next) {
256 if (dev->flags & IFF_LOOPBACK) return(dev->pa_addr);
257 }
258 return(0);
259 }
260
261
262 static int dev_nit=0; /* Number of network taps running */
263
264 /* Add a protocol ID to the list. This will change soon. */
265 void
266 dev_add_pack(struct packet_type *pt)
267 {
268 struct packet_type *p1;
269 pt->next = ptype_base;
270
271 /* Don't use copy counts on ETH_P_ALL. Instead keep a global
272 count of number of these and use it and pt->copy to decide
273 copies */
274 pt->copy=0;
275 if(pt->type==NET16(ETH_P_ALL))
276 dev_nit++; /* I'd like a /dev/nit too one day 8) */
277 else
278 {
279 /* See if we need to copy it. */
280 for (p1 = ptype_base; p1 != NULL; p1 = p1->next) {
281 if (p1->type == pt->type) {
282 pt->copy = 1;
283 break;
284 }
285 }
286 }
287
288 /*
289 * NIT taps must go at the end or inet_bh will leak!
290 */
291
292 if(pt->type==NET16(ETH_P_ALL))
293 {
294 pt->next=NULL;
295 if(ptype_base==NULL)
296 ptype_base=pt;
297 else
298 {
299 for(p1=ptype_base;p1->next!=NULL;p1=p1->next);
300 p1->next=pt;
301 }
302 }
303 else
304 ptype_base = pt;
305 }
306
307
308 /* Remove a protocol ID from the list. This will change soon. */
309 void
310 dev_remove_pack(struct packet_type *pt)
311 {
312 struct packet_type *lpt, *pt1;
313
314 if (pt->type == NET16(ETH_P_ALL))
315 dev_nit--;
316 if (pt == ptype_base) {
317 ptype_base = pt->next;
318 return;
319 }
320
321 lpt = NULL;
322 for (pt1 = ptype_base; pt1->next != NULL; pt1 = pt1->next) {
323 if (pt1->next == pt ) {
324 cli();
325 if (!pt->copy && lpt)
326 lpt->copy = 0;
327 pt1->next = pt->next;
328 sti();
329 return;
330 }
331
332 if (pt1->next -> type == pt ->type && pt->type != NET16(ETH_P_ALL)) {
333 lpt = pt1->next;
334 }
335 }
336 }
337
338
339 /* Find an interface in the list. This will change soon. */
340 struct device *
341 dev_get(char *name)
342 {
343 struct device *dev;
344
345 for (dev = dev_base; dev != NULL; dev = dev->next) {
346 if (strcmp(dev->name, name) == 0)
347 return(dev);
348 }
349 return(NULL);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -