in.c (b89e82dd87dec9034c8b7f1a01524dceea11ff49) in.c (d10910e6cee0dca8be3d5a7fdbe404a15d9e7b52)
1/*-
2 * Copyright (c) 1982, 1986, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (C) 2001 WIDE Project. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 43 unchanged lines hidden (view full) ---

52#include <net/if_types.h>
53#include <net/route.h>
54
55#include <netinet/in.h>
56#include <netinet/in_var.h>
57#include <netinet/in_pcb.h>
58#include <netinet/ip_var.h>
59#include <netinet/vinet.h>
1/*-
2 * Copyright (c) 1982, 1986, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 * Copyright (C) 2001 WIDE Project. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 43 unchanged lines hidden (view full) ---

52#include <net/if_types.h>
53#include <net/route.h>
54
55#include <netinet/in.h>
56#include <netinet/in_var.h>
57#include <netinet/in_pcb.h>
58#include <netinet/ip_var.h>
59#include <netinet/vinet.h>
60#include <netinet/igmp_var.h>
60
61static int in_mask2len(struct in_addr *);
62static void in_len2mask(struct in_addr *, int);
63static int in_lifaddr_ioctl(struct socket *, u_long, caddr_t,
64 struct ifnet *, struct thread *);
65
66static int in_addprefix(struct in_ifaddr *, int);
67static int in_scrubprefix(struct in_ifaddr *);

--- 142 unchanged lines hidden (view full) ---

210{
211 INIT_VNET_INET(curvnet); /* both so and ifp can be NULL here! */
212 register struct ifreq *ifr = (struct ifreq *)data;
213 register struct in_ifaddr *ia, *iap;
214 register struct ifaddr *ifa;
215 struct in_addr allhosts_addr;
216 struct in_addr dst;
217 struct in_ifaddr *oia;
61
62static int in_mask2len(struct in_addr *);
63static void in_len2mask(struct in_addr *, int);
64static int in_lifaddr_ioctl(struct socket *, u_long, caddr_t,
65 struct ifnet *, struct thread *);
66
67static int in_addprefix(struct in_ifaddr *, int);
68static int in_scrubprefix(struct in_ifaddr *);

--- 142 unchanged lines hidden (view full) ---

