|
|
1.1 root 1: /*
2: * Copyright (c) 1982, 1986, 1991 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. All advertising materials mentioning features or use of this software
14: * must display the following acknowledgement:
15: * This product includes software developed by the University of
16: * California, Berkeley and its contributors.
17: * 4. Neither the name of the University nor the names of its contributors
18: * may be used to endorse or promote products derived from this software
19: * without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31: * SUCH DAMAGE.
32: *
1.1.1.2 ! root 33: * from: @(#)in.c 7.17 (Berkeley) 4/20/91
! 34: * in.c,v 1.4 1993/06/10 05:16:46 deraadt Exp
1.1 root 35: */
36:
37: #include "param.h"
38: #include "ioctl.h"
39: #include "mbuf.h"
40: #include "socket.h"
41: #include "socketvar.h"
42: #include "in_systm.h"
43: #include "net/if.h"
44: #include "net/route.h"
45: #include "net/af.h"
46: #include "in.h"
47: #include "in_var.h"
48:
49: #ifdef INET
50: /*
51: * Formulate an Internet address from network + host.
52: */
53: struct in_addr
54: in_makeaddr(net, host)
55: u_long net, host;
56: {
57: register struct in_ifaddr *ia;
58: register u_long mask;
59: u_long addr;
60:
61: if (IN_CLASSA(net))
62: mask = IN_CLASSA_HOST;
63: else if (IN_CLASSB(net))
64: mask = IN_CLASSB_HOST;
65: else
66: mask = IN_CLASSC_HOST;
67: for (ia = in_ifaddr; ia; ia = ia->ia_next)
68: if ((ia->ia_netmask & net) == ia->ia_net) {
69: mask = ~ia->ia_subnetmask;
70: break;
71: }
72: addr = htonl(net | (host & mask));
73: return (*(struct in_addr *)&addr);
74: }
75:
76: /*
77: * Return the network number from an internet address.
78: */
79: u_long
80: in_netof(in)
81: struct in_addr in;
82: {
83: register u_long i = ntohl(in.s_addr);
84: register u_long net;
85: register struct in_ifaddr *ia;
86:
87: if (IN_CLASSA(i))
88: net = i & IN_CLASSA_NET;
89: else if (IN_CLASSB(i))
90: net = i & IN_CLASSB_NET;
91: else if (IN_CLASSC(i))
92: net = i & IN_CLASSC_NET;
93: else
94: return (0);
95:
96: /*
97: * Check whether network is a subnet;
98: * if so, return subnet number.
99: */
100: for (ia = in_ifaddr; ia; ia = ia->ia_next)
101: if (net == ia->ia_net)
102: return (i & ia->ia_subnetmask);
103: return (net);
104: }
105:
106: /*
107: * Compute and save network mask as sockaddr from an internet address.
108: */
109: in_sockmaskof(in, sockmask)
110: struct in_addr in;
111: register struct sockaddr_in *sockmask;
112: {
113: register u_long net;
114: register u_long mask;
115: {
116: register u_long i = ntohl(in.s_addr);
117:
118: if (i == 0)
119: net = 0, mask = 0;
120: else if (IN_CLASSA(i))
121: net = i & IN_CLASSA_NET, mask = IN_CLASSA_NET;
122: else if (IN_CLASSB(i))
123: net = i & IN_CLASSB_NET, mask = IN_CLASSB_NET;
124: else if (IN_CLASSC(i))
125: net = i & IN_CLASSC_NET, mask = IN_CLASSC_NET;
126: else
127: net = i, mask = -1;
128: }
129: {
130: register struct in_ifaddr *ia;
131: /*
132: * Check whether network is a subnet;
133: * if so, return subnet number.
134: */
135: for (ia = in_ifaddr; ia; ia = ia->ia_next)
136: if (net == ia->ia_net)
137: mask = ia->ia_subnetmask;
138: }
139: {
140: register char *cpbase = (char *)&(sockmask->sin_addr);
141: register char *cp = (char *)(1 + &(sockmask->sin_addr));
142:
143: sockmask->sin_addr.s_addr = htonl(mask);
144: sockmask->sin_len = 0;
145: while (--cp >= cpbase)
146: if (*cp) {
147: sockmask->sin_len = 1 + cp - (caddr_t)sockmask;
148: break;
149: }
150: }
151: }
152:
153: /*
154: * Return the host portion of an internet address.
155: */
156: u_long
157: in_lnaof(in)
158: struct in_addr in;
159: {
160: register u_long i = ntohl(in.s_addr);
161: register u_long net, host;
162: register struct in_ifaddr *ia;
163:
164: if (IN_CLASSA(i)) {
165: net = i & IN_CLASSA_NET;
166: host = i & IN_CLASSA_HOST;
167: } else if (IN_CLASSB(i)) {
168: net = i & IN_CLASSB_NET;
169: host = i & IN_CLASSB_HOST;
170: } else if (IN_CLASSC(i)) {
171: net = i & IN_CLASSC_NET;
172: host = i & IN_CLASSC_HOST;
173: } else
174: return (i);
175:
176: /*
177: * Check whether network is a subnet;
178: * if so, use the modified interpretation of `host'.
179: */
180: for (ia = in_ifaddr; ia; ia = ia->ia_next)
181: if (net == ia->ia_net)
182: return (host &~ ia->ia_subnetmask);
183: return (host);
184: }
185:
186: #ifndef SUBNETSARELOCAL
187: #define SUBNETSARELOCAL 1
188: #endif
189: int subnetsarelocal = SUBNETSARELOCAL;
190: /*
191: * Return 1 if an internet address is for a ``local'' host
192: * (one to which we have a connection). If subnetsarelocal
193: * is true, this includes other subnets of the local net.
194: * Otherwise, it includes only the directly-connected (sub)nets.
195: */
196: in_localaddr(in)
197: struct in_addr in;
198: {
199: register u_long i = ntohl(in.s_addr);
200: register struct in_ifaddr *ia;
201:
202: if (subnetsarelocal) {
203: for (ia = in_ifaddr; ia; ia = ia->ia_next)
204: if ((i & ia->ia_netmask) == ia->ia_net)
205: return (1);
206: } else {
207: for (ia = in_ifaddr; ia; ia = ia->ia_next)
208: if ((i & ia->ia_subnetmask) == ia->ia_subnet)
209: return (1);
210: }
211: return (0);
212: }
213:
214: /*
215: * Determine whether an IP address is in a reserved set of addresses
216: * that may not be forwarded, or whether datagrams to that destination
217: * may be forwarded.
218: */
219: in_canforward(in)
220: struct in_addr in;
221: {
222: register u_long i = ntohl(in.s_addr);
223: register u_long net;
224:
225: if (IN_EXPERIMENTAL(i))
226: return (0);
227: if (IN_CLASSA(i)) {
228: net = i & IN_CLASSA_NET;
1.1.1.2 ! root 229: if (net == 0 || net == (IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
1.1 root 230: return (0);
231: }
232: return (1);
233: }
234:
235: int in_interfaces; /* number of external internet interfaces */
236: extern struct ifnet loif;
237:
238: /*
239: * Generic internet control operations (ioctl's).
240: * Ifp is 0 if not an interface-specific ioctl.
241: */
242: /* ARGSUSED */
243: in_control(so, cmd, data, ifp)
244: struct socket *so;
245: int cmd;
246: caddr_t data;
247: register struct ifnet *ifp;
248: {
249: register struct ifreq *ifr = (struct ifreq *)data;
250: register struct in_ifaddr *ia = 0;
251: register struct ifaddr *ifa;
252: struct in_ifaddr *oia;
253: struct in_aliasreq *ifra = (struct in_aliasreq *)data;
254: struct mbuf *m;
255: struct sockaddr_in oldaddr;
256: int error, hostIsNew, maskIsNew;
257: u_long i;
258:
259: /*
260: * Find address for this interface, if it exists.
261: */
262: if (ifp)
263: for (ia = in_ifaddr; ia; ia = ia->ia_next)
264: if (ia->ia_ifp == ifp)
265: break;
266:
267: switch (cmd) {
268:
269: case SIOCAIFADDR:
270: case SIOCDIFADDR:
271: if (ifra->ifra_addr.sin_family == AF_INET)
272: for (oia = ia; ia; ia = ia->ia_next) {
273: if (ia->ia_ifp == ifp &&
274: ia->ia_addr.sin_addr.s_addr ==
275: ifra->ifra_addr.sin_addr.s_addr)
276: break;
277: }
278: if (cmd == SIOCDIFADDR && ia == 0)
279: return (EADDRNOTAVAIL);
280: /* FALLTHROUGH */
281: case SIOCSIFADDR:
282: case SIOCSIFNETMASK:
283: case SIOCSIFDSTADDR:
284: if ((so->so_state & SS_PRIV) == 0)
285: return (EPERM);
286:
287: if (ifp == 0)
288: panic("in_control");
289: if (ia == (struct in_ifaddr *)0) {
290: m = m_getclr(M_WAIT, MT_IFADDR);
291: if (m == (struct mbuf *)NULL)
292: return (ENOBUFS);
293: if (ia = in_ifaddr) {
294: for ( ; ia->ia_next; ia = ia->ia_next)
295: ;
296: ia->ia_next = mtod(m, struct in_ifaddr *);
297: } else
298: in_ifaddr = mtod(m, struct in_ifaddr *);
299: ia = mtod(m, struct in_ifaddr *);
300: if (ifa = ifp->if_addrlist) {
301: for ( ; ifa->ifa_next; ifa = ifa->ifa_next)
302: ;
303: ifa->ifa_next = (struct ifaddr *) ia;
304: } else
305: ifp->if_addrlist = (struct ifaddr *) ia;
306: ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
307: ia->ia_ifa.ifa_dstaddr
308: = (struct sockaddr *)&ia->ia_dstaddr;
309: ia->ia_ifa.ifa_netmask
310: = (struct sockaddr *)&ia->ia_sockmask;
311: ia->ia_sockmask.sin_len = 8;
312: if (ifp->if_flags & IFF_BROADCAST) {
313: ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
314: ia->ia_broadaddr.sin_family = AF_INET;
315: }
316: ia->ia_ifp = ifp;
317: if (ifp != &loif)
318: in_interfaces++;
319: }
320: break;
321:
322: case SIOCSIFBRDADDR:
323: if ((so->so_state & SS_PRIV) == 0)
324: return (EPERM);
325: /* FALLTHROUGH */
326:
327: case SIOCGIFADDR:
328: case SIOCGIFNETMASK:
329: case SIOCGIFDSTADDR:
330: case SIOCGIFBRDADDR:
331: if (ia == (struct in_ifaddr *)0)
332: return (EADDRNOTAVAIL);
333: break;
334:
335: default:
336: return (EOPNOTSUPP);
337: break;
338: }
339: switch (cmd) {
340:
341: case SIOCGIFADDR:
342: *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_addr;
343: break;
344:
345: case SIOCGIFBRDADDR:
346: if ((ifp->if_flags & IFF_BROADCAST) == 0)
347: return (EINVAL);
348: *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_broadaddr;
349: break;
350:
351: case SIOCGIFDSTADDR:
352: if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
353: return (EINVAL);
354: *((struct sockaddr_in *)&ifr->ifr_dstaddr) = ia->ia_dstaddr;
355: break;
356:
357: case SIOCGIFNETMASK:
358: *((struct sockaddr_in *)&ifr->ifr_addr) = ia->ia_sockmask;
359: break;
360:
361: case SIOCSIFDSTADDR:
362: if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
363: return (EINVAL);
364: oldaddr = ia->ia_dstaddr;
365: ia->ia_dstaddr = *(struct sockaddr_in *)&ifr->ifr_dstaddr;
366: if (ifp->if_ioctl &&
367: (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR, ia))) {
368: ia->ia_dstaddr = oldaddr;
369: return (error);
370: }
371: if (ia->ia_flags & IFA_ROUTE) {
372: ia->ia_ifa.ifa_dstaddr = (struct sockaddr *)&oldaddr;
373: rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
374: ia->ia_ifa.ifa_dstaddr =
375: (struct sockaddr *)&ia->ia_dstaddr;
376: rtinit(&(ia->ia_ifa), (int)RTM_ADD, RTF_HOST|RTF_UP);
377: }
378: break;
379:
380: case SIOCSIFBRDADDR:
381: if ((ifp->if_flags & IFF_BROADCAST) == 0)
382: return (EINVAL);
383: ia->ia_broadaddr = *(struct sockaddr_in *)&ifr->ifr_broadaddr;
384: break;
385:
386: case SIOCSIFADDR:
387: return (in_ifinit(ifp, ia,
388: (struct sockaddr_in *) &ifr->ifr_addr, 1));
389:
390: case SIOCSIFNETMASK:
391: i = ifra->ifra_addr.sin_addr.s_addr;
392: ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr = i);
393: break;
394:
395: case SIOCAIFADDR:
396: maskIsNew = 0;
397: hostIsNew = 1;
398: error = 0;
399: if (ia->ia_addr.sin_family == AF_INET) {
400: if (ifra->ifra_addr.sin_len == 0) {
401: ifra->ifra_addr = ia->ia_addr;
402: hostIsNew = 0;
403: } else if (ifra->ifra_addr.sin_addr.s_addr ==
404: ia->ia_addr.sin_addr.s_addr)
405: hostIsNew = 0;
406: }
407: if (ifra->ifra_mask.sin_len) {
408: in_ifscrub(ifp, ia);
409: ia->ia_sockmask = ifra->ifra_mask;
410: ia->ia_subnetmask =
411: ntohl(ia->ia_sockmask.sin_addr.s_addr);
412: maskIsNew = 1;
413: }
414: if ((ifp->if_flags & IFF_POINTOPOINT) &&
415: (ifra->ifra_dstaddr.sin_family == AF_INET)) {
416: in_ifscrub(ifp, ia);
417: ia->ia_dstaddr = ifra->ifra_dstaddr;
418: maskIsNew = 1; /* We lie; but the effect's the same */
419: }
420: if (ifra->ifra_addr.sin_family == AF_INET &&
421: (hostIsNew || maskIsNew))
422: error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
423: if ((ifp->if_flags & IFF_BROADCAST) &&
424: (ifra->ifra_broadaddr.sin_family == AF_INET))
425: ia->ia_broadaddr = ifra->ifra_broadaddr;
426: return (error);
427:
428: case SIOCDIFADDR:
429: in_ifscrub(ifp, ia);
430: if ((ifa = ifp->if_addrlist) == (struct ifaddr *)ia)
431: ifp->if_addrlist = ifa->ifa_next;
432: else {
433: while (ifa->ifa_next &&
434: (ifa->ifa_next != (struct ifaddr *)ia))
435: ifa = ifa->ifa_next;
436: if (ifa->ifa_next)
437: ifa->ifa_next = ((struct ifaddr *)ia)->ifa_next;
438: else
439: printf("Couldn't unlink inifaddr from ifp\n");
440: }
441: oia = ia;
442: if (oia == (ia = in_ifaddr))
443: in_ifaddr = ia->ia_next;
444: else {
445: while (ia->ia_next && (ia->ia_next != oia))
446: ia = ia->ia_next;
447: if (ia->ia_next)
448: ia->ia_next = oia->ia_next;
449: else
450: printf("Didn't unlink inifadr from list\n");
451: }
452: (void) m_free(dtom(oia));
453: break;
454:
455: default:
456: if (ifp == 0 || ifp->if_ioctl == 0)
457: return (EOPNOTSUPP);
458: return ((*ifp->if_ioctl)(ifp, cmd, data));
459: }
460: return (0);
461: }
462:
463: /*
464: * Delete any existing route for an interface.
465: */
466: in_ifscrub(ifp, ia)
467: register struct ifnet *ifp;
468: register struct in_ifaddr *ia;
469: {
470:
471: if ((ia->ia_flags & IFA_ROUTE) == 0)
472: return;
473: if (ifp->if_flags & (IFF_LOOPBACK|IFF_POINTOPOINT))
474: rtinit(&(ia->ia_ifa), (int)RTM_DELETE, RTF_HOST);
475: else
476: rtinit(&(ia->ia_ifa), (int)RTM_DELETE, 0);
477: ia->ia_flags &= ~IFA_ROUTE;
478: }
479:
480: /*
481: * Initialize an interface's internet address
482: * and routing table entry.
483: */
484: in_ifinit(ifp, ia, sin, scrub)
485: register struct ifnet *ifp;
486: register struct in_ifaddr *ia;
487: struct sockaddr_in *sin;
488: {
489: register u_long i = ntohl(sin->sin_addr.s_addr);
490: struct sockaddr_in oldaddr;
491: int s = splimp(), error, flags = RTF_UP;
492:
493: oldaddr = ia->ia_addr;
494: ia->ia_addr = *sin;
495: /*
496: * Give the interface a chance to initialize
497: * if this is its first address,
498: * and to validate the address if necessary.
499: */
500: if (ifp->if_ioctl && (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, ia))) {
501: splx(s);
502: ia->ia_addr = oldaddr;
503: return (error);
504: }
505: splx(s);
506: if (scrub) {
507: ia->ia_ifa.ifa_addr = (struct sockaddr *)&oldaddr;
508: in_ifscrub(ifp, ia);
509: ia->ia_ifa.ifa_addr = (struct sockaddr *)&ia->ia_addr;
510: }
511: if (IN_CLASSA(i))
512: ia->ia_netmask = IN_CLASSA_NET;
513: else if (IN_CLASSB(i))
514: ia->ia_netmask = IN_CLASSB_NET;
515: else
516: ia->ia_netmask = IN_CLASSC_NET;
517: ia->ia_net = i & ia->ia_netmask;
518: /*
519: * The subnet mask includes at least the standard network part,
520: * but may already have been set to a larger value.
521: */
522: ia->ia_subnetmask |= ia->ia_netmask;
523: ia->ia_subnet = i & ia->ia_subnetmask;
524: ia->ia_sockmask.sin_addr.s_addr = htonl(ia->ia_subnetmask);
525: {
526: register char *cp = (char *) (1 + &(ia->ia_sockmask.sin_addr));
527: register char *cpbase = (char *) &(ia->ia_sockmask.sin_addr);
528: while (--cp >= cpbase)
529: if (*cp) {
530: ia->ia_sockmask.sin_len =
531: 1 + cp - (char *) &(ia->ia_sockmask);
532: break;
533: }
534: }
535: /*
536: * Add route for the network.
537: */
538: if (ifp->if_flags & IFF_BROADCAST) {
539: ia->ia_broadaddr.sin_addr =
540: in_makeaddr(ia->ia_subnet, INADDR_BROADCAST);
541: ia->ia_netbroadcast.s_addr =
542: htonl(ia->ia_net | (INADDR_BROADCAST &~ ia->ia_netmask));
543: } else if (ifp->if_flags & IFF_LOOPBACK) {
544: ia->ia_ifa.ifa_dstaddr = ia->ia_ifa.ifa_addr;
545: flags |= RTF_HOST;
546: } else if (ifp->if_flags & IFF_POINTOPOINT) {
547: if (ia->ia_dstaddr.sin_family != AF_INET)
548: return (0);
549: flags |= RTF_HOST;
550: }
551: if ((error = rtinit(&(ia->ia_ifa), (int)RTM_ADD, flags)) == 0)
552: ia->ia_flags |= IFA_ROUTE;
553: return (error);
554: }
555:
556: /*
557: * Return address info for specified internet network.
558: */
559: struct in_ifaddr *
560: in_iaonnetof(net)
561: u_long net;
562: {
563: register struct in_ifaddr *ia;
564:
565: for (ia = in_ifaddr; ia; ia = ia->ia_next)
566: if (ia->ia_subnet == net)
567: return (ia);
568: return ((struct in_ifaddr *)0);
569: }
570:
571: /*
572: * Return 1 if the address might be a local broadcast address.
573: */
574: in_broadcast(in)
575: struct in_addr in;
576: {
577: register struct in_ifaddr *ia;
578: u_long t;
579:
580: /*
581: * Look through the list of addresses for a match
582: * with a broadcast address.
583: */
584: for (ia = in_ifaddr; ia; ia = ia->ia_next)
585: if (ia->ia_ifp->if_flags & IFF_BROADCAST) {
586: if (ia->ia_broadaddr.sin_addr.s_addr == in.s_addr)
587: return (1);
588: /*
589: * Check for old-style (host 0) broadcast.
590: */
591: if ((t = ntohl(in.s_addr)) == ia->ia_subnet || t == ia->ia_net)
592: return (1);
593: }
594: if (in.s_addr == INADDR_BROADCAST || in.s_addr == INADDR_ANY)
595: return (1);
596: return (0);
597: }
598: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.