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