Deleted Added
full compact
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 ---