in6.c (287617) | in6.c (287789) |
---|---|
1/*- 2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 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 --- 47 unchanged lines hidden (view full) --- 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * SUCH DAMAGE. 59 * 60 * @(#)in.c 8.2 (Berkeley) 11/15/93 61 */ 62 63#include <sys/cdefs.h> | 1/*- 2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 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 --- 47 unchanged lines hidden (view full) --- 56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 58 * SUCH DAMAGE. 59 * 60 * @(#)in.c 8.2 (Berkeley) 11/15/93 61 */ 62 63#include <sys/cdefs.h> |
64__FBSDID("$FreeBSD: head/sys/netinet6/in6.c 287617 2015-09-10 08:37:03Z hrs $"); | 64__FBSDID("$FreeBSD: head/sys/netinet6/in6.c 287789 2015-09-14 16:48:19Z melifaro $"); |
65 66#include "opt_compat.h" 67#include "opt_inet.h" 68#include "opt_inet6.h" 69 70#include <sys/param.h> 71#include <sys/eventhandler.h> 72#include <sys/errno.h> --- 1229 unchanged lines hidden (view full) --- 1302 (struct sockaddr *)&ia->ia_addr); 1303 if (error == 0) 1304 ia->ia_flags &= ~IFA_RTSELF; 1305 } 1306 1307 /* stop DAD processing */ 1308 nd6_dad_stop(ifa); 1309 | 65 66#include "opt_compat.h" 67#include "opt_inet.h" 68#include "opt_inet6.h" 69 70#include <sys/param.h> 71#include <sys/eventhandler.h> 72#include <sys/errno.h> --- 1229 unchanged lines hidden (view full) --- 1302 (struct sockaddr *)&ia->ia_addr); 1303 if (error == 0) 1304 ia->ia_flags &= ~IFA_RTSELF; 1305 } 1306 1307 /* stop DAD processing */ 1308 nd6_dad_stop(ifa); 1309 |
1310 /* Remove local address entry from lltable. */ 1311 nd6_rem_ifa_lle(ia); 1312 | |
1313 /* Leave multicast groups. */ 1314 while ((imm = LIST_FIRST(&ia->ia6_memberships)) != NULL) { 1315 LIST_REMOVE(imm, i6mm_chain); 1316 in6_leavegroup(imm); 1317 } 1318 plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */ 1319 if ((ia->ia_flags & IFA_ROUTE) && plen == 128) { 1320 error = rtinit(&(ia->ia_ifa), RTM_DELETE, ia->ia_flags | --- 7 unchanged lines hidden (view full) --- 1328 in6_newaddrmsg(ia, RTM_DELETE); 1329 in6_unlink_ifa(ia, ifp); 1330} 1331 1332static void 1333in6_unlink_ifa(struct in6_ifaddr *ia, struct ifnet *ifp) 1334{ 1335 char ip6buf[INET6_ADDRSTRLEN]; | 1310 /* Leave multicast groups. */ 1311 while ((imm = LIST_FIRST(&ia->ia6_memberships)) != NULL) { 1312 LIST_REMOVE(imm, i6mm_chain); 1313 in6_leavegroup(imm); 1314 } 1315 plen = in6_mask2len(&ia->ia_prefixmask.sin6_addr, NULL); /* XXX */ 1316 if ((ia->ia_flags & IFA_ROUTE) && plen == 128) { 1317 error = rtinit(&(ia->ia_ifa), RTM_DELETE, ia->ia_flags | --- 7 unchanged lines hidden (view full) --- 1325 in6_newaddrmsg(ia, RTM_DELETE); 1326 in6_unlink_ifa(ia, ifp); 1327} 1328 1329static void 1330in6_unlink_ifa(struct in6_ifaddr *ia, struct ifnet *ifp) 1331{ 1332 char ip6buf[INET6_ADDRSTRLEN]; |
1333 int remove_lle; |
|
1336 1337 IF_ADDR_WLOCK(ifp); 1338 TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link); 1339 IF_ADDR_WUNLOCK(ifp); 1340 ifa_free(&ia->ia_ifa); /* if_addrhead */ 1341 1342 /* 1343 * Defer the release of what might be the last reference to the --- 4 unchanged lines hidden (view full) --- 1348 TAILQ_REMOVE(&V_in6_ifaddrhead, ia, ia_link); 1349 LIST_REMOVE(ia, ia6_hash); 1350 IN6_IFADDR_WUNLOCK(); 1351 1352 /* 1353 * Release the reference to the base prefix. There should be a 1354 * positive reference. 1355 */ | 1334 1335 IF_ADDR_WLOCK(ifp); 1336 TAILQ_REMOVE(&ifp->if_addrhead, &ia->ia_ifa, ifa_link); 1337 IF_ADDR_WUNLOCK(ifp); 1338 ifa_free(&ia->ia_ifa); /* if_addrhead */ 1339 1340 /* 1341 * Defer the release of what might be the last reference to the --- 4 unchanged lines hidden (view full) --- 1346 TAILQ_REMOVE(&V_in6_ifaddrhead, ia, ia_link); 1347 LIST_REMOVE(ia, ia6_hash); 1348 IN6_IFADDR_WUNLOCK(); 1349 1350 /* 1351 * Release the reference to the base prefix. There should be a 1352 * positive reference. 1353 */ |
1354 remove_lle = 0; |
|
1356 if (ia->ia6_ndpr == NULL) { 1357 nd6log((LOG_NOTICE, 1358 "in6_unlink_ifa: autoconf'ed address " 1359 "%s has no prefix\n", ip6_sprintf(ip6buf, IA6_IN6(ia)))); 1360 } else { 1361 ia->ia6_ndpr->ndpr_refcnt--; | 1355 if (ia->ia6_ndpr == NULL) { 1356 nd6log((LOG_NOTICE, 1357 "in6_unlink_ifa: autoconf'ed address " 1358 "%s has no prefix\n", ip6_sprintf(ip6buf, IA6_IN6(ia)))); 1359 } else { 1360 ia->ia6_ndpr->ndpr_refcnt--; |
1361 /* Do not delete lles within prefix if refcont != 0 */ 1362 if (ia->ia6_ndpr->ndpr_refcnt == 0) 1363 remove_lle = 1; |
|
1362 ia->ia6_ndpr = NULL; 1363 } 1364 | 1364 ia->ia6_ndpr = NULL; 1365 } 1366 |
1367 nd6_rem_ifa_lle(ia, remove_lle); 1368 |
|
1365 /* 1366 * Also, if the address being removed is autoconf'ed, call 1367 * pfxlist_onlink_check() since the release might affect the status of 1368 * other (detached) addresses. 1369 */ 1370 if ((ia->ia6_flags & IN6_IFF_AUTOCONF)) { 1371 pfxlist_onlink_check(); 1372 } --- 703 unchanged lines hidden (view full) --- 2076 lle->base.lle_free = in6_lltable_destroy_lle; 2077 LLE_LOCK_INIT(&lle->base); 2078 callout_init(&lle->base.lle_timer, 1); 2079 2080 return (&lle->base); 2081} 2082 2083static int | 1369 /* 1370 * Also, if the address being removed is autoconf'ed, call 1371 * pfxlist_onlink_check() since the release might affect the status of 1372 * other (detached) addresses. 1373 */ 1374 if ((ia->ia6_flags & IN6_IFF_AUTOCONF)) { 1375 pfxlist_onlink_check(); 1376 } --- 703 unchanged lines hidden (view full) --- 2080 lle->base.lle_free = in6_lltable_destroy_lle; 2081 LLE_LOCK_INIT(&lle->base); 2082 callout_init(&lle->base.lle_timer, 1); 2083 2084 return (&lle->base); 2085} 2086 2087static int |
2084in6_lltable_match_prefix(const struct sockaddr *prefix, 2085 const struct sockaddr *mask, u_int flags, struct llentry *lle) | 2088in6_lltable_match_prefix(const struct sockaddr *saddr, 2089 const struct sockaddr *smask, u_int flags, struct llentry *lle) |
2086{ | 2090{ |
2087 const struct sockaddr_in6 *pfx = (const struct sockaddr_in6 *)prefix; 2088 const struct sockaddr_in6 *msk = (const struct sockaddr_in6 *)mask; | 2091 const struct in6_addr *addr, *mask, *lle_addr; |
2089 | 2092 |
2090 if (IN6_ARE_MASKED_ADDR_EQUAL(&lle->r_l3addr.addr6, 2091 &pfx->sin6_addr, &msk->sin6_addr) && 2092 ((flags & LLE_STATIC) || !(lle->la_flags & LLE_STATIC))) | 2093 addr = &((const struct sockaddr_in6 *)saddr)->sin6_addr; 2094 mask = &((const struct sockaddr_in6 *)smask)->sin6_addr; 2095 lle_addr = &lle->r_l3addr.addr6; 2096 2097 if (IN6_ARE_MASKED_ADDR_EQUAL(lle_addr, addr, mask) == 0) 2098 return (0); 2099 2100 if (lle->la_flags & LLE_IFADDR) { 2101 2102 /* 2103 * Delete LLE_IFADDR records IFF address & flag matches. 2104 * Note that addr is the interface address within prefix 2105 * being matched. 2106 */ 2107 if (IN6_ARE_ADDR_EQUAL(addr, lle_addr) && 2108 (flags & LLE_STATIC) != 0) 2109 return (1); 2110 return (0); 2111 } 2112 2113 /* flags & LLE_STATIC means deleting both dynamic and static entries */ 2114 if ((flags & LLE_STATIC) || !(lle->la_flags & LLE_STATIC)) |
2093 return (1); 2094 2095 return (0); 2096} 2097 2098static void 2099in6_lltable_free_entry(struct lltable *llt, struct llentry *lle) 2100{ --- 94 unchanged lines hidden (view full) --- 2195 continue; 2196 if (IN6_ARE_ADDR_EQUAL(&lle->r_l3addr.addr6, dst)) 2197 break; 2198 } 2199 2200 return (lle); 2201} 2202 | 2115 return (1); 2116 2117 return (0); 2118} 2119 2120static void 2121in6_lltable_free_entry(struct lltable *llt, struct llentry *lle) 2122{ --- 94 unchanged lines hidden (view full) --- 2217 continue; 2218 if (IN6_ARE_ADDR_EQUAL(&lle->r_l3addr.addr6, dst)) 2219 break; 2220 } 2221 2222 return (lle); 2223} 2224 |
2203static int 2204in6_lltable_delete(struct lltable *llt, u_int flags, 2205 const struct sockaddr *l3addr) | 2225static void 2226in6_lltable_delete_entry(struct lltable *llt, struct llentry *lle) |
2206{ | 2227{ |
2207 const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)l3addr; 2208 struct llentry *lle; | |
2209 | 2228 |
2210 IF_AFDATA_LOCK_ASSERT(llt->llt_ifp); 2211 KASSERT(l3addr->sa_family == AF_INET6, 2212 ("sin_family %d", l3addr->sa_family)); 2213 2214 lle = in6_lltable_find_dst(llt, &sin6->sin6_addr); 2215 2216 if (lle == NULL) 2217 return (ENOENT); 2218 2219 if (!(lle->la_flags & LLE_IFADDR) || (flags & LLE_IFADDR)) { 2220 LLE_WLOCK(lle); 2221 lle->la_flags |= LLE_DELETED; 2222 EVENTHANDLER_INVOKE(lle_event, lle, LLENTRY_DELETED); | 2229 lle->la_flags |= LLE_DELETED; 2230 EVENTHANDLER_INVOKE(lle_event, lle, LLENTRY_DELETED); |
2223#ifdef DIAGNOSTIC | 2231#ifdef DIAGNOSTIC |
2224 log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle); | 2232 log(LOG_INFO, "ifaddr cache = %p is deleted\n", lle); |
2225#endif | 2233#endif |
2226 if ((lle->la_flags & (LLE_STATIC | LLE_IFADDR)) == LLE_STATIC) 2227 llentry_free(lle); 2228 else 2229 LLE_WUNLOCK(lle); 2230 } 2231 2232 return (0); | 2234 llentry_free(lle); |
2233} 2234 2235static struct llentry * 2236in6_lltable_alloc(struct lltable *llt, u_int flags, 2237 const struct sockaddr *l3addr) 2238{ 2239 const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)l3addr; 2240 struct ifnet *ifp = llt->llt_ifp; --- 123 unchanged lines hidden (view full) --- 2364 struct lltable *llt; 2365 2366 llt = lltable_allocate_htbl(IN6_LLTBL_DEFAULT_HSIZE); 2367 llt->llt_af = AF_INET6; 2368 llt->llt_ifp = ifp; 2369 2370 llt->llt_lookup = in6_lltable_lookup; 2371 llt->llt_alloc_entry = in6_lltable_alloc; | 2235} 2236 2237static struct llentry * 2238in6_lltable_alloc(struct lltable *llt, u_int flags, 2239 const struct sockaddr *l3addr) 2240{ 2241 const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)l3addr; 2242 struct ifnet *ifp = llt->llt_ifp; --- 123 unchanged lines hidden (view full) --- 2366 struct lltable *llt; 2367 2368 llt = lltable_allocate_htbl(IN6_LLTBL_DEFAULT_HSIZE); 2369 llt->llt_af = AF_INET6; 2370 llt->llt_ifp = ifp; 2371 2372 llt->llt_lookup = in6_lltable_lookup; 2373 llt->llt_alloc_entry = in6_lltable_alloc; |
2372 llt->llt_delete = in6_lltable_delete; | 2374 llt->llt_delete_entry = in6_lltable_delete_entry; |
2373 llt->llt_dump_entry = in6_lltable_dump_entry; 2374 llt->llt_hash = in6_lltable_hash; 2375 llt->llt_fill_sa_entry = in6_lltable_fill_sa_entry; 2376 llt->llt_free_entry = in6_lltable_free_entry; 2377 llt->llt_match_prefix = in6_lltable_match_prefix; 2378 lltable_link(llt); 2379 2380 return (llt); --- 120 unchanged lines hidden --- | 2375 llt->llt_dump_entry = in6_lltable_dump_entry; 2376 llt->llt_hash = in6_lltable_hash; 2377 llt->llt_fill_sa_entry = in6_lltable_fill_sa_entry; 2378 llt->llt_free_entry = in6_lltable_free_entry; 2379 llt->llt_match_prefix = in6_lltable_match_prefix; 2380 lltable_link(llt); 2381 2382 return (llt); --- 120 unchanged lines hidden --- |