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