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/types.h>
22 #include <linux/kernel.h>
23 #include <linux/sched.h>
24 #include <linux/string.h>
25 #include <linux/mm.h>
26 #include <linux/socket.h>
27 #include <linux/sockios.h>
28 #include <linux/in.h>
29 #include <linux/errno.h>
30 #include <linux/interrupt.h>
31 #include <linux/if_ether.h>
32 #include <linux/inet.h>
33 #include <linux/netdevice.h>
34 #include <linux/etherdevice.h>
35 #include "ip.h"
36 #include "route.h"
37 #include "protocol.h"
38 #include "tcp.h"
39 #include <linux/skbuff.h>
40 #include "sock.h"
41 #include "arp.h"
42
43 /* 44 * Determine a default network mask, based on the IP address. 45 */ 46
47 unsignedlongip_get_mask(unsignedlongaddr)
/* */ 48 { 49 unsignedlongdst;
50
51 if (addr == 0L)
52 return(0L); /* special case */ 53
54 dst = ntohl(addr);
55 if (IN_CLASSA(dst))
56 return(htonl(IN_CLASSA_NET));
57 if (IN_CLASSB(dst))
58 return(htonl(IN_CLASSB_NET));
59 if (IN_CLASSC(dst))
60 return(htonl(IN_CLASSC_NET));
61
62 /* 63 * Something else, probably a multicast. 64 */ 65
66 return(0);
67 } 68
69 /* 70 * Check the address for our address, broadcasts, etc. 71 * 72 * I intend to fix this to at the very least cache the last 73 * resolved entry. 74 */ 75
76 intip_chk_addr(unsignedlongaddr)
/* */ 77 { 78 structdevice *dev;
79 unsignedlongmask;
80
81 /* 82 * Accept both `all ones' and `all zeros' as BROADCAST. 83 * (Support old BSD in other words). This old BSD 84 * support will go very soon as it messes other things 85 * up. 86 * Also accept `loopback broadcast' as BROADCAST. 87 */ 88
89 if (addr == INADDR_ANY || addr == INADDR_BROADCAST ||
90 addr == htonl(0x7FFFFFFFL))
91 returnIS_BROADCAST;
92
93 mask = ip_get_mask(addr);
94
95 /* 96 * Accept all of the `loopback' class A net. 97 */ 98
99 if ((addr & mask) == htonl(0x7F000000L))
100 returnIS_MYADDR;
101
102 /* 103 * OK, now check the interface addresses. 104 */ 105
106 for (dev = dev_base; dev != NULL; dev = dev->next)
107 { 108 if (!(dev->flags & IFF_UP))
109 continue;
110 /* 111 * If the protocol address of the device is 0 this is special 112 * and means we are address hunting (eg bootp). 113 */ 114
115 if ((dev->pa_addr == 0)/* || (dev->flags&IFF_PROMISC)*/)
116 returnIS_MYADDR;
117 /* 118 * Is it the exact IP address? 119 */ 120
121 if (addr == dev->pa_addr)
122 returnIS_MYADDR;
123 /* 124 * Is it our broadcast address? 125 */ 126
127 if ((dev->flags & IFF_BROADCAST) && addr == dev->pa_brdaddr)
128 returnIS_BROADCAST;
129 /* 130 * Nope. Check for a subnetwork broadcast. 131 */ 132
133 if (((addr ^ dev->pa_addr) & dev->pa_mask) == 0)
134 { 135 if ((addr & ~dev->pa_mask) == 0)
136 returnIS_BROADCAST;
137 if ((addr & ~dev->pa_mask) == ~dev->pa_mask)
138 returnIS_BROADCAST;
139 } 140
141 /* 142 * Nope. Check for Network broadcast. 143 */ 144
145 if (((addr ^ dev->pa_addr) & mask) == 0)
146 { 147 if ((addr & ~mask) == 0)
148 returnIS_BROADCAST;
149 if ((addr & ~mask) == ~mask)
150 returnIS_BROADCAST;
151 } 152 } 153 if(IN_MULTICAST(ntohl(addr)))
154 returnIS_MULTICAST;
155 return 0; /* no match at all */ 156 } 157
158
159 /* 160 * Retrieve our own address. 161 * 162 * Because the loopback address (127.0.0.1) is already recognized 163 * automatically, we can use the loopback interface's address as 164 * our "primary" interface. This is the address used by IP et 165 * al when it doesn't know which address to use (i.e. it does not 166 * yet know from or to which interface to go...). 167 */ 168
169 unsignedlongip_my_addr(void)
/* */ 170 { 171 structdevice *dev;
172
173 for (dev = dev_base; dev != NULL; dev = dev->next)
174 { 175 if (dev->flags & IFF_LOOPBACK)
176 return(dev->pa_addr);
177 } 178 return(0);
179 } 180
181 /* 182 * Find an interface that can handle addresses for a certain address. 183 * 184 * This needs optimising, since its relatively trivial to collapse 185 * the two loops into one. 186 */ 187
188 structdevice * ip_dev_check(unsignedlongaddr)
/* */ 189 { 190 structdevice *dev;
191
192 for (dev = dev_base; dev; dev = dev->next)
193 { 194 if (!(dev->flags & IFF_UP))
195 continue;
196 if (!(dev->flags & IFF_POINTOPOINT))
197 continue;
198 if (addr != dev->pa_dstaddr)
199 continue;
200 returndev;
201 } 202 for (dev = dev_base; dev; dev = dev->next)
203 { 204 if (!(dev->flags & IFF_UP))
205 continue;
206 if (dev->flags & IFF_POINTOPOINT)
207 continue;
208 if (dev->pa_mask & (addr ^ dev->pa_addr))
209 continue;
210 returndev;
211 } 212 returnNULL;
213 }