Deleted Added
full compact
in6_pcb.c (58907) in6_pcb.c (62587)
1/* $FreeBSD: head/sys/netinet6/in6_pcb.c 62587 2000-07-04 16:35:15Z itojun $ */
2/* $KAME: in6_pcb.c,v 1.8 2000/06/09 00:37:02 itojun Exp $ */
3
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

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

21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright

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

24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
29 * $FreeBSD: head/sys/netinet6/in6_pcb.c 58907 2000-04-01 22:35:47Z shin $
30 */
31
32/*
33 * Copyright (c) 1982, 1986, 1991, 1993
34 * The Regents of the University of California. All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions

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

57 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
63 *
64 * @(#)in_pcb.c 8.2 (Berkeley) 1/4/94
32 */
33
34/*
35 * Copyright (c) 1982, 1986, 1991, 1993
36 * The Regents of the University of California. All rights reserved.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions

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

59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64 * SUCH DAMAGE.
65 *
66 * @(#)in_pcb.c 8.2 (Berkeley) 1/4/94
65 * $FreeBSD: head/sys/netinet6/in6_pcb.c 58907 2000-04-01 22:35:47Z shin $
66 */
67
68#include "opt_ipsec.h"
69
70#include <sys/param.h>
71#include <sys/systm.h>
72#include <sys/malloc.h>
73#include <sys/mbuf.h>

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

85
86#include <net/if.h>
87#include <net/if_types.h>
88#include <net/route.h>
89
90#include <netinet/in.h>
91#include <netinet/in_var.h>
92#include <netinet/in_systm.h>
67 */
68
69#include "opt_ipsec.h"
70
71#include <sys/param.h>
72#include <sys/systm.h>
73#include <sys/malloc.h>
74#include <sys/mbuf.h>

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

