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