1:
2:
3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30:
31:
32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60:
61:
62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91:
92:
93: #include <sys/cdefs.h>
94: __KERNEL_RCSID(0, "$NetBSD: in.c,v 1.127.4.3 2010/05/20 05:05:58 snj Exp $");
95:
96: #include "opt_inet.h"
97: #include "opt_inet_conf.h"
98: #ifndef T2EX
99: #include "opt_mrouting.h"
100: #include "opt_pfil_hooks.h"
101: #endif
102:
103: #include <sys/param.h>
104: #include <sys/ioctl.h>
105: #include <sys/errno.h>
106: #include <sys/malloc.h>
107: #include <sys/socket.h>
108: #include <sys/socketvar.h>
109: #include <sys/sysctl.h>
110: #include <sys/systm.h>
111: #include <sys/proc.h>
112: #include <sys/syslog.h>
113: #ifndef T2EX
114: #include <sys/kauth.h>
115: #endif
116:
117: #include <net/if.h>
118: #include <net/route.h>
119:
120: #include <net/if_ether.h>
121:
122: #include <netinet/in_systm.h>
123: #include <netinet/in.h>
124: #include <netinet/in_var.h>
125: #include <netinet/ip.h>
126: #include <netinet/ip_var.h>
127: #include <netinet/in_ifattach.h>
128: #include <netinet/in_pcb.h>
129: #include <netinet/if_inarp.h>
130: #include <netinet/ip_mroute.h>
131: #include <netinet/igmp_var.h>
132:
133: #ifdef IPSELSRC
134: #include <netinet/in_selsrc.h>
135: #endif
136:
137: #ifdef PFIL_HOOKS
138: #include <net/pfil.h>
139: #endif
140:
141: static u_int in_mask2len(struct in_addr *);
142: static void in_len2mask(struct in_addr *, u_int);
143: static int in_lifaddr_ioctl(struct socket *, u_long, void *,
144: struct ifnet *, struct lwp *);
145:
146: static int in_ifaddrpref_ioctl(struct socket *, u_long, void *,
147: struct ifnet *);
148: static int in_addprefix(struct in_ifaddr *, int);
149: static int in_scrubprefix(struct in_ifaddr *);
150:
151: #ifndef SUBNETSARELOCAL
152: #define SUBNETSARELOCAL 1
153: #endif
154:
155: #ifndef HOSTZEROBROADCAST
156: #define HOSTZEROBROADCAST 1
157: #endif
158:
159: int subnetsarelocal = SUBNETSARELOCAL;
160: int hostzeroisbroadcast = HOSTZEROBROADCAST;
161:
162: 163: 164: 165: 166:
167: static TAILQ_HEAD(, in_ifaddr) in_mk = TAILQ_HEAD_INITIALIZER(in_mk);
168:
169: 170: 171: 172: 173: 174:
175: int
176: in_localaddr(struct in_addr in)
177: {
178: struct in_ifaddr *ia;
179:
180: if (subnetsarelocal) {
181: TAILQ_FOREACH(ia, &in_ifaddrhead, ia_list)
182: if ((in.s_addr & ia->ia_netmask) == ia->ia_net)
183: return (1);
184: } else {
185: TAILQ_FOREACH(ia, &in_ifaddrhead, ia_list)
186: if ((in.s_addr & ia->ia_subnetmask) == ia->ia_subnet)
187: return (1);
188: }
189: return (0);
190: }
191:
192: 193: 194: 195: 196:
197: int
198: in_canforward(struct in_addr in)
199: {
200: u_int32_t net;
201:
202: if (IN_EXPERIMENTAL(in.s_addr) || IN_MULTICAST(in.s_addr))
203: return (0);
204: if (IN_CLASSA(in.s_addr)) {
205: net = in.s_addr & IN_CLASSA_NET;
206: if (net == 0 || net == htonl(IN_LOOPBACKNET << IN_CLASSA_NSHIFT))
207: return (0);
208: }
209: return (1);
210: }
211:
212: 213: 214:
215: void
216: in_socktrim(struct sockaddr_in *ap)
217: {
218: char *cplim = (char *) &ap->sin_addr;
219: char *cp = (char *) (&ap->sin_addr + 1);
220:
221: ap->sin_len = 0;
222: while (--cp >= cplim)
223: if (*cp) {
224: (ap)->sin_len = cp - (char *) (ap) + 1;
225: break;
226: }
227: }
228:
229: 230: 231: 232:
233: const char *
234: in_fmtaddr(struct in_addr addr)
235: {
236: static char buf[sizeof("123.456.789.123")];
237:
238: addr.s_addr = ntohl(addr.s_addr);
239:
240: snprintf(buf, sizeof(buf), "%d.%d.%d.%d",
241: (addr.s_addr >> 24) & 0xFF,
242: (addr.s_addr >> 16) & 0xFF,
243: (addr.s_addr >> 8) & 0xFF,
244: (addr.s_addr >> 0) & 0xFF);
245: return buf;
246: }
247:
248: 249: 250: 251: 252:
253: unsigned long in_maxmtu;
254:
255: void
256: in_setmaxmtu(void)
257: {
258: struct in_ifaddr *ia;
259: struct ifnet *ifp;
260: unsigned long maxmtu = 0;
261:
262: TAILQ_FOREACH(ia, &in_ifaddrhead, ia_list) {
263: if ((ifp = ia->ia_ifp) == 0)
264: continue;
265: if ((ifp->if_flags & (IFF_UP|IFF_LOOPBACK)) != IFF_UP)
266: continue;
267: if (ifp->if_mtu > maxmtu)
268: maxmtu = ifp->if_mtu;
269: }
270: if (maxmtu)
271: in_maxmtu = maxmtu;
272: }
273:
274: static u_int
275: in_mask2len(struct in_addr *mask)
276: {
277: u_int x, y;
278: u_char *p;
279:
280: p = (u_char *)mask;
281: for (x = 0; x < sizeof(*mask); x++) {
282: if (p[x] != 0xff)
283: break;
284: }
285: y = 0;
286: if (x < sizeof(*mask)) {
287: for (y = 0; y < NBBY; y++) {
288: if ((p[x] & (0x80 >> y)) == 0)
289: break;
290: }
291: }
292: return x * NBBY + y;
293: }
294:
295: static void
296: in_len2mask(struct in_addr *mask, u_int len)
297: {
298: u_int i;
299: u_char *p;
300:
301: p = (u_char *)mask;
302: bzero(mask, sizeof(*mask));
303: for (i = 0; i < len / NBBY; i++)
304: p[i] = 0xff;
305: if (len % NBBY)
306: p[i] = (0xff00 >> (len % NBBY)) & 0xff;
307: }
308:
309: 310: 311: 312:
313:
314: int
315: in_control(struct socket *so, u_long cmd, void *data, struct ifnet *ifp,
316: struct lwp *l)
317: {
318: struct ifreq *ifr = (struct ifreq *)data;
319: struct in_ifaddr *ia = 0;
320: struct in_aliasreq *ifra = (struct in_aliasreq *)data;
321: struct sockaddr_in oldaddr;
322: int error, hostIsNew, maskIsNew;
323: int newifaddr = 0;
324:
325: switch (cmd) {
326: case SIOCALIFADDR:
327: case SIOCDLIFADDR:
328: case SIOCSIFADDRPREF:
329: if (l == NULL)
330: return (EPERM);
331: #ifndef T2EX
332: if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_INTERFACE,
333: KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp, (void *)cmd,
334: NULL) != 0)
335: return (EPERM);
336: #endif
337:
338: case SIOCGIFADDRPREF:
339: case SIOCGLIFADDR:
340: if (ifp == NULL)
341: return EINVAL;
342: if (cmd == SIOCGIFADDRPREF || cmd == SIOCSIFADDRPREF)
343: return in_ifaddrpref_ioctl(so, cmd, data, ifp);
344: else
345: return in_lifaddr_ioctl(so, cmd, data, ifp, l);
346: }
347:
348: 349: 350:
351: if (ifp != NULL)
352: IFP_TO_IA(ifp, ia);
353:
354: switch (cmd) {
355:
356: case SIOCAIFADDR:
357: case SIOCDIFADDR:
358: case SIOCGIFALIAS:
359: if (ifra->ifra_addr.sin_family == AF_INET)
360: LIST_FOREACH(ia,
361: &IN_IFADDR_HASH(ifra->ifra_addr.sin_addr.s_addr),
362: ia_hash) {
363: if (ia->ia_ifp == ifp &&
364: in_hosteq(ia->ia_addr.sin_addr,
365: ifra->ifra_addr.sin_addr))
366: break;
367: }
368: if ((cmd == SIOCDIFADDR || cmd == SIOCGIFALIAS) && ia == NULL)
369: return (EADDRNOTAVAIL);
370:
371: #if 1
372: if (cmd == SIOCDIFADDR &&
373: ifra->ifra_addr.sin_family == AF_UNSPEC) {
374: ifra->ifra_addr.sin_family = AF_INET;
375: }
376: #endif
377:
378: case SIOCSIFADDR:
379: case SIOCSIFDSTADDR:
380: if (ifra->ifra_addr.sin_family != AF_INET)
381: return (EAFNOSUPPORT);
382:
383: case SIOCSIFNETMASK:
384: if (ifp == NULL)
385: panic("in_control");
386:
387: if (cmd == SIOCGIFALIAS)
388: break;
389:
390: if (ia == NULL &&
391: (cmd == SIOCSIFNETMASK || cmd == SIOCSIFDSTADDR))
392: return (EADDRNOTAVAIL);
393:
394: if (l == NULL)
395: return (EPERM);
396: #ifndef T2EX
397: if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_INTERFACE,
398: KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp, (void *)cmd,
399: NULL) != 0)
400: return (EPERM);
401: #endif
402:
403: if (ia == 0) {
404: MALLOC(ia, struct in_ifaddr *, sizeof(*ia),
405: M_IFADDR, M_WAITOK);
406: if (ia == 0)
407: return (ENOBUFS);
408: bzero((void *)ia, sizeof *ia);
409: TAILQ_INSERT_TAIL(&in_ifaddrhead, ia, ia_list);
410: IFAREF(&ia->ia_ifa);
411: ifa_insert(ifp, &ia->ia_ifa);
412: ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);
413: ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr);
414: ia->ia_ifa.ifa_netmask = sintosa(&ia->ia_sockmask);
415: #ifdef IPSELSRC
416: ia->ia_ifa.ifa_getifa = in_getifa;
417: #else
418: ia->ia_ifa.ifa_getifa = NULL;
419: #endif
420: ia->ia_sockmask.sin_len = 8;
421: if (ifp->if_flags & IFF_BROADCAST) {
422: ia->ia_broadaddr.sin_len = sizeof(ia->ia_addr);
423: ia->ia_broadaddr.sin_family = AF_INET;
424: }
425: ia->ia_ifp = ifp;
426: ia->ia_idsalt = arc4random() % 65535;
427: LIST_INIT(&ia->ia_multiaddrs);
428: newifaddr = 1;
429: }
430: break;
431:
432: case SIOCSIFBRDADDR:
433: if (l == NULL)
434: return (EPERM);
435: #ifndef T2EX
436: if (kauth_authorize_network(l->l_cred, KAUTH_NETWORK_INTERFACE,
437: KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp, (void *)cmd,
438: NULL) != 0)
439: return (EPERM);
440: #endif
441:
442:
443: case SIOCGIFADDR:
444: case SIOCGIFNETMASK:
445: case SIOCGIFDSTADDR:
446: case SIOCGIFBRDADDR:
447: if (ia == 0)
448: return (EADDRNOTAVAIL);
449: break;
450: }
451: error = 0;
452: switch (cmd) {
453:
454: case SIOCGIFADDR:
455: ifreq_setaddr(cmd, ifr, sintocsa(&ia->ia_addr));
456: break;
457:
458: case SIOCGIFBRDADDR:
459: if ((ifp->if_flags & IFF_BROADCAST) == 0)
460: return (EINVAL);
461: ifreq_setdstaddr(cmd, ifr, sintocsa(&ia->ia_broadaddr));
462: break;
463:
464: case SIOCGIFDSTADDR:
465: if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
466: return (EINVAL);
467: ifreq_setdstaddr(cmd, ifr, sintocsa(&ia->ia_dstaddr));
468: break;
469:
470: case SIOCGIFNETMASK:
471: ifreq_setaddr(cmd, ifr, sintocsa(&ia->ia_sockmask));
472: break;
473:
474: case SIOCSIFDSTADDR:
475: if ((ifp->if_flags & IFF_POINTOPOINT) == 0)
476: return (EINVAL);
477: oldaddr = ia->ia_dstaddr;
478: ia->ia_dstaddr = *satocsin(ifreq_getdstaddr(cmd, ifr));
479: if (ifp->if_ioctl != NULL &&
480: (error = (*ifp->if_ioctl)(ifp, SIOCSIFDSTADDR,
481: (void *)ia)) != 0) {
482: ia->ia_dstaddr = oldaddr;
483: return error;
484: }
485: if (ia->ia_flags & IFA_ROUTE) {
486: ia->ia_ifa.ifa_dstaddr = sintosa(&oldaddr);
487: rtinit(&ia->ia_ifa, RTM_DELETE, RTF_HOST);
488: ia->ia_ifa.ifa_dstaddr = sintosa(&ia->ia_dstaddr);
489: rtinit(&ia->ia_ifa, RTM_ADD, RTF_HOST|RTF_UP);
490: }
491: break;
492:
493: case SIOCSIFBRDADDR:
494: if ((ifp->if_flags & IFF_BROADCAST) == 0)
495: return EINVAL;
496: ia->ia_broadaddr = *satocsin(ifreq_getbroadaddr(cmd, ifr));
497: break;
498:
499: case SIOCSIFADDR:
500: error = in_ifinit(ifp, ia, satocsin(ifreq_getaddr(cmd, ifr)),
501: 1);
502: #ifdef PFIL_HOOKS
503: if (error == 0)
504: (void)pfil_run_hooks(&if_pfil,
505: (struct mbuf **)SIOCSIFADDR, ifp, PFIL_IFADDR);
506: #endif
507: break;
508:
509: case SIOCSIFNETMASK:
510: in_ifscrub(ifp, ia);
511: ia->ia_sockmask = *satocsin(ifreq_getaddr(cmd, ifr));
512: ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr;
513: error = in_ifinit(ifp, ia, NULL, 0);
514: break;
515:
516: case SIOCAIFADDR:
517: maskIsNew = 0;
518: hostIsNew = 1;
519: if (ia->ia_addr.sin_family != AF_INET)
520: ;
521: else if (ifra->ifra_addr.sin_len == 0) {
522: ifra->ifra_addr = ia->ia_addr;
523: hostIsNew = 0;
524: } else if (in_hosteq(ia->ia_addr.sin_addr,
525: ifra->ifra_addr.sin_addr))
526: hostIsNew = 0;
527: if (ifra->ifra_mask.sin_len) {
528: in_ifscrub(ifp, ia);
529: ia->ia_sockmask = ifra->ifra_mask;
530: ia->ia_subnetmask = ia->ia_sockmask.sin_addr.s_addr;
531: maskIsNew = 1;
532: }
533: if ((ifp->if_flags & IFF_POINTOPOINT) &&
534: (ifra->ifra_dstaddr.sin_family == AF_INET)) {
535: in_ifscrub(ifp, ia);
536: ia->ia_dstaddr = ifra->ifra_dstaddr;
537: maskIsNew = 1;
538: }
539: if (ifra->ifra_addr.sin_family == AF_INET &&
540: (hostIsNew || maskIsNew)) {
541: error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
542: }
543: if ((ifp->if_flags & IFF_BROADCAST) &&
544: (ifra->ifra_broadaddr.sin_family == AF_INET))
545: ia->ia_broadaddr = ifra->ifra_broadaddr;
546: #ifdef PFIL_HOOKS
547: if (error == 0)
548: (void)pfil_run_hooks(&if_pfil,
549: (struct mbuf **)SIOCAIFADDR, ifp, PFIL_IFADDR);
550: #endif
551: break;
552:
553: case SIOCGIFALIAS:
554: ifra->ifra_mask = ia->ia_sockmask;
555: if ((ifp->if_flags & IFF_POINTOPOINT) &&
556: (ia->ia_dstaddr.sin_family == AF_INET))
557: ifra->ifra_dstaddr = ia->ia_dstaddr;
558: else if ((ifp->if_flags & IFF_BROADCAST) &&
559: (ia->ia_broadaddr.sin_family == AF_INET))
560: ifra->ifra_broadaddr = ia->ia_broadaddr;
561: else
562: memset(&ifra->ifra_broadaddr, 0,
563: sizeof(ifra->ifra_broadaddr));
564: break;
565:
566: case SIOCDIFADDR:
567: in_purgeaddr(&ia->ia_ifa);
568: #ifdef PFIL_HOOKS
569: (void)pfil_run_hooks(&if_pfil, (struct mbuf **)SIOCDIFADDR,
570: ifp, PFIL_IFADDR);
571: #endif
572: break;
573:
574: #ifdef MROUTING
575: case SIOCGETVIFCNT:
576: case SIOCGETSGCNT:
577: error = mrt_ioctl(so, cmd, data);
578: break;
579: #endif
580:
581: default:
582: if (ifp == NULL || ifp->if_ioctl == NULL)
583: return EOPNOTSUPP;
584: error = (*ifp->if_ioctl)(ifp, cmd, data);
585: in_setmaxmtu();
586: break;
587: }
588:
589: if (error != 0 && newifaddr) {
590: KASSERT(ia != NULL);
591: in_purgeaddr(&ia->ia_ifa);
592: }
593:
594: return error;
595: }
596:
597: void
598: in_purgeaddr(struct ifaddr *ifa)
599: {
600: struct ifnet *ifp = ifa->ifa_ifp;
601: struct in_ifaddr *ia = (void *) ifa;
602:
603: in_ifscrub(ifp, ia);
604: LIST_REMOVE(ia, ia_hash);
605: ifa_remove(ifp, &ia->ia_ifa);
606: TAILQ_REMOVE(&in_ifaddrhead, ia, ia_list);
607: if (ia->ia_allhosts != NULL)
608: in_delmulti(ia->ia_allhosts);
609: IFAFREE(&ia->ia_ifa);
610: in_setmaxmtu();
611: }
612:
613: void
614: in_purgeif(struct ifnet *ifp)
615: {
616: if_purgeaddrs(ifp, AF_INET, in_purgeaddr);
617: igmp_purgeif(ifp);
618: #ifdef MROUTING
619: ip_mrouter_detach(ifp);
620: #endif
621: }
622:
623: 624: 625: 626: 627: 628: 629: 630: 631: 632: 633: 634: 635: 636: 637: 638:
639: static int
640: in_lifaddr_ioctl(struct socket *so, u_long cmd, void *data,
641: struct ifnet *ifp, struct lwp *l)
642: {
643: struct if_laddrreq *iflr = (struct if_laddrreq *)data;
644: struct ifaddr *ifa;
645: struct sockaddr *sa;
646:
647:
648: if (data == NULL || ifp == NULL) {
649: panic("invalid argument to in_lifaddr_ioctl");
650:
651: }
652:
653: switch (cmd) {
654: case SIOCGLIFADDR:
655:
656: if ((iflr->flags & IFLR_PREFIX) == 0)
657: break;
658:
659: case SIOCALIFADDR:
660: case SIOCDLIFADDR:
661:
662: sa = (struct sockaddr *)&iflr->addr;
663: if (sa->sa_family != AF_INET)
664: return EINVAL;
665: if (sa->sa_len != sizeof(struct sockaddr_in))
666: return EINVAL;
667:
668: sa = (struct sockaddr *)&iflr->dstaddr;
669: if (sa->sa_family != AF_UNSPEC && sa->sa_family != AF_INET)
670: return EINVAL;
671: if (sa->sa_len != 0 && sa->sa_len != sizeof(struct sockaddr_in))
672: return EINVAL;
673: break;
674: default:
675: #if 0
676: panic("invalid cmd to in_lifaddr_ioctl");
677:
678: #else
679: return EOPNOTSUPP;
680: #endif
681: }
682: if (sizeof(struct in_addr) * NBBY < iflr->prefixlen)
683: return EINVAL;
684:
685: switch (cmd) {
686: case SIOCALIFADDR:
687: {
688: struct in_aliasreq ifra;
689:
690: if (iflr->flags & IFLR_PREFIX)
691: return EINVAL;
692:
693:
694: bzero(&ifra, sizeof(ifra));
695: bcopy(iflr->iflr_name, ifra.ifra_name,
696: sizeof(ifra.ifra_name));
697:
698: bcopy(&iflr->addr, &ifra.ifra_addr,
699: ((struct sockaddr *)&iflr->addr)->sa_len);
700:
701: if (((struct sockaddr *)&iflr->dstaddr)->sa_family) {
702: bcopy(&iflr->dstaddr, &ifra.ifra_dstaddr,
703: ((struct sockaddr *)&iflr->dstaddr)->sa_len);
704: }
705:
706: ifra.ifra_mask.sin_family = AF_INET;
707: ifra.ifra_mask.sin_len = sizeof(struct sockaddr_in);
708: in_len2mask(&ifra.ifra_mask.sin_addr, iflr->prefixlen);
709:
710: return in_control(so, SIOCAIFADDR, (void *)&ifra, ifp, l);
711: }
712: case SIOCGLIFADDR:
713: case SIOCDLIFADDR:
714: {
715: struct in_ifaddr *ia;
716: struct in_addr mask, candidate, match;
717: struct sockaddr_in *sin;
718: int cmp;
719:
720: bzero(&mask, sizeof(mask));
721: bzero(&match, sizeof(match));
722: if (iflr->flags & IFLR_PREFIX) {
723:
724: in_len2mask(&mask, iflr->prefixlen);
725:
726: sin = (struct sockaddr_in *)&iflr->addr;
727: match.s_addr = sin->sin_addr.s_addr;
728: match.s_addr &= mask.s_addr;
729:
730:
731: if (match.s_addr != sin->sin_addr.s_addr)
732: return EINVAL;
733:
734: cmp = 1;
735: } else {
736: if (cmd == SIOCGLIFADDR) {
737:
738: cmp = 0;
739: } else {
740:
741: in_len2mask(&mask, 32);
742: sin = (struct sockaddr_in *)&iflr->addr;
743: match.s_addr = sin->sin_addr.s_addr;
744:
745: cmp = 1;
746: }
747: }
748:
749: IFADDR_FOREACH(ifa, ifp) {
750: if (ifa->ifa_addr->sa_family != AF_INET)
751: continue;
752: if (cmp == 0)
753: break;
754: candidate.s_addr = ((struct sockaddr_in *)&ifa->ifa_addr)->sin_addr.s_addr;
755: candidate.s_addr &= mask.s_addr;
756: if (candidate.s_addr == match.s_addr)
757: break;
758: }
759: if (ifa == NULL)
760: return EADDRNOTAVAIL;
761: ia = (struct in_ifaddr *)ifa;
762:
763: if (cmd == SIOCGLIFADDR) {
764:
765: bcopy(&ia->ia_addr, &iflr->addr, ia->ia_addr.sin_len);
766:
767: if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
768: bcopy(&ia->ia_dstaddr, &iflr->dstaddr,
769: ia->ia_dstaddr.sin_len);
770: } else
771: bzero(&iflr->dstaddr, sizeof(iflr->dstaddr));
772:
773: iflr->prefixlen =
774: in_mask2len(&ia->ia_sockmask.sin_addr);
775:
776: iflr->flags = 0;
777:
778: return 0;
779: } else {
780: struct in_aliasreq ifra;
781:
782:
783: bzero(&ifra, sizeof(ifra));
784: bcopy(iflr->iflr_name, ifra.ifra_name,
785: sizeof(ifra.ifra_name));
786:
787: bcopy(&ia->ia_addr, &ifra.ifra_addr,
788: ia->ia_addr.sin_len);
789: if ((ifp->if_flags & IFF_POINTOPOINT) != 0) {
790: bcopy(&ia->ia_dstaddr, &ifra.ifra_dstaddr,
791: ia->ia_dstaddr.sin_len);
792: }
793: bcopy(&ia->ia_sockmask, &ifra.ifra_dstaddr,
794: ia->ia_sockmask.sin_len);
795:
796: return in_control(so, SIOCDIFADDR, (void *)&ifra,
797: ifp, l);
798: }
799: }
800: }
801:
802: return EOPNOTSUPP;
803: }
804:
805: static int
806: in_ifaddrpref_ioctl(struct socket *so, u_long cmd, void *data,
807: struct ifnet *ifp)
808: {
809: struct if_addrprefreq *ifap = (struct if_addrprefreq *)data;
810: struct ifaddr *ifa;
811: struct sockaddr *sa;
812: struct in_ifaddr *ia = NULL;
813: struct in_addr match;
814: struct sockaddr_in *sin;
815:
816:
817: if (data == NULL || ifp == NULL) {
818: panic("invalid argument to %s", __func__);
819:
820: }
821:
822:
823: sa = (struct sockaddr *)&ifap->ifap_addr;
824: if (sa->sa_family != AF_INET)
825: return EINVAL;
826: if (sa->sa_len != sizeof(struct sockaddr_in))
827: return EINVAL;
828:
829: switch (cmd) {
830: case SIOCSIFADDRPREF:
831: case SIOCGIFADDRPREF:
832: break;
833: default:
834: return EOPNOTSUPP;
835: }
836:
837: sin = (struct sockaddr_in *)&ifap->ifap_addr;
838: match.s_addr = sin->sin_addr.s_addr;
839:
840: IFADDR_FOREACH(ifa, ifp) {
841: ia = (struct in_ifaddr *)ifa;
842: if (ia->ia_addr.sin_family != AF_INET)
843: continue;
844: if (ia->ia_addr.sin_addr.s_addr == match.s_addr)
845: break;
846: }
847: if (ifa == NULL)
848: return EADDRNOTAVAIL;
849:
850: switch (cmd) {
851: case SIOCSIFADDRPREF:
852: ifa->ifa_preference = ifap->ifap_preference;
853: return 0;
854: case SIOCGIFADDRPREF:
855:
856: (void)memcpy(&ifap->ifap_addr, &ia->ia_addr,
857: ia->ia_addr.sin_len);
858: ifap->ifap_preference = ifa->ifa_preference;
859: return 0;
860: default:
861: return EOPNOTSUPP;
862: }
863: }
864:
865: 866: 867:
868: void
869: in_ifscrub(struct ifnet *ifp, struct in_ifaddr *ia)
870: {
871:
872: in_scrubprefix(ia);
873: }
874:
875: 876: 877: 878:
879: int
880: in_ifinit(struct ifnet *ifp, struct in_ifaddr *ia,
881: const struct sockaddr_in *sin, int scrub)
882: {
883: u_int32_t i;
884: struct sockaddr_in oldaddr;
885: int s = splnet(), flags = RTF_UP, error;
886:
887: if (sin == NULL)
888: sin = &ia->ia_addr;
889:
890: 891: 892:
893: oldaddr = ia->ia_addr;
894: if (ia->ia_addr.sin_family == AF_INET)
895: LIST_REMOVE(ia, ia_hash);
896: ia->ia_addr = *sin;
897: LIST_INSERT_HEAD(&IN_IFADDR_HASH(ia->ia_addr.sin_addr.s_addr), ia, ia_hash);
898:
899: 900: 901: 902: 903:
904: if (ifp->if_ioctl &&
905: (error = (*ifp->if_ioctl)(ifp, SIOCSIFADDR, (void *)ia)))
906: goto bad;
907: splx(s);
908: if (scrub) {
909: ia->ia_ifa.ifa_addr = sintosa(&oldaddr);
910: in_ifscrub(ifp, ia);
911: ia->ia_ifa.ifa_addr = sintosa(&ia->ia_addr);
912: }
913:
914: i = ia->ia_addr.sin_addr.s_addr;
915: if (IN_CLASSA(i))
916: ia->ia_netmask = IN_CLASSA_NET;
917: else if (IN_CLASSB(i))
918: ia->ia_netmask = IN_CLASSB_NET;
919: else
920: ia->ia_netmask = IN_CLASSC_NET;
921: 922: 923: 924: 925:
926: if (ia->ia_subnetmask == 0) {
927: ia->ia_subnetmask = ia->ia_netmask;
928: ia->ia_sockmask.sin_addr.s_addr = ia->ia_subnetmask;
929: } else
930: ia->ia_netmask &= ia->ia_subnetmask;
931:
932: ia->ia_net = i & ia->ia_netmask;
933: ia->ia_subnet = i & ia->ia_subnetmask;
934: in_socktrim(&ia->ia_sockmask);
935:
936: in_setmaxmtu();
937: 938: 939:
940: ia->ia_ifa.ifa_metric = ifp->if_metric;
941: if (ifp->if_flags & IFF_BROADCAST) {
942: ia->ia_broadaddr.sin_addr.s_addr =
943: ia->ia_subnet | ~ia->ia_subnetmask;
944: ia->ia_netbroadcast.s_addr =
945: ia->ia_net | ~ia->ia_netmask;
946: } else if (ifp->if_flags & IFF_LOOPBACK) {
947: ia->ia_dstaddr = ia->ia_addr;
948: flags |= RTF_HOST;
949: } else if (ifp->if_flags & IFF_POINTOPOINT) {
950: if (ia->ia_dstaddr.sin_family != AF_INET)
951: return (0);
952: flags |= RTF_HOST;
953: }
954: error = in_addprefix(ia, flags);
955: 956: 957: 958:
959: if ((ifp->if_flags & IFF_MULTICAST) != 0 && ia->ia_allhosts == NULL) {
960: struct in_addr addr;
961:
962: addr.s_addr = INADDR_ALLHOSTS_GROUP;
963: ia->ia_allhosts = in_addmulti(&addr, ifp);
964: }
965: return (error);
966: bad:
967: splx(s);
968: LIST_REMOVE(ia, ia_hash);
969: ia->ia_addr = oldaddr;
970: if (ia->ia_addr.sin_family == AF_INET)
971: LIST_INSERT_HEAD(&IN_IFADDR_HASH(ia->ia_addr.sin_addr.s_addr),
972: ia, ia_hash);
973: return (error);
974: }
975:
976: #define rtinitflags(x) \
977: ((((x)->ia_ifp->if_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) != 0) \
978: ? RTF_HOST : 0)
979:
980: 981: 982: 983:
984: static int
985: in_addprefix(struct in_ifaddr *target, int flags)
986: {
987: struct in_ifaddr *ia;
988: struct in_addr prefix, mask, p;
989: int error;
990:
991: if ((flags & RTF_HOST) != 0)
992: prefix = target->ia_dstaddr.sin_addr;
993: else {
994: prefix = target->ia_addr.sin_addr;
995: mask = target->ia_sockmask.sin_addr;
996: prefix.s_addr &= mask.s_addr;
997: }
998:
999: TAILQ_FOREACH(ia, &in_ifaddrhead, ia_list) {
1000: if (rtinitflags(ia))
1001: p = ia->ia_dstaddr.sin_addr;
1002: else {
1003: p = ia->ia_addr.sin_addr;
1004: p.s_addr &= ia->ia_sockmask.sin_addr.s_addr;
1005: }
1006:
1007: if (prefix.s_addr != p.s_addr)
1008: continue;
1009:
1010: 1011: 1012: 1013: 1014: 1015:
1016: if (ia->ia_flags & IFA_ROUTE)
1017: return 0;
1018: }
1019:
1020: 1021: 1022:
1023: error = rtinit(&target->ia_ifa, RTM_ADD, flags);
1024: if (error == 0)
1025: target->ia_flags |= IFA_ROUTE;
1026: else if (error == EEXIST) {
1027: 1028: 1029:
1030: error = 0;
1031: }
1032: return error;
1033: }
1034:
1035: 1036: 1037: 1038: 1039:
1040: static int
1041: in_scrubprefix(struct in_ifaddr *target)
1042: {
1043: struct in_ifaddr *ia;
1044: struct in_addr prefix, mask, p;
1045: int error;
1046:
1047: if ((target->ia_flags & IFA_ROUTE) == 0)
1048: return 0;
1049:
1050: if (rtinitflags(target))
1051: prefix = target->ia_dstaddr.sin_addr;
1052: else {
1053: prefix = target->ia_addr.sin_addr;
1054: mask = target->ia_sockmask.sin_addr;
1055: prefix.s_addr &= mask.s_addr;
1056: }
1057:
1058: TAILQ_FOREACH(ia, &in_ifaddrhead, ia_list) {
1059: if (rtinitflags(ia))
1060: p = ia->ia_dstaddr.sin_addr;
1061: else {
1062: p = ia->ia_addr.sin_addr;
1063: p.s_addr &= ia->ia_sockmask.sin_addr.s_addr;
1064: }
1065:
1066: if (prefix.s_addr != p.s_addr)
1067: continue;
1068:
1069: 1070: 1071:
1072: if ((ia->ia_flags & IFA_ROUTE) == 0) {
1073: rtinit(&target->ia_ifa, RTM_DELETE,
1074: rtinitflags(target));
1075: target->ia_flags &= ~IFA_ROUTE;
1076:
1077: error = rtinit(&ia->ia_ifa, RTM_ADD,
1078: rtinitflags(ia) | RTF_UP);
1079: if (error == 0)
1080: ia->ia_flags |= IFA_ROUTE;
1081: return error;
1082: }
1083: }
1084:
1085: 1086: 1087:
1088: rtinit(&target->ia_ifa, RTM_DELETE, rtinitflags(target));
1089: target->ia_flags &= ~IFA_ROUTE;
1090: return 0;
1091: }
1092:
1093: #undef rtinitflags
1094:
1095: 1096: 1097:
1098: int
1099: in_broadcast(struct in_addr in, struct ifnet *ifp)
1100: {
1101: struct ifaddr *ifa;
1102:
1103: if (in.s_addr == INADDR_BROADCAST ||
1104: in_nullhost(in))
1105: return 1;
1106: if ((ifp->if_flags & IFF_BROADCAST) == 0)
1107: return 0;
1108: 1109: 1110: 1111:
1112: #define ia (ifatoia(ifa))
1113: IFADDR_FOREACH(ifa, ifp)
1114: if (ifa->ifa_addr->sa_family == AF_INET &&
1115: !in_hosteq(in, ia->ia_addr.sin_addr) &&
1116: (in_hosteq(in, ia->ia_broadaddr.sin_addr) ||
1117: in_hosteq(in, ia->ia_netbroadcast) ||
1118: (hostzeroisbroadcast &&
1119: 1120: 1121:
1122: (in.s_addr == ia->ia_subnet ||
1123: in.s_addr == ia->ia_net))))
1124: return 1;
1125: return (0);
1126: #undef ia
1127: }
1128:
1129: 1130: 1131:
1132: struct in_multi *
1133: in_addmulti(struct in_addr *ap, struct ifnet *ifp)
1134: {
1135: struct sockaddr_in sin;
1136: struct in_multi *inm;
1137: struct ifreq ifr;
1138: int s = splsoftnet();
1139:
1140: 1141: 1142:
1143: IN_LOOKUP_MULTI(*ap, ifp, inm);
1144: if (inm != NULL) {
1145: 1146: 1147:
1148: ++inm->inm_refcount;
1149: } else {
1150: 1151: 1152: 1153:
1154: inm = pool_get(&inmulti_pool, PR_NOWAIT);
1155: if (inm == NULL) {
1156: splx(s);
1157: return (NULL);
1158: }
1159: inm->inm_addr = *ap;
1160: inm->inm_ifp = ifp;
1161: inm->inm_refcount = 1;
1162: LIST_INSERT_HEAD(
1163: &IN_MULTI_HASH(inm->inm_addr.s_addr, ifp),
1164: inm, inm_list);
1165: 1166: 1167: 1168:
1169: sockaddr_in_init(&sin, ap, 0);
1170: ifreq_setaddr(SIOCADDMULTI, &ifr, sintosa(&sin));
1171: if ((ifp->if_ioctl == NULL) ||
1172: (*ifp->if_ioctl)(ifp, SIOCADDMULTI,(void *)&ifr) != 0) {
1173: LIST_REMOVE(inm, inm_list);
1174: pool_put(&inmulti_pool, inm);
1175: splx(s);
1176: return (NULL);
1177: }
1178: 1179: 1180:
1181: if (igmp_joingroup(inm) != 0) {
1182: LIST_REMOVE(inm, inm_list);
1183: pool_put(&inmulti_pool, inm);
1184: splx(s);
1185: return (NULL);
1186: }
1187: in_multientries++;
1188: }
1189: splx(s);
1190: return (inm);
1191: }
1192:
1193: 1194: 1195:
1196: void
1197: in_delmulti(struct in_multi *inm)
1198: {
1199: struct sockaddr_in sin;
1200: struct ifreq ifr;
1201: int s = splsoftnet();
1202:
1203: if (--inm->inm_refcount == 0) {
1204: 1205: 1206: 1207:
1208: igmp_leavegroup(inm);
1209: 1210: 1211:
1212: LIST_REMOVE(inm, inm_list);
1213: in_multientries--;
1214: 1215: 1216: 1217:
1218: sockaddr_in_init(&sin, &inm->inm_addr, 0);
1219: ifreq_setaddr(SIOCDELMULTI, &ifr, sintosa(&sin));
1220: (*inm->inm_ifp->if_ioctl)(inm->inm_ifp, SIOCDELMULTI,
1221: (void *)&ifr);
1222: pool_put(&inmulti_pool, inm);
1223: }
1224: splx(s);
1225: }