ip6_output.c revision 1.14 1 /* $NetBSD: ip6_output.c,v 1.14 2000/02/06 12:49:46 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, 1988, 1990, 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 * @(#)ip_output.c 8.3 (Berkeley) 1/21/94
65 */
66
67 #include "opt_inet.h"
68 #include "opt_ipsec.h"
69
70 #include <sys/param.h>
71 #include <sys/malloc.h>
72 #include <sys/mbuf.h>
73 #include <sys/errno.h>
74 #include <sys/protosw.h>
75 #include <sys/socket.h>
76 #include <sys/socketvar.h>
77 #include <sys/systm.h>
78 #include <sys/proc.h>
79
80 #include <net/if.h>
81 #include <net/route.h>
82
83 #include <netinet/in.h>
84 #include <netinet/in_var.h>
85 #include <netinet/ip6.h>
86 #include <netinet/icmp6.h>
87 #include <netinet6/ip6_var.h>
88 #include <netinet6/in6_pcb.h>
89 #include <netinet6/nd6.h>
90
91 #ifdef IPSEC
92 #include <netinet6/ipsec.h>
93 #include <netkey/key.h>
94 #include <netkey/key_debug.h>
95 #endif /* IPSEC */
96
97 #include "loop.h"
98
99 #include <net/net_osdep.h>
100
101 #ifdef IPV6FIREWALL
102 #include <netinet6/ip6_fw.h>
103 #endif
104
105 struct ip6_exthdrs {
106 struct mbuf *ip6e_ip6;
107 struct mbuf *ip6e_hbh;
108 struct mbuf *ip6e_dest1;
109 struct mbuf *ip6e_rthdr;
110 struct mbuf *ip6e_dest2;
111 };
112
113 static int ip6_pcbopts __P((struct ip6_pktopts **, struct mbuf *,
114 struct socket *));
115 static int ip6_setmoptions __P((int, struct ip6_moptions **, struct mbuf *));
116 static int ip6_getmoptions __P((int, struct ip6_moptions *, struct mbuf **));
117 static int ip6_copyexthdr __P((struct mbuf **, caddr_t, int));
118 static int ip6_insertfraghdr __P((struct mbuf *, struct mbuf *, int,
119 struct ip6_frag **));
120 static int ip6_insert_jumboopt __P((struct ip6_exthdrs *, u_int32_t));
121 static int ip6_splithdr __P((struct mbuf *, struct ip6_exthdrs *));
122
123 extern struct ifnet **ifindex2ifnet;
124 extern struct ifnet loif[NLOOP];
125
126 /*
127 * IP6 output. The packet in mbuf chain m contains a skeletal IP6
128 * header (with pri, len, nxt, hlim, src, dst).
129 * This function may modify ver and hlim only.
130 * The mbuf chain containing the packet will be freed.
131 * The mbuf opt, if present, will not be freed.
132 */
133 int
134 ip6_output(m0, opt, ro, flags, im6o, ifpp)
135 struct mbuf *m0;
136 struct ip6_pktopts *opt;
137 struct route_in6 *ro;
138 int flags;
139 struct ip6_moptions *im6o;
140 struct ifnet **ifpp; /* XXX: just for statistics */
141 {
142 struct ip6_hdr *ip6, *mhip6;
143 struct ifnet *ifp;
144 struct mbuf *m = m0;
145 int hlen, tlen, len, off;
146 struct route_in6 ip6route;
147 struct sockaddr_in6 *dst;
148 int error = 0;
149 struct in6_ifaddr *ia;
150 u_long mtu;
151 u_int32_t optlen = 0, plen = 0, unfragpartlen = 0;
152 struct ip6_exthdrs exthdrs;
153 struct in6_addr finaldst;
154 struct route_in6 *ro_pmtu = NULL;
155 int hdrsplit = 0;
156 int needipsec = 0;
157 #ifdef IPSEC
158 int needipsectun = 0;
159 struct socket *so;
160 struct secpolicy *sp = NULL;
161
162 /* for AH processing. stupid to have "socket" variable in IP layer... */
163 so = (struct socket *)m->m_pkthdr.rcvif;
164 m->m_pkthdr.rcvif = NULL;
165 ip6 = mtod(m, struct ip6_hdr *);
166 #endif /* IPSEC */
167
168 #define MAKE_EXTHDR(hp,mp) \
169 { \
170 if (hp) { \
171 struct ip6_ext *eh = (struct ip6_ext *)(hp); \
172 error = ip6_copyexthdr((mp), (caddr_t)(hp), \
173 ((eh)->ip6e_len + 1) << 3); \
174 if (error) \
175 goto freehdrs; \
176 } \
177 }
178
179 bzero(&exthdrs, sizeof(exthdrs));
180 if (opt) {
181 /* Hop-by-Hop options header */
182 MAKE_EXTHDR(opt->ip6po_hbh, &exthdrs.ip6e_hbh);
183 /* Destination options header(1st part) */
184 MAKE_EXTHDR(opt->ip6po_dest1, &exthdrs.ip6e_dest1);
185 /* Routing header */
186 MAKE_EXTHDR(opt->ip6po_rthdr, &exthdrs.ip6e_rthdr);
187 /* Destination options header(2nd part) */
188 MAKE_EXTHDR(opt->ip6po_dest2, &exthdrs.ip6e_dest2);
189 }
190
191 #ifdef IPSEC
192 /* get a security policy for this packet */
193 if (so == NULL)
194 sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, 0, &error);
195 else
196 sp = ipsec6_getpolicybysock(m, IPSEC_DIR_OUTBOUND, so, &error);
197
198 if (sp == NULL) {
199 ipsec6stat.out_inval++;
200 goto bad;
201 }
202
203 error = 0;
204
205 /* check policy */
206 switch (sp->policy) {
207 case IPSEC_POLICY_DISCARD:
208 /*
209 * This packet is just discarded.
210 */
211 ipsec6stat.out_polvio++;
212 goto bad;
213
214 case IPSEC_POLICY_BYPASS:
215 case IPSEC_POLICY_NONE:
216 /* no need to do IPsec. */
217 needipsec = 0;
218 break;
219
220 case IPSEC_POLICY_IPSEC:
221 if (sp->req == NULL) {
222 /* XXX should be panic ? */
223 printf("ip6_output: No IPsec request specified.\n");
224 error = EINVAL;
225 goto bad;
226 }
227 needipsec = 1;
228 break;
229
230 case IPSEC_POLICY_ENTRUST:
231 default:
232 printf("ip6_output: Invalid policy found. %d\n", sp->policy);
233 }
234 #endif /* IPSEC */
235
236 /*
237 * Calculate the total length of the extension header chain.
238 * Keep the length of the unfragmentable part for fragmentation.
239 */
240 optlen = 0;
241 if (exthdrs.ip6e_hbh) optlen += exthdrs.ip6e_hbh->m_len;
242 if (exthdrs.ip6e_dest1) optlen += exthdrs.ip6e_dest1->m_len;
243 if (exthdrs.ip6e_rthdr) optlen += exthdrs.ip6e_rthdr->m_len;
244 unfragpartlen = optlen + sizeof(struct ip6_hdr);
245 /* NOTE: we don't add AH/ESP length here. do that later. */
246 if (exthdrs.ip6e_dest2) optlen += exthdrs.ip6e_dest2->m_len;
247
248 /*
249 * If we need IPsec, or there is at least one extension header,
250 * separate IP6 header from the payload.
251 */
252 if ((needipsec || optlen) && !hdrsplit) {
253 if ((error = ip6_splithdr(m, &exthdrs)) != 0) {
254 m = NULL;
255 goto freehdrs;
256 }
257 m = exthdrs.ip6e_ip6;
258 hdrsplit++;
259 }
260
261 /* adjust pointer */
262 ip6 = mtod(m, struct ip6_hdr *);
263
264 /* adjust mbuf packet header length */
265 m->m_pkthdr.len += optlen;
266 plen = m->m_pkthdr.len - sizeof(*ip6);
267
268 /* If this is a jumbo payload, insert a jumbo payload option. */
269 if (plen > IPV6_MAXPACKET) {
270 if (!hdrsplit) {
271 if ((error = ip6_splithdr(m, &exthdrs)) != 0) {
272 m = NULL;
273 goto freehdrs;
274 }
275 m = exthdrs.ip6e_ip6;
276 hdrsplit++;
277 }
278 /* adjust pointer */
279 ip6 = mtod(m, struct ip6_hdr *);
280 if ((error = ip6_insert_jumboopt(&exthdrs, plen)) != 0)
281 goto freehdrs;
282 ip6->ip6_plen = 0;
283 } else
284 ip6->ip6_plen = htons(plen);
285
286 /*
287 * Concatenate headers and fill in next header fields.
288 * Here we have, on "m"
289 * IPv6 payload
290 * and we insert headers accordingly. Finally, we should be getting:
291 * IPv6 hbh dest1 rthdr ah* [esp* dest2 payload]
292 *
293 * during the header composing process, "m" points to IPv6 header.
294 * "mprev" points to an extension header prior to esp.
295 */
296 {
297 u_char *nexthdrp = &ip6->ip6_nxt;
298 struct mbuf *mprev = m;
299
300 /*
301 * we treat dest2 specially. this makes IPsec processing
302 * much easier.
303 *
304 * result: IPv6 dest2 payload
305 * m and mprev will point to IPv6 header.
306 */
307 if (exthdrs.ip6e_dest2) {
308 if (!hdrsplit)
309 panic("assumption failed: hdr not split");
310 exthdrs.ip6e_dest2->m_next = m->m_next;
311 m->m_next = exthdrs.ip6e_dest2;
312 *mtod(exthdrs.ip6e_dest2, u_char *) = ip6->ip6_nxt;
313 ip6->ip6_nxt = IPPROTO_DSTOPTS;
314 }
315
316 #define MAKE_CHAIN(m,mp,p,i)\
317 {\
318 if (m) {\
319 if (!hdrsplit) \
320 panic("assumption failed: hdr not split"); \
321 *mtod((m), u_char *) = *(p);\
322 *(p) = (i);\
323 p = mtod((m), u_char *);\
324 (m)->m_next = (mp)->m_next;\
325 (mp)->m_next = (m);\
326 (mp) = (m);\
327 }\
328 }
329 /*
330 * result: IPv6 hbh dest1 rthdr dest2 payload
331 * m will point to IPv6 header. mprev will point to the
332 * extension header prior to dest2 (rthdr in the above case).
333 */
334 MAKE_CHAIN(exthdrs.ip6e_hbh, mprev,
335 nexthdrp, IPPROTO_HOPOPTS);
336 MAKE_CHAIN(exthdrs.ip6e_dest1, mprev,
337 nexthdrp, IPPROTO_DSTOPTS);
338 MAKE_CHAIN(exthdrs.ip6e_rthdr, mprev,
339 nexthdrp, IPPROTO_ROUTING);
340
341 #ifdef IPSEC
342 if (!needipsec)
343 goto skip_ipsec2;
344
345 /*
346 * pointers after IPsec headers are not valid any more.
347 * other pointers need a great care too.
348 * (IPsec routines should not mangle mbufs prior to AH/ESP)
349 */
350 exthdrs.ip6e_dest2 = NULL;
351
352 {
353 struct ip6_rthdr *rh = NULL;
354 int segleft_org = 0;
355 struct ipsec_output_state state;
356
357 if (exthdrs.ip6e_rthdr) {
358 rh = mtod(exthdrs.ip6e_rthdr, struct ip6_rthdr *);
359 segleft_org = rh->ip6r_segleft;
360 rh->ip6r_segleft = 0;
361 }
362
363 bzero(&state, sizeof(state));
364 state.m = m;
365 error = ipsec6_output_trans(&state, nexthdrp, mprev, sp, flags,
366 &needipsectun);
367 m = state.m;
368 if (error) {
369 /* mbuf is already reclaimed in ipsec6_output_trans. */
370 m = NULL;
371 switch (error) {
372 case EHOSTUNREACH:
373 case ENETUNREACH:
374 case EMSGSIZE:
375 case ENOBUFS:
376 case ENOMEM:
377 break;
378 default:
379 printf("ip6_output (ipsec): error code %d\n", error);
380 /*fall through*/
381 case ENOENT:
382 /* don't show these error codes to the user */
383 error = 0;
384 break;
385 }
386 goto bad;
387 }
388 if (exthdrs.ip6e_rthdr) {
389 /* ah6_output doesn't modify mbuf chain */
390 rh->ip6r_segleft = segleft_org;
391 }
392 }
393 skip_ipsec2:;
394 #endif
395 }
396
397 /*
398 * If there is a routing header, replace destination address field
399 * with the first hop of the routing header.
400 */
401 if (exthdrs.ip6e_rthdr) {
402 struct ip6_rthdr *rh =
403 (struct ip6_rthdr *)(mtod(exthdrs.ip6e_rthdr,
404 struct ip6_rthdr *));
405 struct ip6_rthdr0 *rh0;
406
407 finaldst = ip6->ip6_dst;
408 switch(rh->ip6r_type) {
409 case IPV6_RTHDR_TYPE_0:
410 rh0 = (struct ip6_rthdr0 *)rh;
411 ip6->ip6_dst = rh0->ip6r0_addr[0];
412 bcopy((caddr_t)&rh0->ip6r0_addr[1],
413 (caddr_t)&rh0->ip6r0_addr[0],
414 sizeof(struct in6_addr)*(rh0->ip6r0_segleft - 1)
415 );
416 rh0->ip6r0_addr[rh0->ip6r0_segleft - 1] = finaldst;
417 break;
418 default: /* is it possible? */
419 error = EINVAL;
420 goto bad;
421 }
422 }
423
424 /* Source address validation */
425 if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src) &&
426 (flags & IPV6_DADOUTPUT) == 0) {
427 error = EOPNOTSUPP;
428 ip6stat.ip6s_badscope++;
429 goto bad;
430 }
431 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src)) {
432 error = EOPNOTSUPP;
433 ip6stat.ip6s_badscope++;
434 goto bad;
435 }
436
437 ip6stat.ip6s_localout++;
438
439 /*
440 * Route packet.
441 */
442 if (ro == 0) {
443 ro = &ip6route;
444 bzero((caddr_t)ro, sizeof(*ro));
445 }
446 ro_pmtu = ro;
447 if (opt && opt->ip6po_rthdr)
448 ro = &opt->ip6po_route;
449 dst = (struct sockaddr_in6 *)&ro->ro_dst;
450 /*
451 * If there is a cached route,
452 * check that it is to the same destination
453 * and is still up. If not, free it and try again.
454 */
455 if (ro->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
456 !IN6_ARE_ADDR_EQUAL(&dst->sin6_addr, &ip6->ip6_dst))) {
457 RTFREE(ro->ro_rt);
458 ro->ro_rt = (struct rtentry *)0;
459 }
460 if (ro->ro_rt == 0) {
461 bzero(dst, sizeof(*dst));
462 dst->sin6_family = AF_INET6;
463 dst->sin6_len = sizeof(struct sockaddr_in6);
464 dst->sin6_addr = ip6->ip6_dst;
465 }
466 #ifdef IPSEC
467 if (needipsec && needipsectun) {
468 struct ipsec_output_state state;
469
470 /*
471 * All the extension headers will become inaccessible
472 * (since they can be encrypted).
473 * Don't panic, we need no more updates to extension headers
474 * on inner IPv6 packet (since they are now encapsulated).
475 *
476 * IPv6 [ESP|AH] IPv6 [extension headers] payload
477 */
478 bzero(&exthdrs, sizeof(exthdrs));
479 exthdrs.ip6e_ip6 = m;
480
481 bzero(&state, sizeof(state));
482 state.m = m;
483 state.ro = (struct route *)ro;
484 state.dst = (struct sockaddr *)dst;
485
486 error = ipsec6_output_tunnel(&state, sp, flags);
487
488 m = state.m;
489 ro = (struct route_in6 *)state.ro;
490 dst = (struct sockaddr_in6 *)state.dst;
491 if (error) {
492 /* mbuf is already reclaimed in ipsec6_output_tunnel. */
493 m0 = m = NULL;
494 m = NULL;
495 switch (error) {
496 case EHOSTUNREACH:
497 case ENETUNREACH:
498 case EMSGSIZE:
499 case ENOBUFS:
500 case ENOMEM:
501 break;
502 default:
503 printf("ip6_output (ipsec): error code %d\n", error);
504 /*fall through*/
505 case ENOENT:
506 /* don't show these error codes to the user */
507 error = 0;
508 break;
509 }
510 goto bad;
511 }
512
513 exthdrs.ip6e_ip6 = m;
514 }
515 #endif /*IPESC*/
516
517 if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
518 /* Unicast */
519
520 #define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa))
521 #define sin6tosa(sin6) ((struct sockaddr *)(sin6))
522 /* xxx
523 * interface selection comes here
524 * if an interface is specified from an upper layer,
525 * ifp must point it.
526 */
527 if (ro->ro_rt == 0) {
528 /*
529 * NetBSD/OpenBSD always clones routes, if parent is
530 * PRF_CLONING.
531 */
532 rtalloc((struct route *)ro);
533 }
534 if (ro->ro_rt == 0) {
535 ip6stat.ip6s_noroute++;
536 error = EHOSTUNREACH;
537 /* XXX in6_ifstat_inc(ifp, ifs6_out_discard); */
538 goto bad;
539 }
540 ia = ifatoia6(ro->ro_rt->rt_ifa);
541 ifp = ro->ro_rt->rt_ifp;
542 ro->ro_rt->rt_use++;
543 if (ro->ro_rt->rt_flags & RTF_GATEWAY)
544 dst = (struct sockaddr_in6 *)ro->ro_rt->rt_gateway;
545 m->m_flags &= ~(M_BCAST | M_MCAST); /* just in case */
546
547 in6_ifstat_inc(ifp, ifs6_out_request);
548
549 /*
550 * Check if there is the outgoing interface conflicts with
551 * the interface specified by ifi6_ifindex(if specified).
552 * Note that loopback interface is always okay.
553 * (this happens when we are sending packet toward my
554 * interface)
555 */
556 if (opt && opt->ip6po_pktinfo
557 && opt->ip6po_pktinfo->ipi6_ifindex) {
558 if (!(ifp->if_flags & IFF_LOOPBACK)
559 && ifp->if_index != opt->ip6po_pktinfo->ipi6_ifindex) {
560 ip6stat.ip6s_noroute++;
561 in6_ifstat_inc(ifp, ifs6_out_discard);
562 error = EHOSTUNREACH;
563 goto bad;
564 }
565 }
566
567 if (opt && opt->ip6po_hlim != -1)
568 ip6->ip6_hlim = opt->ip6po_hlim & 0xff;
569 } else {
570 /* Multicast */
571 struct in6_multi *in6m;
572
573 m->m_flags = (m->m_flags & ~M_BCAST) | M_MCAST;
574
575 /*
576 * See if the caller provided any multicast options
577 */
578 ifp = NULL;
579 if (im6o != NULL) {
580 ip6->ip6_hlim = im6o->im6o_multicast_hlim;
581 if (im6o->im6o_multicast_ifp != NULL)
582 ifp = im6o->im6o_multicast_ifp;
583 } else
584 ip6->ip6_hlim = ip6_defmcasthlim;
585
586 /*
587 * See if the caller provided the outgoing interface
588 * as an ancillary data.
589 * Boundary check for ifindex is assumed to be already done.
590 */
591 if (opt && opt->ip6po_pktinfo && opt->ip6po_pktinfo->ipi6_ifindex)
592 ifp = ifindex2ifnet[opt->ip6po_pktinfo->ipi6_ifindex];
593
594 /*
595 * If the destination is a node-local scope multicast,
596 * the packet should be loop-backed only.
597 */
598 if (IN6_IS_ADDR_MC_NODELOCAL(&ip6->ip6_dst)) {
599 /*
600 * If the outgoing interface is already specified,
601 * it should be a loopback interface.
602 */
603 if (ifp && (ifp->if_flags & IFF_LOOPBACK) == 0) {
604 ip6stat.ip6s_badscope++;
605 error = ENETUNREACH; /* XXX: better error? */
606 /* XXX correct ifp? */
607 in6_ifstat_inc(ifp, ifs6_out_discard);
608 goto bad;
609 }
610 else {
611 ifp = &loif[0];
612 }
613 }
614
615 if (opt && opt->ip6po_hlim != -1)
616 ip6->ip6_hlim = opt->ip6po_hlim & 0xff;
617
618 /*
619 * If caller did not provide an interface lookup a
620 * default in the routing table. This is either a
621 * default for the speicfied group (i.e. a host
622 * route), or a multicast default (a route for the
623 * ``net'' ff00::/8).
624 */
625 if (ifp == NULL) {
626 if (ro->ro_rt == 0) {
627 ro->ro_rt = rtalloc1((struct sockaddr *)
628 &ro->ro_dst, 0
629 );
630 }
631 if (ro->ro_rt == 0) {
632 ip6stat.ip6s_noroute++;
633 error = EHOSTUNREACH;
634 /* XXX in6_ifstat_inc(ifp, ifs6_out_discard) */
635 goto bad;
636 }
637 ia = ifatoia6(ro->ro_rt->rt_ifa);
638 ifp = ro->ro_rt->rt_ifp;
639 ro->ro_rt->rt_use++;
640 }
641
642 if ((flags & IPV6_FORWARDING) == 0)
643 in6_ifstat_inc(ifp, ifs6_out_request);
644 in6_ifstat_inc(ifp, ifs6_out_mcast);
645
646 /*
647 * Confirm that the outgoing interface supports multicast.
648 */
649 if ((ifp->if_flags & IFF_MULTICAST) == 0) {
650 ip6stat.ip6s_noroute++;
651 in6_ifstat_inc(ifp, ifs6_out_discard);
652 error = ENETUNREACH;
653 goto bad;
654 }
655 IN6_LOOKUP_MULTI(ip6->ip6_dst, ifp, in6m);
656 if (in6m != NULL &&
657 (im6o == NULL || im6o->im6o_multicast_loop)) {
658 /*
659 * If we belong to the destination multicast group
660 * on the outgoing interface, and the caller did not
661 * forbid loopback, loop back a copy.
662 */
663 ip6_mloopback(ifp, m, dst);
664 } else {
665 /*
666 * If we are acting as a multicast router, perform
667 * multicast forwarding as if the packet had just
668 * arrived on the interface to which we are about
669 * to send. The multicast forwarding function
670 * recursively calls this function, using the
671 * IPV6_FORWARDING flag to prevent infinite recursion.
672 *
673 * Multicasts that are looped back by ip6_mloopback(),
674 * above, will be forwarded by the ip6_input() routine,
675 * if necessary.
676 */
677 if (ip6_mrouter && (flags & IPV6_FORWARDING) == 0) {
678 if (ip6_mforward(ip6, ifp, m) != NULL) {
679 m_freem(m);
680 goto done;
681 }
682 }
683 }
684 /*
685 * Multicasts with a hoplimit of zero may be looped back,
686 * above, but must not be transmitted on a network.
687 * Also, multicasts addressed to the loopback interface
688 * are not sent -- the above call to ip6_mloopback() will
689 * loop back a copy if this host actually belongs to the
690 * destination group on the loopback interface.
691 */
692 if (ip6->ip6_hlim == 0 || (ifp->if_flags & IFF_LOOPBACK)) {
693 m_freem(m);
694 goto done;
695 }
696 }
697
698 /*
699 * Fill the outgoing inteface to tell the upper layer
700 * to increment per-interface statistics.
701 */
702 if (ifpp)
703 *ifpp = ifp;
704
705 /*
706 * Determine path MTU.
707 */
708 if (ro_pmtu != ro) {
709 /* The first hop and the final destination may differ. */
710 struct sockaddr_in6 *sin6_fin =
711 (struct sockaddr_in6 *)&ro_pmtu->ro_dst;
712 if (ro_pmtu->ro_rt && ((ro->ro_rt->rt_flags & RTF_UP) == 0 ||
713 !IN6_ARE_ADDR_EQUAL(&sin6_fin->sin6_addr,
714 &finaldst))) {
715 RTFREE(ro_pmtu->ro_rt);
716 ro_pmtu->ro_rt = (struct rtentry *)0;
717 }
718 if (ro_pmtu->ro_rt == 0) {
719 bzero(sin6_fin, sizeof(*sin6_fin));
720 sin6_fin->sin6_family = AF_INET6;
721 sin6_fin->sin6_len = sizeof(struct sockaddr_in6);
722 sin6_fin->sin6_addr = finaldst;
723
724 rtalloc((struct route *)ro_pmtu);
725 }
726 }
727 if (ro_pmtu->ro_rt != NULL) {
728 u_int32_t ifmtu = nd_ifinfo[ifp->if_index].linkmtu;
729
730 mtu = ro_pmtu->ro_rt->rt_rmx.rmx_mtu;
731 if (mtu > ifmtu) {
732 /*
733 * The MTU on the route is larger than the MTU on
734 * the interface! This shouldn't happen, unless the
735 * MTU of the interface has been changed after the
736 * interface was brought up. Change the MTU in the
737 * route to match the interface MTU (as long as the
738 * field isn't locked).
739 */
740 mtu = ifmtu;
741 if ((ro_pmtu->ro_rt->rt_rmx.rmx_locks & RTV_MTU) == 0)
742 ro_pmtu->ro_rt->rt_rmx.rmx_mtu = mtu; /* XXX */
743 }
744 } else {
745 mtu = nd_ifinfo[ifp->if_index].linkmtu;
746 }
747
748 /*
749 * Fake link-local scope-class addresses
750 */
751 if ((ifp->if_flags & IFF_LOOPBACK) == 0) {
752 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
753 ip6->ip6_src.s6_addr16[1] = 0;
754 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
755 ip6->ip6_dst.s6_addr16[1] = 0;
756 }
757
758 /*
759 * If the outgoing packet contains a hop-by-hop options header,
760 * it must be examined and processed even by the source node.
761 * (RFC 2460, section 4.)
762 */
763 if (exthdrs.ip6e_hbh) {
764 struct ip6_hbh *hbh = mtod(exthdrs.ip6e_hbh,
765 struct ip6_hbh *);
766 u_int32_t dummy1; /* XXX unused */
767 u_int32_t dummy2; /* XXX unused */
768
769 /*
770 * XXX: if we have to send an ICMPv6 error to the sender,
771 * we need the M_LOOP flag since icmp6_error() expects
772 * the IPv6 and the hop-by-hop options header are
773 * continuous unless the flag is set.
774 */
775 m->m_flags |= M_LOOP;
776 m->m_pkthdr.rcvif = ifp;
777 if (ip6_process_hopopts(m,
778 (u_int8_t *)(hbh + 1),
779 ((hbh->ip6h_len + 1) << 3) -
780 sizeof(struct ip6_hbh),
781 &dummy1, &dummy2) < 0) {
782 /* m was already freed at this point */
783 error = EINVAL;/* better error? */
784 goto done;
785 }
786 m->m_flags &= ~M_LOOP; /* XXX */
787 m->m_pkthdr.rcvif = NULL;
788 }
789
790 /*
791 * Send the packet to the outgoing interface.
792 * If necessary, do IPv6 fragmentation before sending.
793 */
794 tlen = m->m_pkthdr.len;
795 if (tlen <= mtu
796 #ifdef notyet
797 /*
798 * On any link that cannot convey a 1280-octet packet in one piece,
799 * link-specific fragmentation and reassembly must be provided at
800 * a layer below IPv6. [RFC 2460, sec.5]
801 * Thus if the interface has ability of link-level fragmentation,
802 * we can just send the packet even if the packet size is
803 * larger than the link's MTU.
804 * XXX: IFF_FRAGMENTABLE (or such) flag has not been defined yet...
805 */
806
807 || ifp->if_flags & IFF_FRAGMENTABLE
808 #endif
809 )
810 {
811 #ifdef IFA_STATS
812 if (IFA_STATS) {
813 struct in6_ifaddr *ia6;
814 ip6 = mtod(m, struct ip6_hdr *);
815 ia6 = in6_ifawithifp(ifp, &ip6->ip6_src);
816 if (ia6) {
817 ia->ia_ifa.ifa_data.ifad_outbytes +=
818 m->m_pkthdr.len;
819 }
820 }
821 #endif
822 #ifdef OLDIP6OUTPUT
823 error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst,
824 ro->ro_rt);
825 #else
826 error = nd6_output(ifp, m, dst, ro->ro_rt);
827 #endif
828 goto done;
829 } else if (mtu < IPV6_MMTU) {
830 /*
831 * note that path MTU is never less than IPV6_MMTU
832 * (see icmp6_input).
833 */
834 error = EMSGSIZE;
835 in6_ifstat_inc(ifp, ifs6_out_fragfail);
836 goto bad;
837 } else if (ip6->ip6_plen == 0) { /* jumbo payload cannot be fragmented */
838 error = EMSGSIZE;
839 in6_ifstat_inc(ifp, ifs6_out_fragfail);
840 goto bad;
841 } else {
842 struct mbuf **mnext, *m_frgpart;
843 struct ip6_frag *ip6f;
844 u_int32_t id = htonl(ip6_id++);
845 u_char nextproto;
846
847 /*
848 * Too large for the destination or interface;
849 * fragment if possible.
850 * Must be able to put at least 8 bytes per fragment.
851 */
852 hlen = unfragpartlen;
853 if (mtu > IPV6_MAXPACKET)
854 mtu = IPV6_MAXPACKET;
855 len = (mtu - hlen - sizeof(struct ip6_frag)) & ~7;
856 if (len < 8) {
857 error = EMSGSIZE;
858 in6_ifstat_inc(ifp, ifs6_out_fragfail);
859 goto bad;
860 }
861
862 mnext = &m->m_nextpkt;
863
864 /*
865 * Change the next header field of the last header in the
866 * unfragmentable part.
867 */
868 if (exthdrs.ip6e_rthdr) {
869 nextproto = *mtod(exthdrs.ip6e_rthdr, u_char *);
870 *mtod(exthdrs.ip6e_rthdr, u_char *) = IPPROTO_FRAGMENT;
871 }
872 else if (exthdrs.ip6e_dest1) {
873 nextproto = *mtod(exthdrs.ip6e_dest1, u_char *);
874 *mtod(exthdrs.ip6e_dest1, u_char *) = IPPROTO_FRAGMENT;
875 }
876 else if (exthdrs.ip6e_hbh) {
877 nextproto = *mtod(exthdrs.ip6e_hbh, u_char *);
878 *mtod(exthdrs.ip6e_hbh, u_char *) = IPPROTO_FRAGMENT;
879 }
880 else {
881 nextproto = ip6->ip6_nxt;
882 ip6->ip6_nxt = IPPROTO_FRAGMENT;
883 }
884
885 /*
886 * Loop through length of segment after first fragment,
887 * make new header and copy data of each part and link onto chain.
888 */
889 m0 = m;
890 for (off = hlen; off < tlen; off += len) {
891 MGETHDR(m, M_DONTWAIT, MT_HEADER);
892 if (!m) {
893 error = ENOBUFS;
894 ip6stat.ip6s_odropped++;
895 goto sendorfree;
896 }
897 m->m_flags = m0->m_flags & M_COPYFLAGS;
898 *mnext = m;
899 mnext = &m->m_nextpkt;
900 m->m_data += max_linkhdr;
901 mhip6 = mtod(m, struct ip6_hdr *);
902 *mhip6 = *ip6;
903 m->m_len = sizeof(*mhip6);
904 error = ip6_insertfraghdr(m0, m, hlen, &ip6f);
905 if (error) {
906 ip6stat.ip6s_odropped++;
907 goto sendorfree;
908 }
909 ip6f->ip6f_offlg = htons((u_short)((off - hlen) & ~7));
910 if (off + len >= tlen)
911 len = tlen - off;
912 else
913 ip6f->ip6f_offlg |= IP6F_MORE_FRAG;
914 mhip6->ip6_plen = htons((u_short)(len + hlen +
915 sizeof(*ip6f) -
916 sizeof(struct ip6_hdr)));
917 if ((m_frgpart = m_copy(m0, off, len)) == 0) {
918 error = ENOBUFS;
919 ip6stat.ip6s_odropped++;
920 goto sendorfree;
921 }
922 m_cat(m, m_frgpart);
923 m->m_pkthdr.len = len + hlen + sizeof(*ip6f);
924 m->m_pkthdr.rcvif = (struct ifnet *)0;
925 ip6f->ip6f_reserved = 0;
926 ip6f->ip6f_ident = id;
927 ip6f->ip6f_nxt = nextproto;
928 ip6stat.ip6s_ofragments++;
929 in6_ifstat_inc(ifp, ifs6_out_fragcreat);
930 }
931
932 in6_ifstat_inc(ifp, ifs6_out_fragok);
933 }
934
935 /*
936 * Remove leading garbages.
937 */
938 sendorfree:
939 m = m0->m_nextpkt;
940 m0->m_nextpkt = 0;
941 m_freem(m0);
942 for (m0 = m; m; m = m0) {
943 m0 = m->m_nextpkt;
944 m->m_nextpkt = 0;
945 if (error == 0) {
946 #ifdef IFA_STATS
947 if (IFA_STATS) {
948 struct in6_ifaddr *ia6;
949 ip6 = mtod(m, struct ip6_hdr *);
950 ia6 = in6_ifawithifp(ifp, &ip6->ip6_src);
951 if (ia6) {
952 ia->ia_ifa.ifa_data.ifad_outbytes +=
953 m->m_pkthdr.len;
954 }
955 }
956 #endif
957 #ifdef OLDIP6OUTPUT
958 error = (*ifp->if_output)(ifp, m,
959 (struct sockaddr *)dst,
960 ro->ro_rt);
961 #else
962 error = nd6_output(ifp, m, dst, ro->ro_rt);
963 #endif
964 }
965 else
966 m_freem(m);
967 }
968
969 if (error == 0)
970 ip6stat.ip6s_fragmented++;
971
972 done:
973 if (ro == &ip6route && ro->ro_rt) { /* brace necessary for RTFREE */
974 RTFREE(ro->ro_rt);
975 } else if (ro_pmtu == &ip6route && ro_pmtu->ro_rt) {
976 RTFREE(ro_pmtu->ro_rt);
977 }
978
979 #ifdef IPSEC
980 if (sp != NULL)
981 key_freesp(sp);
982 #endif /* IPSEC */
983
984 return(error);
985
986 freehdrs:
987 m_freem(exthdrs.ip6e_hbh); /* m_freem will check if mbuf is 0 */
988 m_freem(exthdrs.ip6e_dest1);
989 m_freem(exthdrs.ip6e_rthdr);
990 m_freem(exthdrs.ip6e_dest2);
991 /* fall through */
992 bad:
993 m_freem(m);
994 goto done;
995 }
996
997 static int
998 ip6_copyexthdr(mp, hdr, hlen)
999 struct mbuf **mp;
1000 caddr_t hdr;
1001 int hlen;
1002 {
1003 struct mbuf *m;
1004
1005 if (hlen > MCLBYTES)
1006 return(ENOBUFS); /* XXX */
1007
1008 MGET(m, M_DONTWAIT, MT_DATA);
1009 if (!m)
1010 return(ENOBUFS);
1011
1012 if (hlen > MLEN) {
1013 MCLGET(m, M_DONTWAIT);
1014 if ((m->m_flags & M_EXT) == 0) {
1015 m_free(m);
1016 return(ENOBUFS);
1017 }
1018 }
1019 m->m_len = hlen;
1020 if (hdr)
1021 bcopy(hdr, mtod(m, caddr_t), hlen);
1022
1023 *mp = m;
1024 return(0);
1025 }
1026
1027 /*
1028 * Insert jumbo payload option.
1029 */
1030 static int
1031 ip6_insert_jumboopt(exthdrs, plen)
1032 struct ip6_exthdrs *exthdrs;
1033 u_int32_t plen;
1034 {
1035 struct mbuf *mopt;
1036 u_char *optbuf;
1037
1038 #define JUMBOOPTLEN 8 /* length of jumbo payload option and padding */
1039
1040 /*
1041 * If there is no hop-by-hop options header, allocate new one.
1042 * If there is one but it doesn't have enough space to store the
1043 * jumbo payload option, allocate a cluster to store the whole options.
1044 * Otherwise, use it to store the options.
1045 */
1046 if (exthdrs->ip6e_hbh == 0) {
1047 MGET(mopt, M_DONTWAIT, MT_DATA);
1048 if (mopt == 0)
1049 return(ENOBUFS);
1050 mopt->m_len = JUMBOOPTLEN;
1051 optbuf = mtod(mopt, u_char *);
1052 optbuf[1] = 0; /* = ((JUMBOOPTLEN) >> 3) - 1 */
1053 exthdrs->ip6e_hbh = mopt;
1054 }
1055 else {
1056 struct ip6_hbh *hbh;
1057
1058 mopt = exthdrs->ip6e_hbh;
1059 if (M_TRAILINGSPACE(mopt) < JUMBOOPTLEN) {
1060 caddr_t oldoptp = mtod(mopt, caddr_t);
1061 int oldoptlen = mopt->m_len;
1062
1063 if (mopt->m_flags & M_EXT)
1064 return(ENOBUFS); /* XXX */
1065 MCLGET(mopt, M_DONTWAIT);
1066 if ((mopt->m_flags & M_EXT) == 0)
1067 return(ENOBUFS);
1068
1069 bcopy(oldoptp, mtod(mopt, caddr_t), oldoptlen);
1070 optbuf = mtod(mopt, caddr_t) + oldoptlen;
1071 mopt->m_len = oldoptlen + JUMBOOPTLEN;
1072 }
1073 else {
1074 optbuf = mtod(mopt, u_char *) + mopt->m_len;
1075 mopt->m_len += JUMBOOPTLEN;
1076 }
1077 optbuf[0] = IP6OPT_PADN;
1078 optbuf[1] = 1;
1079
1080 /*
1081 * Adjust the header length according to the pad and
1082 * the jumbo payload option.
1083 */
1084 hbh = mtod(mopt, struct ip6_hbh *);
1085 hbh->ip6h_len += (JUMBOOPTLEN >> 3);
1086 }
1087
1088 /* fill in the option. */
1089 optbuf[2] = IP6OPT_JUMBO;
1090 optbuf[3] = 4;
1091 *(u_int32_t *)&optbuf[4] = htonl(plen + JUMBOOPTLEN);
1092
1093 /* finally, adjust the packet header length */
1094 exthdrs->ip6e_ip6->m_pkthdr.len += JUMBOOPTLEN;
1095
1096 return(0);
1097 #undef JUMBOOPTLEN
1098 }
1099
1100 /*
1101 * Insert fragment header and copy unfragmentable header portions.
1102 */
1103 static int
1104 ip6_insertfraghdr(m0, m, hlen, frghdrp)
1105 struct mbuf *m0, *m;
1106 int hlen;
1107 struct ip6_frag **frghdrp;
1108 {
1109 struct mbuf *n, *mlast;
1110
1111 if (hlen > sizeof(struct ip6_hdr)) {
1112 n = m_copym(m0, sizeof(struct ip6_hdr),
1113 hlen - sizeof(struct ip6_hdr), M_DONTWAIT);
1114 if (n == 0)
1115 return(ENOBUFS);
1116 m->m_next = n;
1117 }
1118 else
1119 n = m;
1120
1121 /* Search for the last mbuf of unfragmentable part. */
1122 for (mlast = n; mlast->m_next; mlast = mlast->m_next)
1123 ;
1124
1125 if ((mlast->m_flags & M_EXT) == 0 &&
1126 M_TRAILINGSPACE(mlast) < sizeof(struct ip6_frag)) {
1127 /* use the trailing space of the last mbuf for the fragment hdr */
1128 *frghdrp =
1129 (struct ip6_frag *)(mtod(mlast, caddr_t) + mlast->m_len);
1130 mlast->m_len += sizeof(struct ip6_frag);
1131 m->m_pkthdr.len += sizeof(struct ip6_frag);
1132 }
1133 else {
1134 /* allocate a new mbuf for the fragment header */
1135 struct mbuf *mfrg;
1136
1137 MGET(mfrg, M_DONTWAIT, MT_DATA);
1138 if (mfrg == 0)
1139 return(ENOBUFS);
1140 mfrg->m_len = sizeof(struct ip6_frag);
1141 *frghdrp = mtod(mfrg, struct ip6_frag *);
1142 mlast->m_next = mfrg;
1143 }
1144
1145 return(0);
1146 }
1147
1148 /*
1149 * IP6 socket option processing.
1150 */
1151 int
1152 ip6_ctloutput(op, so, level, optname, mp)
1153 int op;
1154 struct socket *so;
1155 int level, optname;
1156 struct mbuf **mp;
1157 {
1158 register struct in6pcb *in6p = sotoin6pcb(so);
1159 register struct mbuf *m = *mp;
1160 register int optval = 0;
1161 int error = 0;
1162 struct proc *p = curproc; /* XXX */
1163
1164 if (level == IPPROTO_IPV6)
1165 switch (op) {
1166
1167 case PRCO_SETOPT:
1168 switch (optname) {
1169 case IPV6_PKTOPTIONS:
1170 return(ip6_pcbopts(&in6p->in6p_outputopts,
1171 m, so));
1172 case IPV6_HOPOPTS:
1173 case IPV6_DSTOPTS:
1174 if (p == 0 || suser(p->p_ucred, &p->p_acflag)) {
1175 error = EPERM;
1176 break;
1177 }
1178 /* fall through */
1179 case IPV6_UNICAST_HOPS:
1180 case IPV6_RECVOPTS:
1181 case IPV6_RECVRETOPTS:
1182 case IPV6_RECVDSTADDR:
1183 case IPV6_PKTINFO:
1184 case IPV6_HOPLIMIT:
1185 case IPV6_RTHDR:
1186 case IPV6_CHECKSUM:
1187 case IPV6_FAITH:
1188 #ifndef INET6_BINDV6ONLY
1189 case IPV6_BINDV6ONLY:
1190 #endif
1191 if (!m || m->m_len != sizeof(int))
1192 error = EINVAL;
1193 else {
1194 optval = *mtod(m, int *);
1195 switch (optname) {
1196
1197 case IPV6_UNICAST_HOPS:
1198 if (optval < -1 || optval >= 256)
1199 error = EINVAL;
1200 else {
1201 /* -1 = kernel default */
1202 in6p->in6p_hops = optval;
1203 }
1204 break;
1205 #define OPTSET(bit) \
1206 if (optval) \
1207 in6p->in6p_flags |= bit; \
1208 else \
1209 in6p->in6p_flags &= ~bit;
1210
1211 case IPV6_RECVOPTS:
1212 OPTSET(IN6P_RECVOPTS);
1213 break;
1214
1215 case IPV6_RECVRETOPTS:
1216 OPTSET(IN6P_RECVRETOPTS);
1217 break;
1218
1219 case IPV6_RECVDSTADDR:
1220 OPTSET(IN6P_RECVDSTADDR);
1221 break;
1222
1223 case IPV6_PKTINFO:
1224 OPTSET(IN6P_PKTINFO);
1225 break;
1226
1227 case IPV6_HOPLIMIT:
1228 OPTSET(IN6P_HOPLIMIT);
1229 break;
1230
1231 case IPV6_HOPOPTS:
1232 OPTSET(IN6P_HOPOPTS);
1233 break;
1234
1235 case IPV6_DSTOPTS:
1236 OPTSET(IN6P_DSTOPTS);
1237 break;
1238
1239 case IPV6_RTHDR:
1240 OPTSET(IN6P_RTHDR);
1241 break;
1242
1243 case IPV6_CHECKSUM:
1244 in6p->in6p_cksum = optval;
1245 break;
1246
1247 case IPV6_FAITH:
1248 OPTSET(IN6P_FAITH);
1249 break;
1250
1251 #ifndef INET6_BINDV6ONLY
1252 case IPV6_BINDV6ONLY:
1253 OPTSET(IN6P_BINDV6ONLY);
1254 break;
1255 #endif
1256 }
1257 }
1258 break;
1259 #undef OPTSET
1260
1261 case IPV6_MULTICAST_IF:
1262 case IPV6_MULTICAST_HOPS:
1263 case IPV6_MULTICAST_LOOP:
1264 case IPV6_JOIN_GROUP:
1265 case IPV6_LEAVE_GROUP:
1266 error = ip6_setmoptions(optname, &in6p->in6p_moptions, m);
1267 break;
1268
1269 case IPV6_PORTRANGE:
1270 optval = *mtod(m, int *);
1271
1272 switch (optval) {
1273 case IPV6_PORTRANGE_DEFAULT:
1274 in6p->in6p_flags &= ~(IN6P_LOWPORT);
1275 in6p->in6p_flags &= ~(IN6P_HIGHPORT);
1276 break;
1277
1278 case IPV6_PORTRANGE_HIGH:
1279 in6p->in6p_flags &= ~(IN6P_LOWPORT);
1280 in6p->in6p_flags |= IN6P_HIGHPORT;
1281 break;
1282
1283 case IPV6_PORTRANGE_LOW:
1284 in6p->in6p_flags &= ~(IN6P_HIGHPORT);
1285 in6p->in6p_flags |= IN6P_LOWPORT;
1286 break;
1287
1288 default:
1289 error = EINVAL;
1290 break;
1291 }
1292 break;
1293
1294 #ifdef IPSEC
1295 case IPV6_IPSEC_POLICY:
1296 {
1297 caddr_t req = NULL;
1298 size_t len = 0;
1299
1300 int priv = 0;
1301 if (p == 0 || suser(p->p_ucred, &p->p_acflag))
1302 priv = 0;
1303 else
1304 priv = 1;
1305 if (m) {
1306 req = mtod(m, caddr_t);
1307 len = m->m_len;
1308 }
1309 error = ipsec6_set_policy(in6p,
1310 optname, req, len, priv);
1311 }
1312 break;
1313 #endif /* IPSEC */
1314
1315 default:
1316 error = ENOPROTOOPT;
1317 break;
1318 }
1319 if (m)
1320 (void)m_free(m);
1321 break;
1322
1323 case PRCO_GETOPT:
1324 switch (optname) {
1325
1326 case IPV6_OPTIONS:
1327 case IPV6_RETOPTS:
1328 #if 0
1329 *mp = m = m_get(M_WAIT, MT_SOOPTS);
1330 if (in6p->in6p_options) {
1331 m->m_len = in6p->in6p_options->m_len;
1332 bcopy(mtod(in6p->in6p_options, caddr_t),
1333 mtod(m, caddr_t),
1334 (unsigned)m->m_len);
1335 } else
1336 m->m_len = 0;
1337 break;
1338 #else
1339 error = ENOPROTOOPT;
1340 break;
1341 #endif
1342
1343 case IPV6_PKTOPTIONS:
1344 if (in6p->in6p_options) {
1345 *mp = m_copym(in6p->in6p_options, 0,
1346 M_COPYALL, M_WAIT);
1347 } else {
1348 *mp = m_get(M_WAIT, MT_SOOPTS);
1349 (*mp)->m_len = 0;
1350 }
1351 break;
1352
1353 case IPV6_HOPOPTS:
1354 case IPV6_DSTOPTS:
1355 if (p == 0 || suser(p->p_ucred, &p->p_acflag)) {
1356 error = EPERM;
1357 break;
1358 }
1359 /* fall through */
1360 case IPV6_UNICAST_HOPS:
1361 case IPV6_RECVOPTS:
1362 case IPV6_RECVRETOPTS:
1363 case IPV6_RECVDSTADDR:
1364 case IPV6_PORTRANGE:
1365 case IPV6_PKTINFO:
1366 case IPV6_HOPLIMIT:
1367 case IPV6_RTHDR:
1368 case IPV6_CHECKSUM:
1369 case IPV6_FAITH:
1370 #ifndef INET6_BINDV6ONLY
1371 case IPV6_BINDV6ONLY:
1372 #endif
1373 *mp = m = m_get(M_WAIT, MT_SOOPTS);
1374 m->m_len = sizeof(int);
1375 switch (optname) {
1376
1377 case IPV6_UNICAST_HOPS:
1378 optval = in6p->in6p_hops;
1379 break;
1380
1381 #define OPTBIT(bit) (in6p->in6p_flags & bit ? 1 : 0)
1382
1383 case IPV6_RECVOPTS:
1384 optval = OPTBIT(IN6P_RECVOPTS);
1385 break;
1386
1387 case IPV6_RECVRETOPTS:
1388 optval = OPTBIT(IN6P_RECVRETOPTS);
1389 break;
1390
1391 case IPV6_RECVDSTADDR:
1392 optval = OPTBIT(IN6P_RECVDSTADDR);
1393 break;
1394
1395 case IPV6_PORTRANGE:
1396 {
1397 int flags;
1398 flags = in6p->in6p_flags;
1399 if (flags & IN6P_HIGHPORT)
1400 optval = IPV6_PORTRANGE_HIGH;
1401 else if (flags & IN6P_LOWPORT)
1402 optval = IPV6_PORTRANGE_LOW;
1403 else
1404 optval = 0;
1405 break;
1406 }
1407
1408 case IPV6_PKTINFO:
1409 optval = OPTBIT(IN6P_PKTINFO);
1410 break;
1411
1412 case IPV6_HOPLIMIT:
1413 optval = OPTBIT(IN6P_HOPLIMIT);
1414 break;
1415
1416 case IPV6_HOPOPTS:
1417 optval = OPTBIT(IN6P_HOPOPTS);
1418 break;
1419
1420 case IPV6_DSTOPTS:
1421 optval = OPTBIT(IN6P_DSTOPTS);
1422 break;
1423
1424 case IPV6_RTHDR:
1425 optval = OPTBIT(IN6P_RTHDR);
1426 break;
1427
1428 case IPV6_CHECKSUM:
1429 optval = in6p->in6p_cksum;
1430 break;
1431
1432 case IPV6_FAITH:
1433 optval = OPTBIT(IN6P_FAITH);
1434 break;
1435
1436 #ifndef INET6_BINDV6ONLY
1437 case IPV6_BINDV6ONLY:
1438 optval = OPTBIT(IN6P_BINDV6ONLY);
1439 break;
1440 #endif
1441 }
1442 *mtod(m, int *) = optval;
1443 break;
1444
1445 case IPV6_MULTICAST_IF:
1446 case IPV6_MULTICAST_HOPS:
1447 case IPV6_MULTICAST_LOOP:
1448 case IPV6_JOIN_GROUP:
1449 case IPV6_LEAVE_GROUP:
1450 error = ip6_getmoptions(optname, in6p->in6p_moptions, mp);
1451 break;
1452
1453 #ifdef IPSEC
1454 case IPV6_IPSEC_POLICY:
1455 {
1456 caddr_t req = NULL;
1457 size_t len = 0;
1458
1459 if (m) {
1460 req = mtod(m, caddr_t);
1461 len = m->m_len;
1462 }
1463 error = ipsec6_get_policy(in6p, req, len, mp);
1464 break;
1465 }
1466 #endif /* IPSEC */
1467
1468 default:
1469 error = ENOPROTOOPT;
1470 break;
1471 }
1472 break;
1473 }
1474 else {
1475 error = EINVAL;
1476 if (op == PRCO_SETOPT && *mp)
1477 (void)m_free(*mp);
1478 }
1479 return(error);
1480 }
1481
1482 /*
1483 * Set up IP6 options in pcb for insertion in output packets.
1484 * Store in mbuf with pointer in pcbopt, adding pseudo-option
1485 * with destination address if source routed.
1486 */
1487 static int
1488 ip6_pcbopts(pktopt, m, so)
1489 struct ip6_pktopts **pktopt;
1490 register struct mbuf *m;
1491 struct socket *so;
1492 {
1493 register struct ip6_pktopts *opt = *pktopt;
1494 int error = 0;
1495 struct proc *p = curproc; /* XXX */
1496 int priv = 0;
1497
1498 /* turn off any old options. */
1499 if (opt) {
1500 if (opt->ip6po_m)
1501 (void)m_free(opt->ip6po_m);
1502 }
1503 else
1504 opt = malloc(sizeof(*opt), M_IP6OPT, M_WAITOK);
1505 *pktopt = 0;
1506
1507 if (!m || m->m_len == 0) {
1508 /*
1509 * Only turning off any previous options.
1510 */
1511 if (opt)
1512 free(opt, M_IP6OPT);
1513 if (m)
1514 (void)m_free(m);
1515 return(0);
1516 }
1517
1518 /* set options specified by user. */
1519 if (p && !suser(p->p_ucred, &p->p_acflag))
1520 priv = 1;
1521 if ((error = ip6_setpktoptions(m, opt, priv)) != 0) {
1522 (void)m_free(m);
1523 return(error);
1524 }
1525 *pktopt = opt;
1526 return(0);
1527 }
1528
1529 /*
1530 * Set the IP6 multicast options in response to user setsockopt().
1531 */
1532 static int
1533 ip6_setmoptions(optname, im6op, m)
1534 int optname;
1535 struct ip6_moptions **im6op;
1536 struct mbuf *m;
1537 {
1538 int error = 0;
1539 u_int loop, ifindex;
1540 struct ipv6_mreq *mreq;
1541 struct ifnet *ifp;
1542 struct ip6_moptions *im6o = *im6op;
1543 struct route_in6 ro;
1544 struct sockaddr_in6 *dst;
1545 struct in6_multi_mship *imm;
1546 struct proc *p = curproc; /* XXX */
1547
1548 if (im6o == NULL) {
1549 /*
1550 * No multicast option buffer attached to the pcb;
1551 * allocate one and initialize to default values.
1552 */
1553 im6o = (struct ip6_moptions *)
1554 malloc(sizeof(*im6o), M_IPMOPTS, M_WAITOK);
1555
1556 if (im6o == NULL)
1557 return(ENOBUFS);
1558 *im6op = im6o;
1559 im6o->im6o_multicast_ifp = NULL;
1560 im6o->im6o_multicast_hlim = ip6_defmcasthlim;
1561 im6o->im6o_multicast_loop = IPV6_DEFAULT_MULTICAST_LOOP;
1562 LIST_INIT(&im6o->im6o_memberships);
1563 }
1564
1565 switch (optname) {
1566
1567 case IPV6_MULTICAST_IF:
1568 /*
1569 * Select the interface for outgoing multicast packets.
1570 */
1571 if (m == NULL || m->m_len != sizeof(u_int)) {
1572 error = EINVAL;
1573 break;
1574 }
1575 ifindex = *(mtod(m, u_int *));
1576 if (ifindex < 0 || if_index < ifindex) {
1577 error = ENXIO; /* XXX EINVAL? */
1578 break;
1579 }
1580 ifp = ifindex2ifnet[ifindex];
1581 if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
1582 error = EADDRNOTAVAIL;
1583 break;
1584 }
1585 im6o->im6o_multicast_ifp = ifp;
1586 break;
1587
1588 case IPV6_MULTICAST_HOPS:
1589 {
1590 /*
1591 * Set the IP6 hoplimit for outgoing multicast packets.
1592 */
1593 int optval;
1594 if (m == NULL || m->m_len != sizeof(int)) {
1595 error = EINVAL;
1596 break;
1597 }
1598 optval = *(mtod(m, u_int *));
1599 if (optval < -1 || optval >= 256)
1600 error = EINVAL;
1601 else if (optval == -1)
1602 im6o->im6o_multicast_hlim = ip6_defmcasthlim;
1603 else
1604 im6o->im6o_multicast_hlim = optval;
1605 break;
1606 }
1607
1608 case IPV6_MULTICAST_LOOP:
1609 /*
1610 * Set the loopback flag for outgoing multicast packets.
1611 * Must be zero or one.
1612 */
1613 if (m == NULL || m->m_len != sizeof(u_int) ||
1614 (loop = *(mtod(m, u_int *))) > 1) {
1615 error = EINVAL;
1616 break;
1617 }
1618 im6o->im6o_multicast_loop = loop;
1619 break;
1620
1621 case IPV6_JOIN_GROUP:
1622 /*
1623 * Add a multicast group membership.
1624 * Group must be a valid IP6 multicast address.
1625 */
1626 if (m == NULL || m->m_len != sizeof(struct ipv6_mreq)) {
1627 error = EINVAL;
1628 break;
1629 }
1630 mreq = mtod(m, struct ipv6_mreq *);
1631 if (IN6_IS_ADDR_UNSPECIFIED(&mreq->ipv6mr_multiaddr)) {
1632 /*
1633 * We use the unspecified address to specify to accept
1634 * all multicast addresses. Only super user is allowed
1635 * to do this.
1636 */
1637 if (suser(p->p_ucred, &p->p_acflag)) {
1638 error = EACCES;
1639 break;
1640 }
1641 } else if (!IN6_IS_ADDR_MULTICAST(&mreq->ipv6mr_multiaddr)) {
1642 error = EINVAL;
1643 break;
1644 }
1645
1646 /*
1647 * If the interface is specified, validate it.
1648 */
1649 if (mreq->ipv6mr_interface < 0
1650 || if_index < mreq->ipv6mr_interface) {
1651 error = ENXIO; /* XXX EINVAL? */
1652 break;
1653 }
1654 /*
1655 * If no interface was explicitly specified, choose an
1656 * appropriate one according to the given multicast address.
1657 */
1658 if (mreq->ipv6mr_interface == 0) {
1659 /*
1660 * If the multicast address is in node-local scope,
1661 * the interface should be a loopback interface.
1662 * Otherwise, look up the routing table for the
1663 * address, and choose the outgoing interface.
1664 * XXX: is it a good approach?
1665 */
1666 if (IN6_IS_ADDR_MC_NODELOCAL(&mreq->ipv6mr_multiaddr)) {
1667 ifp = &loif[0];
1668 }
1669 else {
1670 ro.ro_rt = NULL;
1671 dst = (struct sockaddr_in6 *)&ro.ro_dst;
1672 bzero(dst, sizeof(*dst));
1673 dst->sin6_len = sizeof(struct sockaddr_in6);
1674 dst->sin6_family = AF_INET6;
1675 dst->sin6_addr = mreq->ipv6mr_multiaddr;
1676 rtalloc((struct route *)&ro);
1677 if (ro.ro_rt == NULL) {
1678 error = EADDRNOTAVAIL;
1679 break;
1680 }
1681 ifp = ro.ro_rt->rt_ifp;
1682 rtfree(ro.ro_rt);
1683 }
1684 } else
1685 ifp = ifindex2ifnet[mreq->ipv6mr_interface];
1686
1687 /*
1688 * See if we found an interface, and confirm that it
1689 * supports multicast
1690 */
1691 if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
1692 error = EADDRNOTAVAIL;
1693 break;
1694 }
1695 /*
1696 * Put interface index into the multicast address,
1697 * if the address has link-local scope.
1698 */
1699 if (IN6_IS_ADDR_MC_LINKLOCAL(&mreq->ipv6mr_multiaddr)) {
1700 mreq->ipv6mr_multiaddr.s6_addr16[1]
1701 = htons(mreq->ipv6mr_interface);
1702 }
1703 /*
1704 * See if the membership already exists.
1705 */
1706 for (imm = im6o->im6o_memberships.lh_first;
1707 imm != NULL; imm = imm->i6mm_chain.le_next)
1708 if (imm->i6mm_maddr->in6m_ifp == ifp &&
1709 IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr,
1710 &mreq->ipv6mr_multiaddr))
1711 break;
1712 if (imm != NULL) {
1713 error = EADDRINUSE;
1714 break;
1715 }
1716 /*
1717 * Everything looks good; add a new record to the multicast
1718 * address list for the given interface.
1719 */
1720 imm = malloc(sizeof(*imm), M_IPMADDR, M_WAITOK);
1721 if (imm == NULL) {
1722 error = ENOBUFS;
1723 break;
1724 }
1725 if ((imm->i6mm_maddr =
1726 in6_addmulti(&mreq->ipv6mr_multiaddr, ifp, &error)) == NULL) {
1727 free(imm, M_IPMADDR);
1728 break;
1729 }
1730 LIST_INSERT_HEAD(&im6o->im6o_memberships, imm, i6mm_chain);
1731 break;
1732
1733 case IPV6_LEAVE_GROUP:
1734 /*
1735 * Drop a multicast group membership.
1736 * Group must be a valid IP6 multicast address.
1737 */
1738 if (m == NULL || m->m_len != sizeof(struct ipv6_mreq)) {
1739 error = EINVAL;
1740 break;
1741 }
1742 mreq = mtod(m, struct ipv6_mreq *);
1743 if (IN6_IS_ADDR_UNSPECIFIED(&mreq->ipv6mr_multiaddr)) {
1744 if (suser(p->p_ucred, &p->p_acflag)) {
1745 error = EACCES;
1746 break;
1747 }
1748 } else if (!IN6_IS_ADDR_MULTICAST(&mreq->ipv6mr_multiaddr)) {
1749 error = EINVAL;
1750 break;
1751 }
1752 /*
1753 * If an interface address was specified, get a pointer
1754 * to its ifnet structure.
1755 */
1756 if (mreq->ipv6mr_interface < 0
1757 || if_index < mreq->ipv6mr_interface) {
1758 error = ENXIO; /* XXX EINVAL? */
1759 break;
1760 }
1761 ifp = ifindex2ifnet[mreq->ipv6mr_interface];
1762 /*
1763 * Put interface index into the multicast address,
1764 * if the address has link-local scope.
1765 */
1766 if (IN6_IS_ADDR_MC_LINKLOCAL(&mreq->ipv6mr_multiaddr)) {
1767 mreq->ipv6mr_multiaddr.s6_addr16[1]
1768 = htons(mreq->ipv6mr_interface);
1769 }
1770 /*
1771 * Find the membership in the membership list.
1772 */
1773 for (imm = im6o->im6o_memberships.lh_first;
1774 imm != NULL; imm = imm->i6mm_chain.le_next) {
1775 if ((ifp == NULL ||
1776 imm->i6mm_maddr->in6m_ifp == ifp) &&
1777 IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr,
1778 &mreq->ipv6mr_multiaddr))
1779 break;
1780 }
1781 if (imm == NULL) {
1782 /* Unable to resolve interface */
1783 error = EADDRNOTAVAIL;
1784 break;
1785 }
1786 /*
1787 * Give up the multicast address record to which the
1788 * membership points.
1789 */
1790 LIST_REMOVE(imm, i6mm_chain);
1791 in6_delmulti(imm->i6mm_maddr);
1792 free(imm, M_IPMADDR);
1793 break;
1794
1795 default:
1796 error = EOPNOTSUPP;
1797 break;
1798 }
1799
1800 /*
1801 * If all options have default values, no need to keep the mbuf.
1802 */
1803 if (im6o->im6o_multicast_ifp == NULL &&
1804 im6o->im6o_multicast_hlim == ip6_defmcasthlim &&
1805 im6o->im6o_multicast_loop == IPV6_DEFAULT_MULTICAST_LOOP &&
1806 im6o->im6o_memberships.lh_first == NULL) {
1807 free(*im6op, M_IPMOPTS);
1808 *im6op = NULL;
1809 }
1810
1811 return(error);
1812 }
1813
1814 /*
1815 * Return the IP6 multicast options in response to user getsockopt().
1816 */
1817 static int
1818 ip6_getmoptions(optname, im6o, mp)
1819 int optname;
1820 register struct ip6_moptions *im6o;
1821 register struct mbuf **mp;
1822 {
1823 u_int *hlim, *loop, *ifindex;
1824
1825 *mp = m_get(M_WAIT, MT_SOOPTS);
1826
1827 switch (optname) {
1828
1829 case IPV6_MULTICAST_IF:
1830 ifindex = mtod(*mp, u_int *);
1831 (*mp)->m_len = sizeof(u_int);
1832 if (im6o == NULL || im6o->im6o_multicast_ifp == NULL)
1833 *ifindex = 0;
1834 else
1835 *ifindex = im6o->im6o_multicast_ifp->if_index;
1836 return(0);
1837
1838 case IPV6_MULTICAST_HOPS:
1839 hlim = mtod(*mp, u_int *);
1840 (*mp)->m_len = sizeof(u_int);
1841 if (im6o == NULL)
1842 *hlim = ip6_defmcasthlim;
1843 else
1844 *hlim = im6o->im6o_multicast_hlim;
1845 return(0);
1846
1847 case IPV6_MULTICAST_LOOP:
1848 loop = mtod(*mp, u_int *);
1849 (*mp)->m_len = sizeof(u_int);
1850 if (im6o == NULL)
1851 *loop = ip6_defmcasthlim;
1852 else
1853 *loop = im6o->im6o_multicast_loop;
1854 return(0);
1855
1856 default:
1857 return(EOPNOTSUPP);
1858 }
1859 }
1860
1861 /*
1862 * Discard the IP6 multicast options.
1863 */
1864 void
1865 ip6_freemoptions(im6o)
1866 register struct ip6_moptions *im6o;
1867 {
1868 struct in6_multi_mship *imm;
1869
1870 if (im6o == NULL)
1871 return;
1872
1873 while ((imm = im6o->im6o_memberships.lh_first) != NULL) {
1874 LIST_REMOVE(imm, i6mm_chain);
1875 if (imm->i6mm_maddr)
1876 in6_delmulti(imm->i6mm_maddr);
1877 free(imm, M_IPMADDR);
1878 }
1879 free(im6o, M_IPMOPTS);
1880 }
1881
1882 /*
1883 * Set IPv6 outgoing packet options based on advanced API.
1884 */
1885 int
1886 ip6_setpktoptions(control, opt, priv)
1887 struct mbuf *control;
1888 struct ip6_pktopts *opt;
1889 int priv;
1890 {
1891 register struct cmsghdr *cm = 0;
1892
1893 if (control == 0 || opt == 0)
1894 return(EINVAL);
1895
1896 bzero(opt, sizeof(*opt));
1897 opt->ip6po_hlim = -1; /* -1 means to use default hop limit */
1898
1899 /*
1900 * XXX: Currently, we assume all the optional information is stored
1901 * in a single mbuf.
1902 */
1903 if (control->m_next)
1904 return(EINVAL);
1905
1906 opt->ip6po_m = control;
1907
1908 for (; control->m_len; control->m_data += CMSG_ALIGN(cm->cmsg_len),
1909 control->m_len -= CMSG_ALIGN(cm->cmsg_len)) {
1910 cm = mtod(control, struct cmsghdr *);
1911 if (cm->cmsg_len == 0 || cm->cmsg_len > control->m_len)
1912 return(EINVAL);
1913 if (cm->cmsg_level != IPPROTO_IPV6)
1914 continue;
1915
1916 switch(cm->cmsg_type) {
1917 case IPV6_PKTINFO:
1918 if (cm->cmsg_len != CMSG_LEN(sizeof(struct in6_pktinfo)))
1919 return(EINVAL);
1920 opt->ip6po_pktinfo = (struct in6_pktinfo *)CMSG_DATA(cm);
1921 if (opt->ip6po_pktinfo->ipi6_ifindex &&
1922 IN6_IS_ADDR_LINKLOCAL(&opt->ip6po_pktinfo->ipi6_addr))
1923 opt->ip6po_pktinfo->ipi6_addr.s6_addr16[1] =
1924 htons(opt->ip6po_pktinfo->ipi6_ifindex);
1925
1926 if (opt->ip6po_pktinfo->ipi6_ifindex > if_index
1927 || opt->ip6po_pktinfo->ipi6_ifindex < 0) {
1928 return(ENXIO);
1929 }
1930
1931 if (!IN6_IS_ADDR_UNSPECIFIED(&opt->ip6po_pktinfo->ipi6_addr)) {
1932 struct ifaddr *ia;
1933 struct sockaddr_in6 sin6;
1934
1935 bzero(&sin6, sizeof(sin6));
1936 sin6.sin6_len = sizeof(sin6);
1937 sin6.sin6_family = AF_INET6;
1938 sin6.sin6_addr =
1939 opt->ip6po_pktinfo->ipi6_addr;
1940 ia = ifa_ifwithaddr(sin6tosa(&sin6));
1941 if (ia == NULL ||
1942 (opt->ip6po_pktinfo->ipi6_ifindex &&
1943 (ia->ifa_ifp->if_index !=
1944 opt->ip6po_pktinfo->ipi6_ifindex))) {
1945 return(EADDRNOTAVAIL);
1946 }
1947 /*
1948 * Check if the requested source address is
1949 * indeed a unicast address assigned to the
1950 * node.
1951 */
1952 if (IN6_IS_ADDR_MULTICAST(&opt->ip6po_pktinfo->ipi6_addr))
1953 return(EADDRNOTAVAIL);
1954 }
1955 break;
1956
1957 case IPV6_HOPLIMIT:
1958 if (cm->cmsg_len != CMSG_LEN(sizeof(int)))
1959 return(EINVAL);
1960
1961 opt->ip6po_hlim = *(int *)CMSG_DATA(cm);
1962 if (opt->ip6po_hlim < -1 || opt->ip6po_hlim > 255)
1963 return(EINVAL);
1964 break;
1965
1966 case IPV6_NEXTHOP:
1967 if (!priv)
1968 return(EPERM);
1969 if (cm->cmsg_len < sizeof(u_char) ||
1970 cm->cmsg_len < CMSG_LEN(*CMSG_DATA(cm)))
1971 return(EINVAL);
1972
1973 opt->ip6po_nexthop = (struct sockaddr *)CMSG_DATA(cm);
1974
1975 break;
1976
1977 case IPV6_HOPOPTS:
1978 if (cm->cmsg_len < CMSG_LEN(sizeof(struct ip6_hbh)))
1979 return(EINVAL);
1980 opt->ip6po_hbh = (struct ip6_hbh *)CMSG_DATA(cm);
1981 if (cm->cmsg_len !=
1982 CMSG_LEN((opt->ip6po_hbh->ip6h_len + 1) << 3))
1983 return(EINVAL);
1984 break;
1985
1986 case IPV6_DSTOPTS:
1987 if (cm->cmsg_len < CMSG_LEN(sizeof(struct ip6_dest)))
1988 return(EINVAL);
1989
1990 /*
1991 * If there is no routing header yet, the destination
1992 * options header should be put on the 1st part.
1993 * Otherwise, the header should be on the 2nd part.
1994 * (See RFC 2460, section 4.1)
1995 */
1996 if (opt->ip6po_rthdr == NULL) {
1997 opt->ip6po_dest1 =
1998 (struct ip6_dest *)CMSG_DATA(cm);
1999 if (cm->cmsg_len !=
2000 CMSG_LEN((opt->ip6po_dest1->ip6d_len + 1)
2001 << 3))
2002 return(EINVAL);
2003 }
2004 else {
2005 opt->ip6po_dest2 =
2006 (struct ip6_dest *)CMSG_DATA(cm);
2007 if (cm->cmsg_len !=
2008 CMSG_LEN((opt->ip6po_dest2->ip6d_len + 1)
2009 << 3))
2010 return(EINVAL);
2011 }
2012 break;
2013
2014 case IPV6_RTHDR:
2015 if (cm->cmsg_len < CMSG_LEN(sizeof(struct ip6_rthdr)))
2016 return(EINVAL);
2017 opt->ip6po_rthdr = (struct ip6_rthdr *)CMSG_DATA(cm);
2018 if (cm->cmsg_len !=
2019 CMSG_LEN((opt->ip6po_rthdr->ip6r_len + 1) << 3))
2020 return(EINVAL);
2021 switch(opt->ip6po_rthdr->ip6r_type) {
2022 case IPV6_RTHDR_TYPE_0:
2023 if (opt->ip6po_rthdr->ip6r_segleft == 0)
2024 return(EINVAL);
2025 break;
2026 default:
2027 return(EINVAL);
2028 }
2029 break;
2030
2031 default:
2032 return(ENOPROTOOPT);
2033 }
2034 }
2035
2036 return(0);
2037 }
2038
2039 /*
2040 * Routine called from ip6_output() to loop back a copy of an IP6 multicast
2041 * packet to the input queue of a specified interface. Note that this
2042 * calls the output routine of the loopback "driver", but with an interface
2043 * pointer that might NOT be &loif -- easier than replicating that code here.
2044 */
2045 void
2046 ip6_mloopback(ifp, m, dst)
2047 struct ifnet *ifp;
2048 register struct mbuf *m;
2049 register struct sockaddr_in6 *dst;
2050 {
2051 struct mbuf *copym;
2052
2053 copym = m_copy(m, 0, M_COPYALL);
2054 if (copym != NULL)
2055 (void)looutput(ifp, copym, (struct sockaddr *)dst, NULL);
2056 }
2057
2058 /*
2059 * Chop IPv6 header off from the payload.
2060 */
2061 static int
2062 ip6_splithdr(m, exthdrs)
2063 struct mbuf *m;
2064 struct ip6_exthdrs *exthdrs;
2065 {
2066 struct mbuf *mh;
2067 struct ip6_hdr *ip6;
2068
2069 ip6 = mtod(m, struct ip6_hdr *);
2070 if (m->m_len > sizeof(*ip6)) {
2071 MGETHDR(mh, M_DONTWAIT, MT_HEADER);
2072 if (mh == 0) {
2073 m_freem(m);
2074 return ENOBUFS;
2075 }
2076 M_COPY_PKTHDR(mh, m);
2077 MH_ALIGN(mh, sizeof(*ip6));
2078 m->m_flags &= ~M_PKTHDR;
2079 m->m_len -= sizeof(*ip6);
2080 m->m_data += sizeof(*ip6);
2081 mh->m_next = m;
2082 m = mh;
2083 m->m_len = sizeof(*ip6);
2084 bcopy((caddr_t)ip6, mtod(m, caddr_t), sizeof(*ip6));
2085 }
2086 exthdrs->ip6e_ip6 = m;
2087 return 0;
2088 }
2089
2090 /*
2091 * Compute IPv6 extension header length.
2092 */
2093 int
2094 ip6_optlen(in6p)
2095 struct in6pcb *in6p;
2096 {
2097 int len;
2098
2099 if (!in6p->in6p_outputopts)
2100 return 0;
2101
2102 len = 0;
2103 #define elen(x) \
2104 (((struct ip6_ext *)(x)) ? (((struct ip6_ext *)(x))->ip6e_len + 1) << 3 : 0)
2105
2106 len += elen(in6p->in6p_outputopts->ip6po_hbh);
2107 len += elen(in6p->in6p_outputopts->ip6po_dest1);
2108 len += elen(in6p->in6p_outputopts->ip6po_rthdr);
2109 len += elen(in6p->in6p_outputopts->ip6po_dest2);
2110 return len;
2111 #undef elen
2112 }
2113