in6_pcb.c revision 1.8 1 /* $NetBSD: in6_pcb.c,v 1.8 1999/07/17 07:07:09 itojun Exp $ */
2
3 /*
4 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the project nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
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
38 * are met:
39 * 1. Redistributions of source code must retain the above copyright
40 * notice, this list of conditions and the following disclaimer.
41 * 2. Redistributions in binary form must reproduce the above copyright
42 * notice, this list of conditions and the following disclaimer in the
43 * documentation and/or other materials provided with the distribution.
44 * 3. All advertising materials mentioning features or use of this software
45 * must display the following acknowledgement:
46 * This product includes software developed by the University of
47 * California, Berkeley and its contributors.
48 * 4. Neither the name of the University nor the names of its contributors
49 * may be used to endorse or promote products derived from this software
50 * without specific prior written permission.
51 *
52 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
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
65 */
66
67 #include "opt_ipsec.h"
68
69 #include <sys/param.h>
70 #include <sys/systm.h>
71 #include <sys/malloc.h>
72 #include <sys/mbuf.h>
73 #include <sys/protosw.h>
74 #include <sys/socket.h>
75 #include <sys/socketvar.h>
76 #include <sys/ioctl.h>
77 #include <sys/errno.h>
78 #include <sys/time.h>
79 #include <sys/proc.h>
80
81 #include <net/if.h>
82 #include <net/route.h>
83
84 #include <netinet/in.h>
85 #include <netinet/in_var.h>
86 #include <netinet/in_systm.h>
87 #include <netinet/ip.h>
88 #include <netinet/in_pcb.h>
89 #include <netinet6/ip6.h>
90 #include <netinet6/in6_pcb.h>
91 #include <netinet6/ip6_var.h>
92 #include <netinet6/nd6.h>
93
94 #include "loop.h"
95 #ifdef __NetBSD__
96 extern struct ifnet loif[NLOOP];
97 #endif
98 #include "faith.h"
99
100 #ifdef IPSEC
101 #include <netinet6/ipsec.h>
102 #include <netkey/key.h>
103 #include <netkey/key_debug.h>
104 #endif /* IPSEC */
105
106 struct in6_addr zeroin6_addr;
107
108 int
109 in6_pcballoc(so, head)
110 struct socket *so;
111 struct in6pcb *head;
112 {
113 struct in6pcb *in6p;
114
115 MALLOC(in6p, struct in6pcb *, sizeof(*in6p), M_PCB, M_NOWAIT);
116 if (in6p == NULL)
117 return(ENOBUFS);
118 bzero((caddr_t)in6p, sizeof(*in6p));
119 in6p->in6p_head = head;
120 in6p->in6p_socket = so;
121 in6p->in6p_hops = -1; /* use kernel default */
122 in6p->in6p_icmp6filt = NULL;
123 #if 0
124 insque(in6p, head);
125 #else
126 in6p->in6p_next = head->in6p_next;
127 head->in6p_next = in6p;
128 in6p->in6p_prev = head;
129 in6p->in6p_next->in6p_prev = in6p;
130 #endif
131 so->so_pcb = (caddr_t)in6p;
132 return(0);
133 }
134
135 int
136 in6_pcbbind(in6p, nam)
137 register struct in6pcb *in6p;
138 struct mbuf *nam;
139 {
140 struct socket *so = in6p->in6p_socket;
141 struct in6pcb *head = in6p->in6p_head;
142 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)NULL;
143 struct proc *p = curproc; /* XXX */
144 u_short lport = 0;
145 int wild = 0, reuseport = (so->so_options & SO_REUSEPORT);
146 int error;
147
148 if (in6p->in6p_lport || !IN6_IS_ADDR_ANY(&in6p->in6p_laddr))
149 return(EINVAL);
150 if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0 &&
151 ((so->so_proto->pr_flags & PR_CONNREQUIRED) == 0 ||
152 (so->so_options & SO_ACCEPTCONN) == 0))
153 wild = IN6PLOOKUP_WILDCARD;
154 if (nam) {
155 sin6 = mtod(nam, struct sockaddr_in6 *);
156 if (nam->m_len != sizeof(*sin6))
157 return(EINVAL);
158 /*
159 * We should check the family, but old programs
160 * incorrectly fail to intialize it.
161 */
162 if (sin6->sin6_family != AF_INET6)
163 return(EAFNOSUPPORT);
164
165 /*
166 * If the scope of the destination is link-local, embed the
167 * interface index in the address.
168 */
169 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) {
170 /* XXX boundary check is assumed to be already done. */
171 /* XXX sin6_scope_id is weaker than advanced-api. */
172 struct in6_pktinfo *pi;
173 if (in6p->in6p_outputopts &&
174 (pi = in6p->in6p_outputopts->ip6po_pktinfo) &&
175 pi->ipi6_ifindex) {
176 sin6->sin6_addr.s6_addr16[1]
177 = htons(pi->ipi6_ifindex);
178 } else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)
179 && in6p->in6p_moptions
180 && in6p->in6p_moptions->im6o_multicast_ifp) {
181 sin6->sin6_addr.s6_addr16[1] =
182 htons(in6p->in6p_moptions->im6o_multicast_ifp->if_index);
183 } else if (sin6->sin6_scope_id) {
184 /* boundary check */
185 if (sin6->sin6_scope_id < 0
186 || if_index < sin6->sin6_scope_id) {
187 return ENXIO; /* XXX EINVAL? */
188 }
189 sin6->sin6_addr.s6_addr16[1]
190 = htons(sin6->sin6_scope_id & 0xffff);/*XXX*/
191 /* this must be cleared for ifa_ifwithaddr() */
192 sin6->sin6_scope_id = 0;
193 }
194 }
195
196 lport = sin6->sin6_port;
197 if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
198 /*
199 * Treat SO_REUSEADDR as SO_REUSEPORT for multicast;
200 * allow compepte duplication of binding if
201 * SO_REUSEPORT is set, or if SO_REUSEADDR is set
202 * and a multicast address is bound on both
203 * new and duplicated sockets.
204 */
205 if (so->so_options & SO_REUSEADDR)
206 reuseport = SO_REUSEADDR|SO_REUSEPORT;
207 } else if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
208 struct sockaddr_in sin;
209
210 bzero(&sin, sizeof(sin));
211 sin.sin_len = sizeof(sin);
212 sin.sin_family = AF_INET;
213 bcopy(&sin6->sin6_addr.s6_addr32[3], &sin.sin_addr,
214 sizeof(sin.sin_addr));
215 if (ifa_ifwithaddr((struct sockaddr *)&sin) == 0)
216 return EADDRNOTAVAIL;
217 } else if (!IN6_IS_ADDR_ANY(&sin6->sin6_addr)) {
218 struct ifaddr *ia = NULL;
219
220 sin6->sin6_port = 0; /* yech... */
221 if ((ia = ifa_ifwithaddr((struct sockaddr *)sin6)) == 0)
222 return(EADDRNOTAVAIL);
223
224 /*
225 * XXX: bind to an anycast address might accidentally
226 * cause sending a packet with anycast source address.
227 */
228 if (ia &&
229 ((struct in6_ifaddr *)ia)->ia6_flags &
230 (IN6_IFF_ANYCAST|IN6_IFF_NOTREADY|
231 IN6_IFF_DETACHED|IN6_IFF_DEPRECATED)) {
232 return(EADDRNOTAVAIL);
233 }
234 }
235 if (lport) {
236 /* GROSS */
237 if (ntohs(lport) < IPV6PORT_RESERVED &&
238 (error = suser(p->p_ucred, &p->p_acflag)))
239 return(EACCES);
240
241 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
242 /* should check this but we can't ... */
243 #if 0
244 struct inpcb *t;
245
246 t = in_pcblookup_bind(&tcbtable,
247 (struct in_addr *)&sin6->sin6_addr.s6_addr32[3],
248 lport);
249 if (t && (reuseport & t->inp_socket->so_options) == 0)
250 return EADDRINUSE;
251 #endif
252 } else {
253 struct in6pcb *t;
254
255 t = in6_pcblookup(head, &zeroin6_addr, 0,
256 &sin6->sin6_addr, lport, wild);
257 if (t && (reuseport & t->in6p_socket->so_options) == 0)
258 return(EADDRINUSE);
259 }
260 }
261 in6p->in6p_laddr = sin6->sin6_addr;
262 }
263 if (lport == 0) {
264 u_short last_port;
265 void *t;
266
267 /* XXX IN6P_LOWPORT */
268
269 /* value out of range */
270 if (head->in6p_lport < IPV6PORT_ANONMIN)
271 head->in6p_lport = IPV6PORT_ANONMIN;
272 else if (head->in6p_lport > IPV6PORT_ANONMAX)
273 head->in6p_lport = IPV6PORT_ANONMIN;
274 last_port = head->in6p_lport;
275 goto startover; /*to randomize*/
276 for (;;) {
277 lport = htons(head->in6p_lport);
278 if (IN6_IS_ADDR_V4MAPPED(&in6p->in6p_laddr)) {
279 #if 0
280 t = in_pcblookup_bind(&tcbtable,
281 (struct in_addr *)&in6p->in6p_laddr.s6_addr32[3],
282 lport);
283 #else
284 t = NULL;
285 #endif
286 } else {
287 t = in6_pcblookup(head, &zeroin6_addr, 0,
288 &in6p->in6p_laddr, lport, wild);
289 }
290 if (t == 0)
291 break;
292 startover:
293 if (head->in6p_lport >= IPV6PORT_ANONMAX)
294 head->in6p_lport = IPV6PORT_ANONMIN;
295 else
296 head->in6p_lport++;
297 if (head->in6p_lport == last_port)
298 return (EADDRINUSE);
299 }
300 }
301 in6p->in6p_lport = lport;
302 in6p->in6p_flowinfo = sin6 ? sin6->sin6_flowinfo : 0; /*XXX*/
303 return(0);
304 }
305
306 /*
307 * Connect from a socket to a specified address.
308 * Both address and port must be specified in argument sin6.
309 * If don't have a local address for this socket yet,
310 * then pick one.
311 */
312 int
313 in6_pcbconnect(in6p, nam)
314 struct in6pcb *in6p;
315 struct mbuf *nam;
316 {
317 struct in6_addr *in6a = NULL;
318 struct sockaddr_in6 *sin6 = mtod(nam, struct sockaddr_in6 *);
319 struct in6_pktinfo *pi;
320 struct ifnet *ifp = NULL; /* outgoing interface */
321 int error = 0;
322 struct in6_addr mapped;
323
324 (void)&in6a; /* XXX fool gcc */
325
326 if (nam->m_len != sizeof(*sin6))
327 return(EINVAL);
328 if (sin6->sin6_family != AF_INET6)
329 return(EAFNOSUPPORT);
330 if (sin6->sin6_port == 0)
331 return(EADDRNOTAVAIL);
332
333 /* sanity check for mapped address case */
334 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
335 if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr))
336 in6p->in6p_laddr.s6_addr16[5] = htons(0xffff);
337 if (!IN6_IS_ADDR_V4MAPPED(&in6p->in6p_laddr))
338 return EINVAL;
339 } else {
340 if (IN6_IS_ADDR_V4MAPPED(&in6p->in6p_laddr))
341 return EINVAL;
342 }
343
344 /*
345 * If the scope of the destination is link-local, embed the interface
346 * index in the address.
347 */
348 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr)) {
349 /* XXX boundary check is assumed to be already done. */
350 /* XXX sin6_scope_id is weaker than advanced-api. */
351 if (in6p->in6p_outputopts &&
352 (pi = in6p->in6p_outputopts->ip6po_pktinfo) &&
353 pi->ipi6_ifindex) {
354 sin6->sin6_addr.s6_addr16[1] = htons(pi->ipi6_ifindex);
355 ifp = ifindex2ifnet[pi->ipi6_ifindex];
356 }
357 else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr) &&
358 in6p->in6p_moptions &&
359 in6p->in6p_moptions->im6o_multicast_ifp) {
360 sin6->sin6_addr.s6_addr16[1] =
361 htons(in6p->in6p_moptions->im6o_multicast_ifp->if_index);
362 ifp = ifindex2ifnet[in6p->in6p_moptions->im6o_multicast_ifp->if_index];
363 } else if (sin6->sin6_scope_id) {
364 /* boundary check */
365 if (sin6->sin6_scope_id < 0
366 || if_index < sin6->sin6_scope_id) {
367 return ENXIO; /* XXX EINVAL? */
368 }
369 sin6->sin6_addr.s6_addr16[1]
370 = htons(sin6->sin6_scope_id & 0xffff);/*XXX*/
371 ifp = ifindex2ifnet[sin6->sin6_scope_id];
372 }
373 }
374
375 /* Source address selection. */
376 if (IN6_IS_ADDR_V4MAPPED(&in6p->in6p_laddr)
377 && in6p->in6p_laddr.s6_addr32[3] == 0) {
378 struct sockaddr_in sin, *sinp;
379
380 bzero(&sin, sizeof(sin));
381 sin.sin_len = sizeof(sin);
382 sin.sin_family = AF_INET;
383 bcopy(&sin6->sin6_addr.s6_addr32[3], &sin.sin_addr,
384 sizeof(sin.sin_addr));
385 sinp = in_selectsrc(&sin, (struct route *)&in6p->in6p_route,
386 in6p->in6p_socket->so_options, NULL, &error);
387 if (sinp == 0) {
388 if (error == 0)
389 error = EADDRNOTAVAIL;
390 return(error);
391 }
392 bzero(&mapped, sizeof(mapped));
393 mapped.s6_addr16[5] = htons(0xffff);
394 bcopy(&sinp->sin_addr, &mapped.s6_addr32[3], sizeof(sinp->sin_addr));
395 in6a = &mapped;
396 } else if (IN6_IS_ADDR_ANY(&in6p->in6p_laddr)) {
397 in6a = in6_selectsrc(sin6, in6p->in6p_outputopts,
398 in6p->in6p_moptions, &in6p->in6p_route,
399 &error);
400 if (in6a == 0) {
401 if (error == 0)
402 error = EADDRNOTAVAIL;
403 return(error);
404 }
405 }
406 if (in6p->in6p_route.ro_rt)
407 ifp = in6p->in6p_route.ro_rt->rt_ifp;
408
409 /*
410 * Default hop limit selection. If a hoplimit was specified via ioctl,
411 * use it. Else if the outgoing interface is detected and the current
412 * hop limit of the interface was specified by router advertisement,
413 * use the value.
414 * Otherwise, use the system default hoplimit.
415 */
416 if (in6p->in6p_hops >= 0)
417 in6p->in6p_ip6.ip6_hlim = (u_int8_t)in6p->in6p_hops;
418 else if (ifp)
419 in6p->in6p_ip6.ip6_hlim = nd_ifinfo[ifp->if_index].chlim;
420 else
421 in6p->in6p_ip6.ip6_hlim = ip6_defhlim;
422
423 if (in6_pcblookup(in6p->in6p_head,
424 &sin6->sin6_addr,
425 sin6->sin6_port,
426 IN6_IS_ADDR_ANY(&in6p->in6p_laddr) ?
427 in6a : &in6p->in6p_laddr,
428 in6p->in6p_lport,
429 0))
430 return(EADDRINUSE);
431 if (IN6_IS_ADDR_ANY(&in6p->in6p_laddr)
432 || (IN6_IS_ADDR_V4MAPPED(&in6p->in6p_laddr)
433 && in6p->in6p_laddr.s6_addr32[3] == 0)) {
434 if (in6p->in6p_lport == 0)
435 (void)in6_pcbbind(in6p, (struct mbuf *)0);
436 in6p->in6p_laddr = *in6a;
437 }
438 in6p->in6p_faddr = sin6->sin6_addr;
439 in6p->in6p_fport = sin6->sin6_port;
440 /*
441 * xxx kazu flowlabel is necessary for connect?
442 * but if this line is missing, the garbage value remains.
443 */
444 in6p->in6p_flowinfo = sin6->sin6_flowinfo;
445 return(0);
446 }
447
448 /*
449 * Return an IPv6 address, which is the most appropriate for given
450 * destination and user specified options.
451 * If necessary, this function lookups the routing table and return
452 * an entry to the caller for later use.
453 */
454 struct in6_addr *
455 in6_selectsrc(dstsock, opts, mopts, ro, errorp)
456 struct sockaddr_in6 *dstsock;
457 struct ip6_pktopts *opts;
458 struct ip6_moptions *mopts;
459 struct route_in6 *ro;
460 int *errorp;
461 {
462 struct in6_addr *dst;
463 struct in6_ifaddr *ia6 = 0;
464 struct in6_pktinfo *pi;
465
466 dst = &dstsock->sin6_addr;
467 *errorp = 0;
468
469 /*
470 * If the source address is explicitly specified by the caller,
471 * use it.
472 * If the caller doesn't specify the source address but
473 * the outgoing interface, use an address associated with
474 * the interface.
475 */
476 if (opts && (pi = opts->ip6po_pktinfo)) {
477 if (!IN6_IS_ADDR_ANY(&pi->ipi6_addr))
478 return(&pi->ipi6_addr);
479 else if (pi->ipi6_ifindex) {
480 /* XXX boundary check is assumed to be already done. */
481 ia6 = in6_ifawithscope(ifindex2ifnet[pi->ipi6_ifindex],
482 dst);
483 if (ia6 == 0) {
484 *errorp = EADDRNOTAVAIL;
485 return(0);
486 }
487 return(&satosin6(&ia6->ia_addr)->sin6_addr);
488 }
489 }
490
491 /*
492 * If the destination address is a multicast address and
493 * the outgoing interface for the address is specified
494 * by the caller, use an address associated with the interface.
495 * There is a sanity check here; if the destination has node-local
496 * scope, the outgoing interfacde should be a loopback address.
497 * Even if the outgoing interface is not specified, we also
498 * choose a loopback interface as the outgoing interface.
499 */
500 if (IN6_IS_ADDR_MULTICAST(dst)) {
501 struct ifnet *ifp = mopts ? mopts->im6o_multicast_ifp : NULL;
502 #ifdef __bsdi__
503 extern struct ifnet loif;
504 #endif
505
506 if (ifp == NULL && IN6_IS_ADDR_MC_NODELOCAL(dst)) {
507 #ifdef __bsdi__
508 ifp = &loif;
509 #else
510 ifp = &loif[0];
511 #endif
512 }
513
514 if (ifp) {
515 ia6 = in6_ifawithscope(ifp, dst);
516 if (ia6 == 0) {
517 *errorp = EADDRNOTAVAIL;
518 return(0);
519 }
520 return(&satosin6(&ia6->ia_addr)->sin6_addr);
521 }
522 }
523
524 /*
525 * XXX How should we use sin6_scope_id???
526 */
527
528 /*
529 * If the next hop address for the packet is specified
530 * by caller, use an address associated with the route
531 * to the next hop.
532 */
533 {
534 struct sockaddr_in6 *sin6_next;
535 struct rtentry *rt;
536
537 if (opts && opts->ip6po_nexthop) {
538 sin6_next = satosin6(opts->ip6po_nexthop);
539 rt = nd6_lookup(&sin6_next->sin6_addr, 1, NULL);
540 if (rt) {
541 ia6 = in6_ifawithscope(rt->rt_ifp, dst);
542 if (ia6 == 0)
543 ia6 = ifatoia6(rt->rt_ifa);
544 }
545 if (ia6 == 0) {
546 *errorp = EADDRNOTAVAIL;
547 return(0);
548 }
549 return(&satosin6(&ia6->ia_addr)->sin6_addr);
550 }
551 }
552
553 /*
554 * If route is known or can be allocated now,
555 * our src addr is taken from the i/f, else punt.
556 */
557 if (ro) {
558 if (ro->ro_rt &&
559 !IN6_ARE_ADDR_EQUAL(&satosin6(&ro->ro_dst)->sin6_addr, dst)) {
560 RTFREE(ro->ro_rt);
561 ro->ro_rt = (struct rtentry *)0;
562 }
563 if (ro->ro_rt == (struct rtentry *)0 ||
564 ro->ro_rt->rt_ifp == (struct ifnet *)0) {
565 /* No route yet, so try to acquire one */
566 bzero(&ro->ro_dst, sizeof(struct sockaddr_in6));
567 ro->ro_dst.sin6_family = AF_INET6;
568 ro->ro_dst.sin6_len = sizeof(struct sockaddr_in6);
569 ro->ro_dst.sin6_addr = *dst;
570 if (IN6_IS_ADDR_MULTICAST(dst)) {
571 #ifdef __FreeBSD__
572 ro->ro_rt = rtalloc1(&((struct route *)ro)
573 ->ro_dst, 0, 0UL);
574 #endif /*__FreeBSD__*/
575 #if defined(__bsdi__) || defined(__NetBSD__)
576 ro->ro_rt = rtalloc1(&((struct route *)ro)
577 ->ro_dst, 0);
578 #endif /*__bsdi__*/
579 } else {
580 #if 0 /* XXX Is this correct? */
581 rtcalloc((struct route *)ro);
582 #else
583 rtalloc((struct route *)ro);
584 #endif
585 }
586 }
587
588 /*
589 * in_pcbconnect() checks out IFF_LOOPBACK to skip using
590 * the address. But we don't know why it does so.
591 * It is necessary to ensure the scope even for lo0
592 * so doesn't check out IFF_LOOPBACK.
593 */
594
595 if (ro->ro_rt) {
596 ia6 = in6_ifawithscope(ro->ro_rt->rt_ifa->ifa_ifp, dst);
597 if (ia6 == 0) /* xxx scope error ?*/
598 ia6 = ifatoia6(ro->ro_rt->rt_ifa);
599 }
600 #if 0
601 /*
602 * xxx The followings are necessary? (kazu)
603 * I don't think so.
604 * It's for SO_DONTROUTE option in IPv4.(jinmei)
605 */
606 if (ia6 == 0) {
607 struct sockaddr_in6 sin6 = {sizeof(sin6), AF_INET6, 0};
608
609 sin6->sin6_addr = *dst;
610
611 ia6 = ifatoia6(ifa_ifwithdstaddr(sin6tosa(&sin6)));
612 if (ia6 == 0)
613 ia6 = ifatoia6(ifa_ifwithnet(sin6tosa(&sin6)));
614 if (ia6 == 0)
615 return(0);
616 return(&satosin6(&ia6->ia_addr)->sin6_addr);
617 }
618 #endif /* 0 */
619 if (ia6 == 0) {
620 *errorp = EHOSTUNREACH; /* no route */
621 return(0);
622 }
623 return(&satosin6(&ia6->ia_addr)->sin6_addr);
624 }
625
626 *errorp = EADDRNOTAVAIL;
627 return(0);
628 }
629
630 void
631 in6_pcbdisconnect(in6p)
632 struct in6pcb *in6p;
633 {
634 bzero((caddr_t)&in6p->in6p_faddr, sizeof(in6p->in6p_faddr));
635 in6p->in6p_fport = 0;
636 if (in6p->in6p_socket->so_state & SS_NOFDREF)
637 in6_pcbdetach(in6p);
638 }
639
640 void
641 in6_pcbdetach(in6p)
642 struct in6pcb *in6p;
643 {
644 struct socket *so = in6p->in6p_socket;
645
646 #ifdef IPSEC
647 if (sotoin6pcb(so) != 0)
648 key_freeso(so);
649 ipsec6_delete_pcbpolicy(in6p);
650 #endif /* IPSEC */
651 sotoin6pcb(so) = 0;
652 sofree(so);
653 if (in6p->in6p_options)
654 m_freem(in6p->in6p_options);
655 if (in6p->in6p_outputopts) {
656 if (in6p->in6p_outputopts->ip6po_rthdr &&
657 in6p->in6p_outputopts->ip6po_route.ro_rt)
658 RTFREE(in6p->in6p_outputopts->ip6po_route.ro_rt);
659 if (in6p->in6p_outputopts->ip6po_m)
660 (void)m_free(in6p->in6p_outputopts->ip6po_m);
661 free(in6p->in6p_outputopts, M_IP6OPT);
662 }
663 if (in6p->in6p_route.ro_rt)
664 rtfree(in6p->in6p_route.ro_rt);
665 ip6_freemoptions(in6p->in6p_moptions);
666 #if 0
667 remque(in6p);
668 #else
669 in6p->in6p_next->in6p_prev = in6p->in6p_prev;
670 in6p->in6p_prev->in6p_next = in6p->in6p_next;
671 in6p->in6p_prev = NULL;
672 #endif
673 FREE(in6p, M_PCB);
674 }
675
676 void
677 in6_setsockaddr(in6p, nam)
678 struct in6pcb *in6p;
679 struct mbuf *nam;
680 {
681 struct sockaddr_in6 *sin6;
682
683 nam->m_len = sizeof(*sin6);
684 sin6 = mtod(nam, struct sockaddr_in6 *);
685 bzero((caddr_t)sin6, sizeof(*sin6));
686 sin6->sin6_family = AF_INET6;
687 sin6->sin6_len = sizeof(struct sockaddr_in6);
688 sin6->sin6_port = in6p->in6p_lport;
689 sin6->sin6_addr = in6p->in6p_laddr;
690 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
691 sin6->sin6_scope_id = ntohs(sin6->sin6_addr.s6_addr16[1]);
692 else
693 sin6->sin6_scope_id = 0; /*XXX*/
694 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
695 sin6->sin6_addr.s6_addr16[1] = 0;
696 }
697
698 void
699 in6_setpeeraddr(in6p, nam)
700 struct in6pcb *in6p;
701 struct mbuf *nam;
702 {
703 struct sockaddr_in6 *sin6;
704
705 nam->m_len = sizeof(*sin6);
706 sin6 = mtod(nam, struct sockaddr_in6 *);
707 bzero((caddr_t)sin6, sizeof(*sin6));
708 sin6->sin6_family = AF_INET6;
709 sin6->sin6_len = sizeof(struct sockaddr_in6);
710 sin6->sin6_port = in6p->in6p_fport;
711 sin6->sin6_addr = in6p->in6p_faddr;
712 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
713 sin6->sin6_scope_id = ntohs(sin6->sin6_addr.s6_addr16[1]);
714 else
715 sin6->sin6_scope_id = 0; /*XXX*/
716 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
717 sin6->sin6_addr.s6_addr16[1] = 0;
718 }
719
720 /*
721 * Pass some notification to all connections of a protocol
722 * associated with address dst. The local address and/or port numbers
723 * may be specified to limit the search. The "usual action" will be
724 * taken, depending on the ctlinput cmd. The caller must filter any
725 * cmds that are uninteresting (e.g., no error in the map).
726 * Call the protocol specific routine (if any) to report
727 * any errors for each matching socket.
728 *
729 * Must be called at splsoftnet.
730 */
731 int
732 in6_pcbnotify(head, dst, fport_arg, laddr6, lport_arg, cmd, notify)
733 struct in6pcb *head;
734 struct sockaddr *dst;
735 u_int fport_arg, lport_arg;
736 struct in6_addr *laddr6;
737 int cmd;
738 void (*notify) __P((struct in6pcb *, int));
739 {
740 struct in6pcb *in6p, *oin6p;
741 struct in6_addr faddr6;
742 u_short fport = fport_arg, lport = lport_arg;
743 int errno;
744 int nmatch = 0;
745
746 if ((unsigned)cmd > PRC_NCMDS || dst->sa_family != AF_INET6)
747 return 0;
748 faddr6 = ((struct sockaddr_in6 *)dst)->sin6_addr;
749 if (IN6_IS_ADDR_ANY(&faddr6))
750 return 0;
751
752 /*
753 * Redirects go to all references to the destination,
754 * and use in_rtchange to invalidate the route cache.
755 * Dead host indications: notify all references to the destination.
756 * Otherwise, if we have knowledge of the local port and address,
757 * deliver only to that socket.
758 */
759 if (PRC_IS_REDIRECT(cmd) || cmd == PRC_HOSTDEAD) {
760 fport = 0;
761 lport = 0;
762 bzero((caddr_t)laddr6, sizeof(*laddr6));
763 if (cmd != PRC_HOSTDEAD)
764 notify = in6_rtchange;
765 }
766 if (notify == NULL)
767 return 0;
768 errno = inet6ctlerrmap[cmd];
769 for (in6p = head->in6p_next; in6p != head;) {
770 if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr,&faddr6) ||
771 in6p->in6p_socket == 0 ||
772 (lport && in6p->in6p_lport != lport) ||
773 (!IN6_IS_ADDR_ANY(laddr6) &&
774 !IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, laddr6)) ||
775 (fport && in6p->in6p_fport != fport)) {
776 in6p = in6p->in6p_next;
777 continue;
778 }
779 oin6p = in6p;
780 in6p = in6p->in6p_next;
781 (*notify)(oin6p, errno);
782 nmatch++;
783 }
784 return nmatch;
785 }
786
787 /*
788 * Check for alternatives when higher level complains
789 * about service problems. For now, invalidate cached
790 * routing information. If the route was created dynamically
791 * (by a redirect), time to try a default gateway again.
792 */
793 void
794 in6_losing(in6p)
795 struct in6pcb *in6p;
796 {
797 struct rtentry *rt;
798 struct rt_addrinfo info;
799
800 if ((rt = in6p->in6p_route.ro_rt) != NULL) {
801 in6p->in6p_route.ro_rt = 0;
802 bzero((caddr_t)&info, sizeof(info));
803 info.rti_info[RTAX_DST] =
804 (struct sockaddr *)&in6p->in6p_route.ro_dst;
805 info.rti_info[RTAX_GATEWAY] = rt->rt_gateway;
806 info.rti_info[RTAX_NETMASK] = rt_mask(rt);
807 rt_missmsg(RTM_LOSING, &info, rt->rt_flags, 0);
808 if (rt->rt_flags & RTF_DYNAMIC)
809 (void)rtrequest(RTM_DELETE, rt_key(rt),
810 rt->rt_gateway, rt_mask(rt), rt->rt_flags,
811 (struct rtentry **)0);
812 else
813 /*
814 * A new route can be allocated
815 * the next time output is attempted.
816 */
817 rtfree(rt);
818 }
819 }
820
821 /*
822 * After a routing change, flush old routing
823 * and allocate a (hopefully) better one.
824 */
825 void
826 in6_rtchange(in6p, errno)
827 struct in6pcb *in6p;
828 int errno;
829 {
830 if (in6p->in6p_route.ro_rt) {
831 rtfree(in6p->in6p_route.ro_rt);
832 in6p->in6p_route.ro_rt = 0;
833 /*
834 * A new route can be allocated the next time
835 * output is attempted.
836 */
837 }
838 }
839
840 struct in6pcb *
841 in6_pcblookup(head, faddr6, fport_arg, laddr6, lport_arg, flags)
842 struct in6pcb *head;
843 struct in6_addr *faddr6, *laddr6;
844 u_int fport_arg, lport_arg;
845 int flags;
846 {
847 struct in6pcb *in6p, *match = 0;
848 int matchwild = 3, wildcard;
849 u_short fport = fport_arg, lport = lport_arg;
850
851 for (in6p = head->in6p_next; in6p != head; in6p = in6p->in6p_next) {
852 if (in6p->in6p_lport != lport)
853 continue;
854 wildcard = 0;
855 if (!IN6_IS_ADDR_ANY(&in6p->in6p_laddr)) {
856 if (IN6_IS_ADDR_ANY(laddr6))
857 wildcard++;
858 else if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, laddr6))
859 continue;
860 } else {
861 if (!IN6_IS_ADDR_ANY(laddr6))
862 wildcard++;
863 }
864 if (!IN6_IS_ADDR_ANY(&in6p->in6p_faddr)) {
865 if (IN6_IS_ADDR_ANY(faddr6))
866 wildcard++;
867 else if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, faddr6)
868 || in6p->in6p_fport != fport)
869 continue;
870 } else {
871 if (!IN6_IS_ADDR_ANY(faddr6))
872 wildcard++;
873 }
874 if (wildcard && (flags & IN6PLOOKUP_WILDCARD) == 0)
875 continue;
876 if (wildcard < matchwild) {
877 match = in6p;
878 matchwild = wildcard;
879 if (matchwild == 0)
880 break;
881 }
882 }
883 return(match);
884 }
885
886 #ifndef TCP6
887 struct rtentry *
888 in6_pcbrtentry(in6p)
889 struct in6pcb *in6p;
890 {
891 struct route_in6 *ro;
892
893 ro = &in6p->in6p_route;
894
895 if (ro->ro_rt == NULL) {
896 /*
897 * No route yet, so try to acquire one.
898 */
899 if (!IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr)) {
900 bzero(&ro->ro_dst, sizeof(ro->ro_dst));
901 ro->ro_dst.sin6_family = AF_INET6;
902 ro->ro_dst.sin6_len = sizeof(struct sockaddr_in6);
903 satosin6(&ro->ro_dst)->sin6_addr = in6p->in6p_faddr;
904 rtalloc((struct route *)ro);
905 }
906 }
907 return (ro->ro_rt);
908 }
909
910 struct in6pcb *
911 in6_pcblookup_connect(head, faddr6, fport_arg, laddr6, lport_arg, faith)
912 struct in6pcb *head;
913 struct in6_addr *faddr6, *laddr6;
914 u_int fport_arg, lport_arg;
915 int faith;
916 {
917 struct in6pcb *in6p;
918 u_short fport = fport_arg, lport = lport_arg;
919
920 for (in6p = head->in6p_next; in6p != head; in6p = in6p->in6p_next) {
921 #if defined(NFAITH) && NFAITH > 0
922 if (faith && (in6p->in6p_flags & IN6P_FAITH) == 0)
923 continue;
924 #endif
925 /* find exact match on both source and dest */
926 if (in6p->in6p_fport != fport)
927 continue;
928 if (in6p->in6p_lport != lport)
929 continue;
930 if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_faddr))
931 continue;
932 if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_faddr, faddr6))
933 continue;
934 if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr))
935 continue;
936 if (!IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, laddr6))
937 continue;
938 return in6p;
939 }
940 return NULL;
941 }
942
943 struct in6pcb *
944 in6_pcblookup_bind(head, laddr6, lport_arg, faith)
945 struct in6pcb *head;
946 struct in6_addr *laddr6;
947 u_int lport_arg;
948 int faith;
949 {
950 struct in6pcb *in6p, *match;
951 u_short lport = lport_arg;
952
953 match = NULL;
954 for (in6p = head->in6p_next; in6p != head; in6p = in6p->in6p_next) {
955 /*
956 * find destination match. exact match is preferred
957 * against wildcard match.
958 */
959 #if defined(NFAITH) && NFAITH > 0
960 if (faith && (in6p->in6p_flags & IN6P_FAITH) == 0)
961 continue;
962 #endif
963 if (in6p->in6p_fport != 0)
964 continue;
965 if (in6p->in6p_lport != lport)
966 continue;
967 if (IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr))
968 match = in6p;
969 else if (IN6_ARE_ADDR_EQUAL(&in6p->in6p_laddr, laddr6))
970 return in6p;
971 }
972 return match;
973 }
974 #endif
975