|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that the above copyright notice and this paragraph are
7: * duplicated in all such forms and that any documentation,
8: * advertising materials, and other materials related to such
9: * distribution and use acknowledge that the software was developed
10: * by the University of California, Berkeley. The name of the
11: * University may not be used to endorse or promote products derived
12: * from this software without specific prior written permission.
13: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16: *
17: * @(#)in.c 7.9 (Berkeley) 6/29/88
18: */
19:
20: #include "param.h"
21: #include "ioctl.h"
22: #include "mbuf.h"
23: #include "protosw.h"
24: #include "socket.h"
25: #include "socketvar.h"
26: #include "uio.h"
27: #include "dir.h"
28: #include "user.h"
29: #include "in_systm.h"
30: #include "../net/if.h"
31: #include "../net/route.h"
32: #include "../net/af.h"
33: #include "in.h"
34: #include "in_var.h"
35:
36: #ifdef INET
37: inet_hash(sin, hp)
38: register struct sockaddr_in *sin;
39: struct afhash *hp;
40: {
41: register u_long n;
42:
43: n = in_netof(sin->sin_addr);
44: if (n)
45: while ((n & 0xff) == 0)
46: n >>= 8;
47: hp->afh_nethash = n;
48: hp->afh_hosthash = ntohl(sin->sin_addr.s_addr);
49: }
50:
51: inet_netmatch(sin1, sin2)
52: struct sockaddr_in *sin1, *sin2;
53: {
54:
55: return (in_netof(sin1->sin_addr) == in_netof(sin2->sin_addr));
56: }
57:
58: /*
59: * Formulate an Internet address from network + host.
60: */
61: struct in_addr
62: in_makeaddr(net, host)
63: u_long net, host;
64: {
65: register struct in_ifaddr *ia;
66: register u_long mask;
67: u_long addr;
68:
69: if (IN_CLASSA(net))
70: mask = IN_CLASSA_HOST;
71: else if (IN_CLASSB(net))
72: mask = IN_CLASSB_HOST;
73: else
74: mask = IN_CLASSC_HOST;
75: for (ia = in_ifaddr; ia; ia = ia->ia_next)
76: if ((ia->ia_netmask & net) == ia->ia_net) {
77: mask = ~ia->ia_subnetmask;
78: break;
79: }
80: addr = htonl(net | (host & mask));
81: return (*(struct in_addr *)&addr);
82: }
83:
84: /*
85: * Return the network number from an internet address.
86: */
87: u_long
88: in_netof(in)
89: struct in_addr in;
90: {
91: register u_long i = ntohl(in.s_addr);
92: register u_long net;
93: register struct in_ifaddr *ia;
94:
95: if (IN_CLASSA(i))
96: net = i & IN_CLASSA_NET;
97: else if (IN_CLASSB(i))
98: net = i & IN_CLASSB_NET;
99: else if (IN_CLASSC(i))
100: net = i & IN_CLASSC_NET;
101: else
102: return (0);
103:
104: /*
105: * Check whether network is a subnet;
106: * if so, return subnet number.
107: */
108: for (ia = in_ifaddr; ia; ia = ia->ia_next)
109: if (net == ia->ia_net)
110: return (i & ia->ia_subnetmask);
111: return (net);
112: }
113:
114: /*
115: * Return the host portion of an internet address.
116: */
117: u_long
118: in_lnaof(in)
119: struct in_addr in;
120: {
121: register u_long i = ntohl(in.s_addr);
122: register u_long net, host;
123: register struct in_ifaddr *ia;
124:
125: if (IN_CLASSA(i)) {
126: net = i & IN_CLASSA_NET;
127: host = i & IN_CLASSA_HOST;
128: } else if (IN_CLASSB(i)) {
129: net = i & IN_CLASSB_NET;
130: host = i & IN_CLASSB_HOST;
131: } else if (IN_CLASSC(i)) {
132: net = i & IN_CLASSC_NET;
133: host = i & IN_CLASSC_HOST;
134: } else
135: return (i);
136:
137: /*
138: * Check whether network is a subnet;
139: * if so, use the modified interpretation of `host'.
140: */
141: for (ia = in_ifaddr; ia; ia = ia->ia_next)
142: if (net == ia->ia_net)
143: return (host &~ ia->ia_subnetmask);
144: return (host);
145: }
146:
147: #ifndef SUBNETSARELOCAL
148: #define SUBNETSARELOCAL 1
149: #endif
150: int subnetsarelocal = SUBNETSARELOCAL;
151: /*
152: * Return 1 if an internet address is for a ``local'' host
153: * (one to which we have a connection). If subnetsarelocal
154: * is true, this includes other subnets of the local net.
155: * Otherwise, it includes only the directly-connected (sub)nets.
156: */
157: in_localaddr(in)
158: struct in_addr in;
159: {
160: register u_long i = ntohl(in.s_addr);
161: register struct in_ifaddr *ia;
162:
163: if (subnetsarelocal) {
164: for (ia = in_ifaddr; ia; ia = ia->ia_next)
165: if ((i & ia->ia_netmask) == ia->ia_net)
166: return (1);
167: } else {
168: for (ia = in_ifaddr; ia; ia = ia->ia_next)
169: if ((i & ia->ia_subnetmask) == ia->ia_subnet)
170: return (1);
171: }
172: return (0);
173: }
174:
175: /*
176: * Determine whether an IP address is in a reserved set of addresses
177: * that may not be forwarded, or whether datagrams to that destination
178: * may be forwarded.
179: */
180: in_canforward(in)
181: struct in_addr in;
182: {
183: register u_long i = ntohl(in.s_addr);
184: register u_long net;
185:
186: if (IN_EXPERIMENTAL(i))
187: return (0);
188: if (IN_CLASSA(i)) {
189: net = i & IN_CLASSA_NET;
190: if (net == 0 || net == IN_LOOPBACKNET)
191: return (0);
192: }
193: return (1);
194: }
195:
196: int in_interfaces; /* number of external internet interfaces */
197: extern struct ifnet loif;
198:
199: /*
200: * Generic internet control operations (ioctl's).
201: * Ifp is 0 if not an interface-specific ioctl.
202: */
203: /* ARGSUSED */
204: in_control(so, cmd, data, ifp)
205: struct socket *so;
206: int cmd;
207: caddr_t data;
208: register struct ifnet *ifp;
209: {
210: register struct ifreq *ifr = (struct ifreq *)data;
211: register struct in_ifaddr *ia = 0;
212: struct ifaddr *ifa;
213: struct mbuf *m;
214: int error;
215:
216: /*
217: * Find address for this interface, if it exists.
218: */
219: if (ifp)
220: for (ia = in_ifaddr; ia; ia = ia->ia_next)
221: if (ia->ia_ifp == ifp)
222: break;
223:
224: switch (cmd) {
225:
226: case SIOCSIFADDR:
227: case SIOCSIFNETMASK:
228: case SIOCSIFDSTADDR:
229: if (!suser())
230: return (u.u_error);
231:
232: if (ifp == 0)
233: panic("in_control");
234: if (ia == (struct in_ifaddr *)0) {
235: m = m_getclr(M_WAIT, MT_IFADDR);
236: if (m == (struct mbuf *)NULL)
237: return (ENOBUFS);
238: if (ia = in_ifaddr) {
239: for ( ; ia->ia_next; ia = ia->ia_next)
240: ;
241: ia->ia_next = mtod(m, struct in_ifaddr *);
242: } else
243: in_ifaddr = mtod(m, struct in_ifaddr *);
244: ia = mtod(m, struct in_ifaddr *);
245: if (ifa = ifp->if_addrlist) {
246: for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
247: ;
248: ifa->ifa_next = (struct ifaddr *) ia;
249: } else
250: ifp->if_addrlist = (struct ifaddr *) ia;
251: ia->ia_ifp = ifp;
252: IA_SIN(ia)->sin_family = AF_INET;
253: if (ifp != &loif)
254: in_interfaces++;
255: }
256: break;
257:
258: case SIOCSIFBRDADDR:
259: if (!suser())
260: return (u.u_error);
261: /* FALLTHROUGH */
262:
263: default:
264: if (ia == (struct in_ifaddr *)0)
265: return (EADDRNOTAVAIL);
266: break;
267: }
268:
269: switch (cmd) {
270:
271: case SIOCGIFADDR:
272: ifr->ifr_addr = ia->ia_addr;
273: break;
274:
275: case SIOCGIFBRDADDR:
276: if ((ifp->if_flags & IFF_BROADCAST) == 0)
277: return (EINVAL);
278: ifr->ifr_dstaddr = ia->ia_broadaddr;
279: break;
280:
281: case SIOCGIFDSTADDR:
282: if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
283: return (EINVAL);
284: ifr->ifr_dstaddr = ia->ia_dstaddr;
285: break;
286:
287: case SIOCGIFNETMASK:
288: #define satosin(sa) ((struct sockaddr_in *)(sa))
289: satosin(&ifr->ifr_addr)->sin_family = AF_INET;
290: satosin(&ifr->ifr_addr)->sin_addr.s_addr = htonl(ia->ia_subnetmask);
291: break;
292:
293: case SIOCSIFDSTADDR:
294: {
295: struct sockaddr oldaddr;
296:
297: if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
298: return (EINVAL);
299: oldaddr = ia->ia_dstaddr;
300: ia->ia_dstaddr = ifr->ifr_dstaddr;
301: if (ifp->if_ioctl &&
302: (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia))) {
303: ia->ia_dstaddr = oldaddr;
304: return (error);
305: }
306: if (ia->ia_flags & IFA_ROUTE) {
307: rtinit(&oldaddr, &ia->ia_addr, (int)SIOCDELRT,
308: RTF_HOST);
309: rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCADDRT,
310: RTF_HOST|RTF_UP);
311: }
312: }
313: break;
314:
315: case SIOCSIFBRDADDR:
316: if ((ifp->if_flags & IFF_BROADCAST) == 0)
317: return (EINVAL);
318: ia->ia_broadaddr = ifr->ifr_broadaddr;
319: break;
320:
321: case SIOCSIFADDR:
322: return (in_ifinit(ifp, ia,
323: (struct sockaddr_in *) &ifr->ifr_addr));
324:
325: case SIOCSIFNETMASK:
326: ia->ia_subnetmask = ntohl(satosin(&ifr->ifr_addr)->sin_addr.s_addr);
327: break;
328:
329: default:
330: if (ifp == 0 || ifp->if_ioctl == 0)
331: return (EOPNOTSUPP);
332: return ((*ifp->if_ioctl)(ifp, cmd, data));
333: }
334: return (0);
335: }
336:
337: /*
338: * Initialize an interface's internet address
339: * and routing table entry.
340: */
341: in_ifinit(ifp, ia, sin)
342: register struct ifnet *ifp;
343: register struct in_ifaddr *ia;
344: struct sockaddr_in *sin;
345: {
346: register u_long i = ntohl(sin->sin_addr.s_addr);
347: struct sockaddr oldaddr;
348: struct sockaddr_in netaddr;
349: int s = splimp(), error;
350:
351: oldaddr = ia->ia_addr;
352: ia->ia_addr = *(struct sockaddr *)sin;
353:
354: /*
355: * Give the interface a chance to initialize
356: * if this is its first address,
357: * and to validate the address if necessary.
358: */
359: if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
360: splx(s);
361: ia->ia_addr = oldaddr;
362: return (error);
363: }
364:
365: /*
366: * Delete any previous route for an old address.
367: */
368: bzero((caddr_t)&netaddr, sizeof (netaddr));
369: netaddr.sin_family = AF_INET;
370: if (ia->ia_flags & IFA_ROUTE) {
371: if (ifp->if_flags & IFF_LOOPBACK)
372: rtinit(&oldaddr, &oldaddr, (int)SIOCDELRT, RTF_HOST);
373: else if (ifp->if_flags & IFF_POINTOPOINT)
374: rtinit(&ia->ia_dstaddr, &oldaddr, (int)SIOCDELRT,
375: RTF_HOST);
376: else {
377: netaddr.sin_addr = in_makeaddr(ia->ia_subnet,
378: INADDR_ANY);
379: rtinit((struct sockaddr *)&netaddr, &oldaddr,
380: (int)SIOCDELRT, 0);
381: }
382: ia->ia_flags &= ~IFA_ROUTE;
383: }
384: if (IN_CLASSA(i))
385: ia->ia_netmask = IN_CLASSA_NET;
386: else if (IN_CLASSB(i))
387: ia->ia_netmask = IN_CLASSB_NET;
388: else
389: ia->ia_netmask = IN_CLASSC_NET;
390: ia->ia_net = i & ia->ia_netmask;
391: /*
392: * The subnet mask includes at least the standard network part,
393: * but may already have been set to a larger value.
394: */
395: ia->ia_subnetmask |= ia->ia_netmask;
396: ia->ia_subnet = i & ia->ia_subnetmask;
397: if (ifp->if_flags & IFF_BROADCAST) {
398: ia->ia_broadaddr.sa_family = AF_INET;
399: ((struct sockaddr_in *)(&ia->ia_broadaddr))->sin_addr =
400: in_makeaddr(ia->ia_subnet, INADDR_BROADCAST);
401: ia->ia_netbroadcast.s_addr =
402: htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask));
403: }
404: /*
405: * Add route for the network.
406: */
407: if (ifp->if_flags & IFF_LOOPBACK)
408: rtinit(&ia->ia_addr, &ia->ia_addr, (int)SIOCADDRT,
409: RTF_HOST|RTF_UP);
410: else if (ifp->if_flags & IFF_POINTOPOINT)
411: rtinit(&ia->ia_dstaddr, &ia->ia_addr, (int)SIOCADDRT,
412: RTF_HOST|RTF_UP);
413: else {
414: netaddr.sin_addr = in_makeaddr(ia->ia_subnet, INADDR_ANY);
415: rtinit((struct sockaddr *)&netaddr, &ia->ia_addr,
416: (int)SIOCADDRT, RTF_UP);
417: }
418: ia->ia_flags |= IFA_ROUTE;
419: splx(s);
420: return (0);
421: }
422:
423: /*
424: * Return address info for specified internet network.
425: */
426: struct in_ifaddr *
427: in_iaonnetof(net)
428: u_long net;
429: {
430: register struct in_ifaddr *ia;
431:
432: for (ia = in_ifaddr; ia; ia = ia->ia_next)
433: if (ia->ia_subnet == net)
434: return (ia);
435: return ((struct in_ifaddr *)0);
436: }
437:
438: /*
439: * Return 1 if the address might be a local broadcast address.
440: */
441: in_broadcast(in)
442: struct in_addr in;
443: {
444: register struct in_ifaddr *ia;
445: u_long t;
446:
447: /*
448: * Look through the list of addresses for a match
449: * with a broadcast address.
450: */
451: for (ia = in_ifaddr; ia; ia = ia->ia_next)
452: if (ia->ia_ifp->if_flags & IFF_BROADCAST) {
453: if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr == in.s_addr)
454: return (1);
455: /*
456: * Check for old-style (host 0) broadcast.
457: */
458: if ((t = ntohl(in.s_addr)) == ia->ia_subnet || t == ia->ia_net)
459: return (1);
460: }
461: if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY)
462: return (1);
463: return (0);
464: }
465: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.