86
87#include <net/if.h>
88#include <net/if_types.h>
89#include <net/route.h>
90
91#include <netinet/in.h>
92#include <netinet/in_var.h>
93#include <netinet/in_systm.h>
93#include <netinet6/ip6.h>
94#include
94#include <netinet/ip_var.h>
95#include <netinet6/ip6_var.h>
96#include <netinet6/nd6.h>
97#include <netinet/in_pcb.h>
98#include <netinet6/in6_pcb.h>
99
100#include "faith.h"
101
102#ifdef IPSEC
103#include <netinet6/ipsec.h>
104#include <netinet6/ah.h>
105#include <netinet6/ipsec6.h>
106#include <netinet6/ah6.h>
107#include <netkey/key.h>
95#include <netinet/ip_var.h>
96#include <netinet6/ip6_var.h>
97#include <netinet6/nd6.h>
98#include <netinet/in_pcb.h>
99#include <netinet6/in6_pcb.h>
100
101#include "faith.h"
102
103#ifdef IPSEC
104#include <netinet6/ipsec.h>
105#include <netinet6/ah.h>
106#include <netinet6/ipsec6.h>
107#include <netinet6/ah6.h>
108#include <netkey/key.h>
108#ifdef IPSEC_DEBUG
109#include <netkey/key_debug.h>
110#else
111#define KEYDEBUG(lev,arg)
112#endif /* IPSEC_DEBUG */
113#endif /* IPSEC */
114
115struct in6_addr zeroin6_addr;
116
117int
118in6_pcbbind(inp, nam, p)
119 register struct inpcb *inp;
120 struct sockaddr *nam;
121 struct proc *p;
122{
123 struct socket *so = inp->inp_socket;
109#endif /* IPSEC */
110
111struct in6_addr zeroin6_addr;
112
113int
114in6_pcbbind(inp, nam, p)
115 register struct inpcb *inp;
116 struct sockaddr *nam;
117 struct proc *p;
118{
119 struct socket *so = inp->inp_socket;
124 unsigned short *lastport;
125 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)NULL;
126 struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
127 u_short lport = 0;
128 int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
120 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)NULL;
121 struct inpcbinfo *pcbinfo = inp->inp_pcbinfo;
122 u_short lport = 0;
123 int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
129 int error;
130
131 if (!in6_ifaddr) /* XXX broken! */
132 return (EADDRNOTAVAIL);
133 if (inp->inp_lport || !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
134 return(EINVAL);
135 if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
136 wild = 1;
137 if (nam) {
138 sin6 = (struct sockaddr_in6 *)nam;
139 if (nam->sa_len != sizeof(*sin6))
140 return(EINVAL);
141 /*
142 * family check.
143 */
144 if (nam->sa_family != AF_INET6)
145 return(EAFNOSUPPORT);
146
124
125 if (!in6_ifaddr) /* XXX broken! */
126 return (EADDRNOTAVAIL);
127 if (inp->inp_lport || !IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
128 return(EINVAL);
129 if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
130 wild = 1;
131 if (nam) {
132 sin6 = (struct sockaddr_in6 *)nam;
133 if (nam->sa_len != sizeof(*sin6))
134 return(EINVAL);
135 /*
136 * family check.
137 */
138 if (nam->sa_family != AF_INET6)
139 return(EAFNOSUPPORT);
140
147 /*
148 * If the scope of the destination is link-local, embed the
149 * interface index in the address.
150 */
151 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) {
152 /* XXX boundary check is assumed to be already done. */
153 /* XXX sin6_scope_id is weaker than advanced-api. */
154 struct in6_pktinfo *pi;
155 if (inp->in6p_outputopts &&
156 (pi = inp->in6p_outputopts->ip6po_pktinfo) &&
157 pi->ipi6_ifindex) {
158 sin6->sin6_addr.s6_addr16[1]
159 = htons(pi->ipi6_ifindex);
160 } else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)
161 && inp->in6p_moptions
162 && inp->in6p_moptions->im6o_multicast_ifp) {
163 sin6->sin6_addr.s6_addr16[1] =
164 htons(inp->in6p_moptions->im6o_multicast_ifp->if_index);
165 } else if (sin6->sin6_scope_id) {
166 /* boundary check */
167 if (sin6->sin6_scope_id < 0
168 || if_index < sin6->sin6_scope_id) {
169 return ENXIO; /* XXX EINVAL? */
170 }
171 sin6->sin6_addr.s6_addr16[1]
172 = htons(sin6->sin6_scope_id & 0xffff);/*XXX*/
173 /* this must be cleared for ifa_ifwithaddr() */
174 sin6->sin6_scope_id = 0;
175 }
176 }
141 /* KAME hack: embed scopeid */
142 if (in6_embedscope(&sin6->sin6_addr, sin6, inp, NULL) != 0)
143 return EINVAL;
144 /* this must be cleared for ifa_ifwithaddr() */
145 sin6->sin6_scope_id = 0;
177
178 lport = sin6->sin6_port;
179 if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
180 /*
181 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast;
182 * allow compepte duplication of binding if
183 * SO_REUSEPORT is set, or if SO_REUSEADDR is set
184 * and a multicast address is bound on both

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

219 if (t &&
220 (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
221 !IN6_IS_ADDR_UNSPECIFIED(&t->in6p_laddr) ||
222 (t->inp_socket->so_options &
223 SO_REUSEPORT) == 0) &&
224 (so->so_cred->cr_uid !=
225 t->inp_socket->so_cred->cr_uid))
226 return (EADDRINUSE);
146
147 lport = sin6->sin6_port;
148 if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
149 /*
150 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast;
151 * allow compepte duplication of binding if
152 * SO_REUSEPORT is set, or if SO_REUSEADDR is set
153 * and a multicast address is bound on both

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

188 if (t &&
189 (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) ||
190 !IN6_IS_ADDR_UNSPECIFIED(&t->in6p_laddr) ||
191 (t->inp_socket->so_options &
192 SO_REUSEPORT) == 0) &&
193 (so->so_cred->cr_uid !=
194 t->inp_socket->so_cred->cr_uid))
195 return (EADDRINUSE);
227 if ((inp->inp_flags & IN6P_BINDV6ONLY) == 0 &&
196 if (ip6_mapped_addr_on != 0 &&
228 IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
229 struct sockaddr_in sin;
230
231 in6_sin6_2_sin(&sin, sin6);
232 t = in_pcblookup_local(pcbinfo,
233 sin.sin_addr, lport,
234 INPLOOKUP_WILDCARD);
235 if (t &&

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

241 INP_SOCKAF(t->inp_socket)))
242 return (EADDRINUSE);
243 }
244 }
245 t = in6_pcblookup_local(pcbinfo, &sin6->sin6_addr,
246 lport, wild);
247 if (t && (reuseport & t->inp_socket->so_options) == 0)
248 return(EADDRINUSE);
197 IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
198 struct sockaddr_in sin;
199
200 in6_sin6_2_sin(&sin, sin6);
201 t = in_pcblookup_local(pcbinfo,
202 sin.sin_addr, lport,
203 INPLOOKUP_WILDCARD);
204 if (t &&

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

210 INP_SOCKAF(t->inp_socket)))
211 return (EADDRINUSE);
212 }
213 }
214 t = in6_pcblookup_local(pcbinfo, &sin6->sin6_addr,
215 lport, wild);
216 if (t && (reuseport & t->inp_socket->so_options) == 0)
217 return(EADDRINUSE);
249 if ((inp->inp_flags & IN6P_BINDV6ONLY) == 0 &&
218 if (ip6_mapped_addr_on != 0 &&
250 IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
251 struct sockaddr_in sin;
252
253 in6_sin6_2_sin(&sin, sin6);
254 t = in_pcblookup_local(pcbinfo, sin.sin_addr,
255 lport, wild);
256 if (t &&
257 (reuseport & t->inp_socket->so_options)
258 == 0 &&
259 (ntohl(t->inp_laddr.s_addr)
260 != INADDR_ANY ||
261 INP_SOCKAF(so) ==
262 INP_SOCKAF(t->inp_socket)))
263 return (EADDRINUSE);
264 }
265 }
266 inp->in6p_laddr = sin6->sin6_addr;
267 }
268 if (lport == 0) {
219 IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
220 struct sockaddr_in sin;
221
222 in6_sin6_2_sin(&sin, sin6);
223 t = in_pcblookup_local(pcbinfo, sin.sin_addr,
224 lport, wild);
225 if (t &&
226 (reuseport & t->inp_socket->so_options)
227 == 0 &&
228 (ntohl(t->inp_laddr.s_addr)
229 != INADDR_ANY ||
230 INP_SOCKAF(so) ==
231 INP_SOCKAF(t->inp_socket)))
232 return (EADDRINUSE);
233 }
234 }
235 inp->in6p_laddr = sin6->sin6_addr;
236 }
237 if (lport == 0) {
269 ushort first, last;
270 int count;
271
272 inp->inp_flags |= INP_ANONPORT;
273
274 if (inp->inp_flags & INP_HIGHPORT) {
275 first = ipport_hifirstauto; /* sysctl */
276 last = ipport_hilastauto;
277 lastport = &pcbinfo->lasthi;
278 } else if (inp->inp_flags & INP_LOWPORT) {
279 if (p && (error = suser_xxx(0, p, PRISON_ROOT)))
280 return error;
281 first = ipport_lowfirstauto; /* 1023 */
282 last = ipport_lowlastauto; /* 600 */
283 lastport = &pcbinfo->lastlow;
284 } else {
285 first = ipport_firstauto; /* sysctl */
286 last = ipport_lastauto;
287 lastport = &pcbinfo->lastport;
238 int e;
239 if ((e = in6_pcbsetport(&inp->in6p_laddr, inp, p)) != 0)
240 return(e);
241 }
242 else {
243 inp->inp_lport = lport;
244 if (in_pcbinshash(inp) != 0) {
245 inp->in6p_laddr = in6addr_any;
246 inp->inp_lport = 0;
247 return (EAGAIN);
288 }
248 }
289 /*
290 * Simple check to ensure all ports are not used up causing
291 * a deadlock here.
292 *
293 * We split the two cases (up and down) so that the direction
294 * is not being tested on each round of the loop.
295 */
296 if (first > last) {
297 /*
298 * counting down
299 */
300 count = first - last;
301
302 do {
303 if (count-- < 0) { /* completely used? */
304 /*
305 * Undo any address bind that may have
306 * occurred above.
307 */
308 inp->in6p_laddr = in6addr_any;
309 return (EAGAIN);
310 }
311 --*lastport;
312 if (*lastport > first || *lastport < last)
313 *lastport = first;
314 lport = htons(*lastport);
315 } while (in6_pcblookup_local(pcbinfo,
316 &inp->in6p_laddr, lport, wild));
317 } else {
318 /*
319 * counting up
320 */
321 count = last - first;
322
323 do {
324 if (count-- < 0) { /* completely used? */
325 /*
326 * Undo any address bind that may have
327 * occurred above.
328 */
329 inp->in6p_laddr = in6addr_any;
330 return (EAGAIN);
331 }
332 ++*lastport;
333 if (*lastport < first || *lastport > last)
334 *lastport = first;
335 lport = htons(*lastport);
336 } while (in6_pcblookup_local(pcbinfo,
337 &inp->in6p_laddr, lport, wild));
338 }
339 }
249 }
340 inp->inp_lport = lport;
341 if (in_pcbinshash(inp) != 0) {
342 inp->in6p_laddr = in6addr_any;
343 inp->inp_lport = 0;
344 return (EAGAIN);
345 }
346 inp->in6p_flowinfo = sin6 ? sin6->sin6_flowinfo : 0; /*XXX*/
347 return(0);
348}
349
350/*
351 * Transform old in6_pcbconnect() into an inner subroutine for new
352 * in6_pcbconnect(): Do some validity-checking on the remote
353 * address (in mbuf 'nam') and then determine local host address

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

372
373 if (nam->sa_len != sizeof (*sin6))
374 return (EINVAL);
375 if (sin6->sin6_family != AF_INET6)
376 return (EAFNOSUPPORT);
377 if (sin6->sin6_port == 0)
378 return (EADDRNOTAVAIL);
379
250 inp->in6p_flowinfo = sin6 ? sin6->sin6_flowinfo : 0; /*XXX*/
251 return(0);
252}
253
254/*
255 * Transform old in6_pcbconnect() into an inner subroutine for new
256 * in6_pcbconnect(): Do some validity-checking on the remote
257 * address (in mbuf 'nam') and then determine local host address

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

276
277 if (nam->sa_len != sizeof (*sin6))
278 return (EINVAL);
279 if (sin6->sin6_family != AF_INET6)
280 return (EAFNOSUPPORT);
281 if (sin6->sin6_port == 0)
282 return (EADDRNOTAVAIL);
283
380 /*
381 * If the scope of the destination is link-local, embed the interface
382 * index in the address.
383 */
384 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) {
385 /* XXX boundary check is assumed to be already done. */
386 /* XXX sin6_scope_id is weaker than advanced-api. */
387 if (inp->in6p_outputopts &&
388 (pi = inp->in6p_outputopts->ip6po_pktinfo) &&
389 pi->ipi6_ifindex) {
390 sin6->sin6_addr.s6_addr16[1] = htons(pi->ipi6_ifindex);
391 ifp = ifindex2ifnet[pi->ipi6_ifindex];
392 } else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr) &&
393 inp->in6p_moptions &&
394 inp->in6p_moptions->im6o_multicast_ifp) {
395 sin6->sin6_addr.s6_addr16[1] =
396 htons(inp->in6p_moptions->im6o_multicast_ifp->if_index);
397 ifp = ifindex2ifnet[inp->in6p_moptions->im6o_multicast_ifp->if_index];
398 } else if (sin6->sin6_scope_id) {
399 /* boundary check */
400 if (sin6->sin6_scope_id < 0
401 || if_index < sin6->sin6_scope_id) {
402 return ENXIO; /* XXX EINVAL? */
403 }
404 sin6->sin6_addr.s6_addr16[1]
405 = htons(sin6->sin6_scope_id & 0xffff);/*XXX*/
406 ifp = ifindex2ifnet[sin6->sin6_scope_id];
407 }
408 }
284 /* KAME hack: embed scopeid */
285 if (in6_embedscope(&sin6->sin6_addr, sin6, inp, &ifp) != 0)
286 return EINVAL;
409
410 if (in6_ifaddr) {
411 /*
412 * If the destination address is UNSPECIFIED addr,
413 * use the loopback addr, e.g ::1.
414 */
415 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
416 sin6->sin6_addr = in6addr_loopback;

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

435 * plocal_addr6
436 * and exit to caller, that will do the lookup.
437 */
438 }
439
440 if (inp->in6p_route.ro_rt)
441 ifp = inp->in6p_route.ro_rt->rt_ifp;
442
287
288 if (in6_ifaddr) {
289 /*
290 * If the destination address is UNSPECIFIED addr,
291 * use the loopback addr, e.g ::1.
292 */
293 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
294 sin6->sin6_addr = in6addr_loopback;

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

313 * plocal_addr6
314 * and exit to caller, that will do the lookup.
315 */
316 }
317
318 if (inp->in6p_route.ro_rt)
319 ifp = inp->in6p_route.ro_rt->rt_ifp;
320
443 inp->in6p_ip6_hlim = (u_int8_t)in6_selecthlim(inp, ifp);
444
445 return(0);
446}
447
448/*
449 * Outer subroutine:
450 * Connect from a socket to a specified address.
451 * Both address and port must be specified in argument sin.
452 * If don't have a local address for this socket yet,

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

494 ip6_auto_flowlabel != 0)
495 inp->in6p_flowinfo |=
496 (htonl(ip6_flow_seq++) & IPV6_FLOWLABEL_MASK);
497
498 in_pcbrehash(inp);
499 return (0);
500}
501
321 return(0);
322}
323
324/*
325 * Outer subroutine:
326 * Connect from a socket to a specified address.
327 * Both address and port must be specified in argument sin.
328 * If don't have a local address for this socket yet,

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

370 ip6_auto_flowlabel != 0)
371 inp->in6p_flowinfo |=
372 (htonl(ip6_flow_seq++) & IPV6_FLOWLABEL_MASK);
373
374 in_pcbrehash(inp);
375 return (0);
376}
377
378#if 0
502/*
503 * Return an IPv6 address, which is the most appropriate for given
504 * destination and user specified options.
505 * If necessary, this function lookups the routing table and return
506 * an entry to the caller for later use.
507 */
508struct in6_addr *
509in6_selectsrc(dstsock, opts, mopts, ro, laddr, errorp)

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

