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} |