211{
212 INIT_VNET_INET(curvnet); /* both so and ifp can be NULL here! */
213 register struct ifreq *ifr = (struct ifreq *)data;
214 register struct in_ifaddr *ia, *iap;
215 register struct ifaddr *ifa;
216 struct in_addr allhosts_addr;
217 struct in_addr dst;
218 struct in_ifaddr *oia;
219 struct in_ifinfo *ii;
218 struct in_aliasreq *ifra = (struct in_aliasreq *)data;
219 struct sockaddr_in oldaddr;
220 int error, hostIsNew, iaIsNew, maskIsNew, s;
221 int iaIsFirst;
222
223 ia = NULL;
220 struct in_aliasreq *ifra = (struct in_aliasreq *)data;
221 struct sockaddr_in oldaddr;
222 int error, hostIsNew, iaIsNew, maskIsNew, s;
223 int iaIsFirst;
224
225 ia = NULL;
226 ii = ((struct in_ifinfo *)ifp->if_afdata[AF_INET]);
224 iaIsFirst = 0;
225 iaIsNew = 0;
226 allhosts_addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
227
228 switch (cmd) {
229 case SIOCALIFADDR:
230 if (td != NULL) {
231 error = priv_check(td, PRIV_NET_ADDIFADDR);

--- 188 unchanged lines hidden (view full) ---

420 return (0);
421
422 case SIOCSIFADDR:
423 error = in_ifinit(ifp, ia,
424 (struct sockaddr_in *) &ifr->ifr_addr, 1);
425 if (error != 0 && iaIsNew)
426 break;
427 if (error == 0) {
227 iaIsFirst = 0;
228 iaIsNew = 0;
229 allhosts_addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
230
231 switch (cmd) {
232 case SIOCALIFADDR:
233 if (td != NULL) {
234 error = priv_check(td, PRIV_NET_ADDIFADDR);

--- 188 unchanged lines hidden (view full) ---

423 return (0);
424
425 case SIOCSIFADDR:
426 error = in_ifinit(ifp, ia,
427 (struct sockaddr_in *) &ifr->ifr_addr, 1);
428 if (error != 0 && iaIsNew)
429 break;
430 if (error == 0) {
428 if (iaIsFirst && (ifp->if_flags & IFF_MULTICAST) != 0)
429 in_addmulti(&allhosts_addr, ifp);
431 if (iaIsFirst &&
432 (ifp->if_flags & IFF_MULTICAST) != 0) {
433 error = in_joingroup(ifp, &allhosts_addr,
434 NULL, &ii->ii_allhosts);
435 }
430 EVENTHANDLER_INVOKE(ifaddr_event, ifp);
431 }
432 return (0);
433
434 case SIOCSIFNETMASK:
435 ia->ia_sockmask.sin_addr = ifra->ifra_addr.sin_addr;
436 ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr);
437 return (0);

--- 29 unchanged lines hidden (view full) ---

467 error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
468 if (error != 0 && iaIsNew)
469 break;
470
471 if ((ifp->if_flags & IFF_BROADCAST) &&
472 (ifra->ifra_broadaddr.sin_family == AF_INET))
473 ia->ia_broadaddr = ifra->ifra_broadaddr;
474 if (error == 0) {
436 EVENTHANDLER_INVOKE(ifaddr_event, ifp);
437 }
438 return (0);
439
440 case SIOCSIFNETMASK:
441 ia->ia_sockmask.sin_addr = ifra->ifra_addr.sin_addr;
442 ia->ia_subnetmask = ntohl(ia->ia_sockmask.sin_addr.s_addr);
443 return (0);

--- 29 unchanged lines hidden (view full) ---

473 error = in_ifinit(ifp, ia, &ifra->ifra_addr, 0);
474 if (error != 0 && iaIsNew)
475 break;
476
477 if ((ifp->if_flags & IFF_BROADCAST) &&
478 (ifra->ifra_broadaddr.sin_family == AF_INET))
479 ia->ia_broadaddr = ifra->ifra_broadaddr;
480 if (error == 0) {
475 if (iaIsFirst && (ifp->if_flags & IFF_MULTICAST) != 0)
476 in_addmulti(&allhosts_addr, ifp);
481 if (iaIsFirst &&
482 (ifp->if_flags & IFF_MULTICAST) != 0) {
483 error = in_joingroup(ifp, &allhosts_addr,
484 NULL, &ii->ii_allhosts);
485 }
477 EVENTHANDLER_INVOKE(ifaddr_event, ifp);
478 }
479 return (error);
480
481 case SIOCDIFADDR:
482 /*
483 * in_ifscrub kills the interface route.
484 */

--- 25 unchanged lines hidden (view full) ---

510 s = splnet();
511 TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
512 TAILQ_REMOVE(&V_in_ifaddrhead, ia, ia_link);
513 if (ia->ia_addr.sin_family == AF_INET) {
514 LIST_REMOVE(ia, ia_hash);
515 /*
516 * If this is the last IPv4 address configured on this
517 * interface, leave the all-hosts group.
486 EVENTHANDLER_INVOKE(ifaddr_event, ifp);
487 }
488 return (error);
489
490 case SIOCDIFADDR:
491 /*
492 * in_ifscrub kills the interface route.
493 */

--- 25 unchanged lines hidden (view full) ---

519 s = splnet();
520 TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link);
521 TAILQ_REMOVE(&V_in_ifaddrhead, ia, ia_link);
522 if (ia->ia_addr.sin_family == AF_INET) {
523 LIST_REMOVE(ia, ia_hash);
524 /*
525 * If this is the last IPv4 address configured on this
526 * interface, leave the all-hosts group.
518 * XXX: This is quite ugly because of locking and structure.
527 * No state-change report need be transmitted.
519 */
520 oia = NULL;
521 IFP_TO_IA(ifp, oia);
522 if (oia == NULL) {
528 */
529 oia = NULL;
530 IFP_TO_IA(ifp, oia);
531 if (oia == NULL) {
523 struct in_multi *inm;
524
525 IFF_LOCKGIANT(ifp);
526 IN_MULTI_LOCK();
532 IFF_LOCKGIANT(ifp);
533 IN_MULTI_LOCK();
527 IN_LOOKUP_MULTI(allhosts_addr, ifp, inm);
528 if (inm != NULL)
529 in_delmulti_locked(inm);
534 if (ii->ii_allhosts) {
535 (void)in_leavegroup_locked(ii->ii_allhosts,
536 NULL);
537 ii->ii_allhosts = NULL;
538 }
530 IN_MULTI_UNLOCK();
531 IFF_UNLOCKGIANT(ifp);
532 }
533 }
534 IFAFREE(&ia->ia_ifa);
535 splx(s);
536
537 return (error);

--- 450 unchanged lines hidden (view full) ---

988 */
989 ia->ia_subnetmask != (u_long)0xffffffff)
990 return (1);
991 return (0);
992#undef ia
993}
994
995/*
539 IN_MULTI_UNLOCK();
540 IFF_UNLOCKGIANT(ifp);
541 }
542 }
543 IFAFREE(&ia->ia_ifa);
544 splx(s);
545
546 return (error);

--- 450 unchanged lines hidden (view full) ---

997 */
998 ia->ia_subnetmask != (u_long)0xffffffff)
999 return (1);
1000 return (0);
1001#undef ia
1002}
1003
1004/*
1005 * On interface removal, clean up IPv4 data structures hung off of the ifnet.
1006 */
1007void
1008in_ifdetach(struct ifnet *ifp)
1009{
1010 INIT_VNET_INET(ifp->if_vnet);
1011
1012 in_pcbpurgeif0(&V_ripcbinfo, ifp);
1013 in_pcbpurgeif0(&V_udbinfo, ifp);
1014 in_purgemaddrs(ifp);
1015}
1016
1017/*
996 * Delete all IPv4 multicast address records, and associated link-layer
997 * multicast address records, associated with ifp.
1018 * Delete all IPv4 multicast address records, and associated link-layer
1019 * multicast address records, associated with ifp.
1020 * XXX It looks like domifdetach runs AFTER the link layer cleanup.
998 */
999static void
1000in_purgemaddrs(struct ifnet *ifp)
1001{
1002 INIT_VNET_INET(ifp->if_vnet);
1021 */
1022static void
1023in_purgemaddrs(struct ifnet *ifp)
1024{
1025 INIT_VNET_INET(ifp->if_vnet);
1003 struct in_multi *inm;
1004 struct in_multi *oinm;
1026 LIST_HEAD(,in_multi) purgeinms;
1027 struct in_multi *inm, *tinm;
1028 struct ifmultiaddr *ifma;
1005
1029
1006 IFF_LOCKGIANT(ifp);
1030 LIST_INIT(&purgeinms);
1007 IN_MULTI_LOCK();
1031 IN_MULTI_LOCK();
1008 LIST_FOREACH_SAFE(inm, &V_in_multihead, inm_link, oinm) {
1009 if (inm->inm_ifp == ifp)
1010 in_delmulti_locked(inm);
1032
1033 /*
1034 * Extract list of in_multi associated with the detaching ifp
1035 * which the PF_INET layer is about to release.
1036 * We need to do this as IF_ADDR_LOCK() may be re-acquired
1037 * by code further down.
1038 */
1039 IF_ADDR_LOCK(ifp);
1040 TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
1041 if (ifma->ifma_addr->sa_family != AF_INET)
1042 continue;
1043 inm = (struct in_multi *)ifma->ifma_protospec;
1044 LIST_INSERT_HEAD(&purgeinms, inm, inm_link);
1011 }
1045 }
1012 IN_MULTI_UNLOCK();
1013 IFF_UNLOCKGIANT(ifp);
1014}
1046 IF_ADDR_UNLOCK(ifp);
1015
1047
1016/*
1017 * On interface removal, clean up IPv4 data structures hung off of the ifnet.
1018 */
1019void
1020in_ifdetach(struct ifnet *ifp)
1021{
1022 INIT_VNET_INET(ifp->if_vnet);
1048 LIST_FOREACH_SAFE(inm, &purgeinms, inm_link, tinm) {
1049 inm_release_locked(inm);
1050 LIST_REMOVE(inm, inm_link);
1051 }
1052 igmp_ifdetach(ifp);
1023
1053
1024 in_pcbpurgeif0(&V_ripcbinfo, ifp);
1025 in_pcbpurgeif0(&V_udbinfo, ifp);
1026 in_purgemaddrs(ifp);
1054 IN_MULTI_UNLOCK();
1027}
1028
1029#include <sys/syslog.h>
1030#include <net/if_dl.h>
1031#include <netinet/if_ether.h>
1032
1033struct in_llentry {
1034 struct llentry base;

--- 210 unchanged lines hidden (view full) ---

1245 }
1246 }
1247 return error;
1248#undef SIN
1249}
1250
1251void *
1252in_domifattach(struct ifnet *ifp)
1055}
1056
1057#include <sys/syslog.h>
1058#include <net/if_dl.h>
1059#include <netinet/if_ether.h>
1060
1061struct in_llentry {
1062 struct llentry base;

--- 210 unchanged lines hidden (view full) ---

1273 }
1274 }
1275 return error;
1276#undef SIN
1277}
1278
1279void *
1280in_domifattach(struct ifnet *ifp)
1253{
1254 struct lltable *llt = lltable_init(ifp, AF_INET);
1255
1281{
1282 struct in_ifinfo *ii;
1283 struct lltable *llt;
1284
1285 ii = malloc(sizeof(struct in_ifinfo), M_IFADDR, M_WAITOK|M_ZERO);
1286
1287 llt = lltable_init(ifp, AF_INET);
1256 if (llt != NULL) {
1257 llt->llt_new = in_lltable_new;
1258 llt->llt_free = in_lltable_free;
1259 llt->llt_rtcheck = in_lltable_rtcheck;
1260 llt->llt_lookup = in_lltable_lookup;
1261 llt->llt_dump = in_lltable_dump;
1262 }
1288 if (llt != NULL) {
1289 llt->llt_new = in_lltable_new;
1290 llt->llt_free = in_lltable_free;
1291 llt->llt_rtcheck = in_lltable_rtcheck;
1292 llt->llt_lookup = in_lltable_lookup;
1293 llt->llt_dump = in_lltable_dump;
1294 }
1263 return (llt);
1295 ii->ii_llt = llt;
1296
1297 ii->ii_igmp = igmp_domifattach(ifp);
1298
1299 return ii;
1264}
1265
1266void
1300}
1301
1302void
1267in_domifdetach(struct ifnet *ifp __unused, void *aux)
1303in_domifdetach(struct ifnet *ifp, void *aux)
1268{
1304{
1269 struct lltable *llt = (struct lltable *)aux;
1305 struct in_ifinfo *ii = (struct in_ifinfo *)aux;
1270
1306
1271 lltable_free(llt);
1307 igmp_domifdetach(ifp);
1308 lltable_free(ii->ii_llt);
1309 free(ii, M_IFADDR);
1272}
1310}