694{
695 if (in6p && in6p->in6p_hops >= 0)
696 return(in6p->in6p_hops);
697 else if (ifp)
698 return(nd_ifinfo[ifp->if_index].chlim);
699 else
700 return(ip6_defhlim);
701}
379/*
380 * Return an IPv6 address, which is the most appropriate for given
381 * destination and user specified options.
382 * If necessary, this function lookups the routing table and return
383 * an entry to the caller for later use.
384 */
385struct in6_addr *
386in6_selectsrc(dstsock, opts, mopts, ro, laddr, errorp)

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

571{
572 if (in6p && in6p->in6p_hops >= 0)
573 return(in6p->in6p_hops);
574 else if (ifp)
575 return(nd_ifinfo[ifp->if_index].chlim);
576 else
577 return(ip6_defhlim);
578}
579#endif
702
703void
704in6_pcbdisconnect(inp)
705 struct inpcb *inp;
706{
707 bzero((caddr_t)&inp->in6p_faddr, sizeof(inp->in6p_faddr));
708 inp->inp_fport = 0;
709 in_pcbrehash(inp);

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

886in6_pcbnotify(head, dst, fport_arg, laddr6, lport_arg, cmd, notify)
887 struct inpcbhead *head;
888 struct sockaddr *dst;
889 u_int fport_arg, lport_arg;
890 struct in6_addr *laddr6;
891 int cmd;
892 void (*notify) __P((struct inpcb *, int));
893{
580
581void
582in6_pcbdisconnect(inp)
583 struct inpcb *inp;
584{
585 bzero((caddr_t)&inp->in6p_faddr, sizeof(inp->in6p_faddr));
586 inp->inp_fport = 0;
587 in_pcbrehash(inp);

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

764in6_pcbnotify(head, dst, fport_arg, laddr6, lport_arg, cmd, notify)
765 struct inpcbhead *head;
766 struct sockaddr *dst;
767 u_int fport_arg, lport_arg;
768 struct in6_addr *laddr6;
769 int cmd;
770 void (*notify) __P((struct inpcb *, int));
771{
894 struct inpcb *inp, *oinp;
772 struct inpcb *inp, *ninp;
895 struct in6_addr faddr6;
896 u_short fport = fport_arg, lport = lport_arg;
897 int errno, s;
773 struct in6_addr faddr6;
774 u_short fport = fport_arg, lport = lport_arg;
775 int errno, s;
776 int do_rtchange = (notify == in6_rtchange);
898
899 if ((unsigned)cmd > PRC_NCMDS || dst->sa_family != AF_INET6)
900 return;
901 faddr6 = ((struct sockaddr_in6 *)dst)->sin6_addr;
902 if (IN6_IS_ADDR_UNSPECIFIED(&faddr6))
903 return;
904
905 /*
906 * Redirects go to all references to the destination,
777
778 if ((unsigned)cmd > PRC_NCMDS || dst->sa_family != AF_INET6)
779 return;
780 faddr6 = ((struct sockaddr_in6 *)dst)->sin6_addr;
781 if (IN6_IS_ADDR_UNSPECIFIED(&faddr6))
782 return;
783
784 /*
785 * Redirects go to all references to the destination,
907 * and use in_rtchange to invalidate the route cache.
908 * Dead host indications: notify all references to the destination.
786 * and use in6_rtchange to invalidate the route cache.
787 * Dead host indications: also use in6_rtchange to invalidate
788 * the cache, and deliver the error to all the sockets.
909 * Otherwise, if we have knowledge of the local port and address,
910 * deliver only to that socket.
911 */
912 if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) {
913 fport = 0;
914 lport = 0;
915 bzero((caddr_t)laddr6, sizeof(*laddr6));
789 * Otherwise, if we have knowledge of the local port and address,
790 * deliver only to that socket.
791 */
792 if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) {
793 fport = 0;
794 lport = 0;
795 bzero((caddr_t)laddr6, sizeof(*laddr6));
916 if (cmd != PRC_HOSTDEAD)
917 notify = in6_rtchange;
796
797 do_rtchange = 1;
918 }
919 errno = inet6ctlerrmap[cmd];
920 s = splnet();
798 }
799 errno = inet6ctlerrmap[cmd];
800 s = splnet();
921 for (inp = LIST_FIRST(head); inp != NULL;) {
922 if ((inp->inp_vflag & INP_IPV6) == 0) {
923 inp = LIST_NEXT(inp, inp_list);
801 for (inp = LIST_FIRST(head); inp != NULL; inp = ninp) {
802 ninp = LIST_NEXT(inp, inp_list);
803
804 if ((inp->inp_vflag & INP_IPV6) == NULL)
924 continue;
805 continue;
925 }
806
807 if (do_rtchange) {
808 /*
809 * Since a non-connected PCB might have a cached route,
810 * we always call in6_rtchange without matching
811 * the PCB to the src/dst pair.
812 *
813 * XXX: we assume in6_rtchange does not free the PCB.
814 */
815 if (IN6_ARE_ADDR_EQUAL(&inp->in6p_route.ro_dst.sin6_addr,
816 &faddr6))
817 in6_rtchange(inp, errno);
818
819 if (notify == in6_rtchange)
820 continue; /* there's nothing to do any more */
821 }
822
926 if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, &faddr6) ||
927 inp->inp_socket == 0 ||
928 (lport && inp->inp_lport != lport) ||
929 (!IN6_IS_ADDR_UNSPECIFIED(laddr6) &&
930 !IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr6)) ||
823 if (!IN6_ARE_ADDR_EQUAL(&inp->in6p_faddr, &faddr6) ||
824 inp->inp_socket == 0 ||
825 (lport && inp->inp_lport != lport) ||
826 (!IN6_IS_ADDR_UNSPECIFIED(laddr6) &&
827 !IN6_ARE_ADDR_EQUAL(&inp->in6p_laddr, laddr6)) ||
931 (fport && inp->inp_fport != fport)) {
932 inp = LIST_NEXT(inp, inp_list);
828 (fport && inp->inp_fport != fport))
933 continue;
829 continue;
934 }
935 oinp = inp;
936 inp = LIST_NEXT(inp, inp_list);
830
937 if (notify)
831 if (notify)
938 (*notify)(oinp, errno);
832 (*notify)(inp, errno);
939 }
940 splx(s);
941}
942
943/*
944 * Lookup a PCB based on the local address and port.
945 */
946struct inpcb *

--- 221 unchanged lines hidden ---
833 }
834 splx(s);
835}
836
837/*
838 * Lookup a PCB based on the local address and port.
839 */
840struct inpcb *

--- 221 unchanged lines hidden ---