in6_src.c (194760) | in6_src.c (194777) |
---|---|
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_pcb.c 8.2 (Berkeley) 1/4/94 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_pcb.c 8.2 (Berkeley) 1/4/94 61 */ 62 63#include <sys/cdefs.h> |
64__FBSDID("$FreeBSD: head/sys/netinet6/in6_src.c 194760 2009-06-23 20:19:09Z rwatson $"); | 64__FBSDID("$FreeBSD: head/sys/netinet6/in6_src.c 194777 2009-06-23 22:08:55Z bz $"); |
65 66#include "opt_inet.h" 67#include "opt_inet6.h" 68#include "opt_mpath.h" 69 70#include <sys/param.h> 71#include <sys/systm.h> 72#include <sys/lock.h> --- 101 unchanged lines hidden (view full) --- 174} while(0) 175#define BREAK(r) do { \ 176 if ((r) < sizeof(V_ip6stat.ip6s_sources_rule) / \ 177 sizeof(V_ip6stat.ip6s_sources_rule[0])) /* check for safety */ \ 178 V_ip6stat.ip6s_sources_rule[(r)]++; \ 179 goto out; /* XXX: we can't use 'break' here */ \ 180} while(0) 181 | 65 66#include "opt_inet.h" 67#include "opt_inet6.h" 68#include "opt_mpath.h" 69 70#include <sys/param.h> 71#include <sys/systm.h> 72#include <sys/lock.h> --- 101 unchanged lines hidden (view full) --- 174} while(0) 175#define BREAK(r) do { \ 176 if ((r) < sizeof(V_ip6stat.ip6s_sources_rule) / \ 177 sizeof(V_ip6stat.ip6s_sources_rule[0])) /* check for safety */ \ 178 V_ip6stat.ip6s_sources_rule[(r)]++; \ 179 goto out; /* XXX: we can't use 'break' here */ \ 180} while(0) 181 |
182struct in6_addr * | 182int |
183in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, 184 struct inpcb *inp, struct route_in6 *ro, struct ucred *cred, | 183in6_selectsrc(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, 184 struct inpcb *inp, struct route_in6 *ro, struct ucred *cred, |
185 struct ifnet **ifpp, int *errorp) | 185 struct ifnet **ifpp, struct in6_addr *srcp) |
186{ 187 INIT_VNET_INET6(curvnet); 188 struct in6_addr dst; 189 struct ifnet *ifp = NULL; 190 struct in6_ifaddr *ia = NULL, *ia_best = NULL; 191 struct in6_pktinfo *pi = NULL; 192 int dst_scope = -1, best_scope = -1, best_matchlen = -1; 193 struct in6_addrpolicy *dst_policy = NULL, *best_policy = NULL; 194 u_int32_t odstzone; 195 int prefer_tempaddr; | 186{ 187 INIT_VNET_INET6(curvnet); 188 struct in6_addr dst; 189 struct ifnet *ifp = NULL; 190 struct in6_ifaddr *ia = NULL, *ia_best = NULL; 191 struct in6_pktinfo *pi = NULL; 192 int dst_scope = -1, best_scope = -1, best_matchlen = -1; 193 struct in6_addrpolicy *dst_policy = NULL, *best_policy = NULL; 194 u_int32_t odstzone; 195 int prefer_tempaddr; |
196 int error; |
|
196 struct ip6_moptions *mopts; 197 | 197 struct ip6_moptions *mopts; 198 |
199 KASSERT(srcp != NULL, ("%s: srcp is NULL", __func__)); 200 |
|
198 dst = dstsock->sin6_addr; /* make a copy for local operation */ | 201 dst = dstsock->sin6_addr; /* make a copy for local operation */ |
199 *errorp = 0; | |
200 if (ifpp) 201 *ifpp = NULL; 202 203 if (inp != NULL) { 204 INP_LOCK_ASSERT(inp); 205 mopts = inp->in6p_moptions; 206 } else { 207 mopts = NULL; --- 6 unchanged lines hidden (view full) --- 214 * address. If everything is okay, use the address as source. 215 */ 216 if (opts && (pi = opts->ip6po_pktinfo) && 217 !IN6_IS_ADDR_UNSPECIFIED(&pi->ipi6_addr)) { 218 struct sockaddr_in6 srcsock; 219 struct in6_ifaddr *ia6; 220 221 /* get the outgoing interface */ | 202 if (ifpp) 203 *ifpp = NULL; 204 205 if (inp != NULL) { 206 INP_LOCK_ASSERT(inp); 207 mopts = inp->in6p_moptions; 208 } else { 209 mopts = NULL; --- 6 unchanged lines hidden (view full) --- 216 * address. If everything is okay, use the address as source. 217 */ 218 if (opts && (pi = opts->ip6po_pktinfo) && 219 !IN6_IS_ADDR_UNSPECIFIED(&pi->ipi6_addr)) { 220 struct sockaddr_in6 srcsock; 221 struct in6_ifaddr *ia6; 222 223 /* get the outgoing interface */ |
222 if ((*errorp = in6_selectif(dstsock, opts, mopts, ro, &ifp)) 223 != 0) { 224 return (NULL); 225 } | 224 if ((error = in6_selectif(dstsock, opts, mopts, ro, &ifp)) != 0) 225 return (error); |
226 227 /* 228 * determine the appropriate zone id of the source based on 229 * the zone of the destination and the outgoing interface. 230 * If the specified address is ambiguous wrt the scope zone, 231 * the interface must be specified; otherwise, ifa_ifwithaddr() 232 * will fail matching the address. 233 */ 234 bzero(&srcsock, sizeof(srcsock)); 235 srcsock.sin6_family = AF_INET6; 236 srcsock.sin6_len = sizeof(srcsock); 237 srcsock.sin6_addr = pi->ipi6_addr; 238 if (ifp) { | 226 227 /* 228 * determine the appropriate zone id of the source based on 229 * the zone of the destination and the outgoing interface. 230 * If the specified address is ambiguous wrt the scope zone, 231 * the interface must be specified; otherwise, ifa_ifwithaddr() 232 * will fail matching the address. 233 */ 234 bzero(&srcsock, sizeof(srcsock)); 235 srcsock.sin6_family = AF_INET6; 236 srcsock.sin6_len = sizeof(srcsock); 237 srcsock.sin6_addr = pi->ipi6_addr; 238 if (ifp) { |
239 *errorp = in6_setscope(&srcsock.sin6_addr, ifp, NULL); 240 if (*errorp != 0) 241 return (NULL); | 239 error = in6_setscope(&srcsock.sin6_addr, ifp, NULL); 240 if (error) 241 return (error); |
242 } | 242 } |
243 if (cred != NULL && (*errorp = prison_local_ip6(cred, | 243 if (cred != NULL && (error = prison_local_ip6(cred, |
244 &srcsock.sin6_addr, (inp != NULL && 245 (inp->inp_flags & IN6P_IPV6_V6ONLY) != 0))) != 0) | 244 &srcsock.sin6_addr, (inp != NULL && 245 (inp->inp_flags & IN6P_IPV6_V6ONLY) != 0))) != 0) |
246 return (NULL); | 246 return (error); |
247 248 ia6 = (struct in6_ifaddr *)ifa_ifwithaddr( 249 (struct sockaddr *)&srcsock); 250 if (ia6 == NULL || 251 (ia6->ia6_flags & (IN6_IFF_ANYCAST | IN6_IFF_NOTREADY))) { 252 if (ia6 != NULL) 253 ifa_free(&ia6->ia_ifa); | 247 248 ia6 = (struct in6_ifaddr *)ifa_ifwithaddr( 249 (struct sockaddr *)&srcsock); 250 if (ia6 == NULL || 251 (ia6->ia6_flags & (IN6_IFF_ANYCAST | IN6_IFF_NOTREADY))) { 252 if (ia6 != NULL) 253 ifa_free(&ia6->ia_ifa); |
254 *errorp = EADDRNOTAVAIL; 255 return (NULL); | 254 return (EADDRNOTAVAIL); |
256 } 257 pi->ipi6_addr = srcsock.sin6_addr; /* XXX: this overrides pi */ 258 if (ifpp) 259 *ifpp = ifp; | 255 } 256 pi->ipi6_addr = srcsock.sin6_addr; /* XXX: this overrides pi */ 257 if (ifpp) 258 *ifpp = ifp; |
260 261 /* 262 * XXXRW: This returns a pointer into a structure with no 263 * refcount. in6_selectsrc() should return it to caller- 264 * provided memory using call-by-reference rather than 265 * returning pointers into other memory. 266 */ | 259 bcopy(&ia6->ia_addr.sin6_addr, srcp, sizeof(*srcp)); |
267 ifa_free(&ia6->ia_ifa); | 260 ifa_free(&ia6->ia_ifa); |
268 return (&ia6->ia_addr.sin6_addr); | 261 return (0); |
269 } 270 271 /* 272 * Otherwise, if the socket has already bound the source, just use it. 273 */ 274 if (inp != NULL && !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) { 275 if (cred != NULL && | 262 } 263 264 /* 265 * Otherwise, if the socket has already bound the source, just use it. 266 */ 267 if (inp != NULL && !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) { 268 if (cred != NULL && |
276 (*errorp = prison_local_ip6(cred, &inp->in6p_laddr, | 269 (error = prison_local_ip6(cred, &inp->in6p_laddr, |
277 ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0))) != 0) | 270 ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0))) != 0) |
278 return (NULL); 279 return (&inp->in6p_laddr); | 271 return (error); 272 bcopy(&inp->in6p_laddr, srcp, sizeof(*srcp)); 273 return (0); |
280 } 281 282 /* 283 * If the address is not specified, choose the best one based on 284 * the outgoing interface and the destination address. 285 */ 286 /* get the outgoing interface */ | 274 } 275 276 /* 277 * If the address is not specified, choose the best one based on 278 * the outgoing interface and the destination address. 279 */ 280 /* get the outgoing interface */ |
287 if ((*errorp = in6_selectif(dstsock, opts, mopts, ro, &ifp)) != 0) 288 return (NULL); | 281 if ((error = in6_selectif(dstsock, opts, mopts, ro, &ifp)) != 0) 282 return (error); |
289 290#ifdef DIAGNOSTIC 291 if (ifp == NULL) /* this should not happen */ 292 panic("in6_selectsrc: NULL ifp"); 293#endif | 283 284#ifdef DIAGNOSTIC 285 if (ifp == NULL) /* this should not happen */ 286 panic("in6_selectsrc: NULL ifp"); 287#endif |
294 *errorp = in6_setscope(&dst, ifp, &odstzone); 295 if (*errorp != 0) 296 return (NULL); | 288 error = in6_setscope(&dst, ifp, &odstzone); 289 if (error) 290 return (error); |
297 298 for (ia = V_in6_ifaddr; ia; ia = ia->ia_next) { 299 int new_scope = -1, new_matchlen = -1; 300 struct in6_addrpolicy *new_policy = NULL; 301 u_int32_t srczone, osrczone, dstzone; 302 struct in6_addr src; 303 struct ifnet *ifp1 = ia->ia_ifp; 304 --- 162 unchanged lines hidden (view full) --- 467 468 next: 469 continue; 470 471 out: 472 break; 473 } 474 | 291 292 for (ia = V_in6_ifaddr; ia; ia = ia->ia_next) { 293 int new_scope = -1, new_matchlen = -1; 294 struct in6_addrpolicy *new_policy = NULL; 295 u_int32_t srczone, osrczone, dstzone; 296 struct in6_addr src; 297 struct ifnet *ifp1 = ia->ia_ifp; 298 --- 162 unchanged lines hidden (view full) --- 461 462 next: 463 continue; 464 465 out: 466 break; 467 } 468 |
475 if ((ia = ia_best) == NULL) { 476 *errorp = EADDRNOTAVAIL; 477 return (NULL); 478 } | 469 if ((ia = ia_best) == NULL) 470 return (EADDRNOTAVAIL); |
479 480 if (ifpp) 481 *ifpp = ifp; 482 | 471 472 if (ifpp) 473 *ifpp = ifp; 474 |
483 return (&ia->ia_addr.sin6_addr); | 475 bcopy(&ia->ia_addr.sin6_addr, srcp, sizeof(*srcp)); 476 return (0); |
484} 485 486/* 487 * clone - meaningful only for bsdi and freebsd 488 */ 489static int 490selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, 491 struct ip6_moptions *mopts, struct route_in6 *ro, --- 702 unchanged lines hidden --- | 477} 478 479/* 480 * clone - meaningful only for bsdi and freebsd 481 */ 482static int 483selectroute(struct sockaddr_in6 *dstsock, struct ip6_pktopts *opts, 484 struct ip6_moptions *mopts, struct route_in6 *ro, --- 702 unchanged lines hidden --- |