]> git.saurik.com Git - apple/xnu.git/blob - bsd/netinet6/ip6_output.c
xnu-1699.24.23.tar.gz
[apple/xnu.git] / bsd / netinet6 / ip6_output.c
1 /*
2 * Copyright (c) 2000-2011 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 /* $FreeBSD: src/sys/netinet6/ip6_output.c,v 1.43 2002/10/31 19:45:48 ume Exp $ */
30 /* $KAME: ip6_output.c,v 1.279 2002/01/26 06:12:30 jinmei Exp $ */
31
32 /*
33 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
34 * 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. Neither the name of the project nor the names of its contributors
45 * may be used to endorse or promote products derived from this software
46 * without specific prior written permission.
47 *
48 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
49 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
51 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
52 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
53 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
54 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
55 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
56 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
57 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
58 * SUCH DAMAGE.
59 */
60
61 /*
62 * Copyright (c) 1982, 1986, 1988, 1990, 1993
63 * The Regents of the University of California. All rights reserved.
64 *
65 * Redistribution and use in source and binary forms, with or without
66 * modification, are permitted provided that the following conditions
67 * are met:
68 * 1. Redistributions of source code must retain the above copyright
69 * notice, this list of conditions and the following disclaimer.
70 * 2. Redistributions in binary form must reproduce the above copyright
71 * notice, this list of conditions and the following disclaimer in the
72 * documentation and/or other materials provided with the distribution.
73 * 3. All advertising materials mentioning features or use of this software
74 * must display the following acknowledgement:
75 * This product includes software developed by the University of
76 * California, Berkeley and its contributors.
77 * 4. Neither the name of the University nor the names of its contributors
78 * may be used to endorse or promote products derived from this software
79 * without specific prior written permission.
80 *
81 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
82 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
83 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
84 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
85 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
86 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
87 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
88 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
89 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
90 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
91 * SUCH DAMAGE.
92 *
93 * @(#)ip_output.c 8.3 (Berkeley) 1/21/94
94 */
95 /*
96 * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce
97 * support for mandatory and extensible security protections. This notice
98 * is included in support of clause 2.2 (b) of the Apple Public License,
99 * Version 2.0.
100 */
101
102 #include <sys/param.h>
103 #include <sys/malloc.h>
104 #include <sys/mbuf.h>
105 #include <sys/errno.h>
106 #include <sys/protosw.h>
107 #include <sys/socket.h>
108 #include <sys/socketvar.h>
109 #include <sys/systm.h>
110 #include <sys/kernel.h>
111 #include <sys/proc.h>
112 #include <sys/kauth.h>
113 #include <sys/mcache.h>
114 #include <sys/sysctl.h>
115 #include <kern/zalloc.h>
116
117 #include <pexpert/pexpert.h>
118
119 #include <net/if.h>
120 #include <net/route.h>
121 #include <net/dlil.h>
122
123 #include <netinet/in.h>
124 #include <netinet/in_var.h>
125 #include <netinet/ip_var.h>
126 #include <netinet6/in6_var.h>
127 #include <netinet/ip6.h>
128 #include <netinet6/ip6protosw.h>
129 #include <netinet/icmp6.h>
130 #include <netinet6/ip6_var.h>
131 #include <netinet/in_pcb.h>
132 #include <netinet6/nd6.h>
133 #include <netinet6/scope6_var.h>
134 #include <mach/sdt.h>
135
136 #if IPSEC
137 #include <netinet6/ipsec.h>
138 #if INET6
139 #include <netinet6/ipsec6.h>
140 #endif
141 #include <netkey/key.h>
142 extern int ipsec_bypass;
143 #endif /* IPSEC */
144
145 #if CONFIG_MACF_NET
146 #include <security/mac.h>
147 #endif /* MAC_NET */
148
149 #include <netinet6/ip6_fw.h>
150
151 #include <net/net_osdep.h>
152
153 #include <netinet/kpi_ipfilter_var.h>
154
155 #if PF
156 #include <net/pfvar.h>
157 #endif /* PF */
158
159 #ifndef __APPLE__
160 static MALLOC_DEFINE(M_IPMOPTS, "ip6_moptions", "internet multicast options");
161 #endif
162
163 struct ip6_exthdrs {
164 struct mbuf *ip6e_ip6;
165 struct mbuf *ip6e_hbh;
166 struct mbuf *ip6e_dest1;
167 struct mbuf *ip6e_rthdr;
168 struct mbuf *ip6e_dest2;
169 };
170
171 int ip6_raw_ctloutput(struct socket *so, struct sockopt *sopt);
172 static int ip6_pcbopts(struct ip6_pktopts **, struct mbuf *,
173 struct socket *, struct sockopt *sopt);
174 static int ip6_pcbopt(int optname, u_char *buf, int len, struct ip6_pktopts **pktopt, int uproto);
175 static int ip6_getpcbopt(struct ip6_pktopts *pktopt, int optname, struct sockopt *sopt);
176 static int ip6_setpktopt(int optname, u_char *buf, int len, struct ip6_pktopts *opt, int sticky, int cmsg, int uproto);
177 static void im6o_trace(struct ip6_moptions *, int);
178 static int ip6_copyexthdr(struct mbuf **, caddr_t, int);
179 static int ip6_insertfraghdr(struct mbuf *, struct mbuf *, int,
180 struct ip6_frag **);
181 static int ip6_insert_jumboopt(struct ip6_exthdrs *, u_int32_t);
182 static int ip6_splithdr(struct mbuf *, struct ip6_exthdrs *);
183 static int ip6_getpmtu (struct route_in6 *, struct route_in6 *,
184 struct ifnet *, struct in6_addr *, u_int32_t *, int *);
185
186 #define IM6O_TRACE_HIST_SIZE 32 /* size of trace history */
187
188 /* For gdb */
189 __private_extern__ unsigned int im6o_trace_hist_size = IM6O_TRACE_HIST_SIZE;
190
191 struct ip6_moptions_dbg {
192 struct ip6_moptions im6o; /* ip6_moptions */
193 u_int16_t im6o_refhold_cnt; /* # of IM6O_ADDREF */
194 u_int16_t im6o_refrele_cnt; /* # of IM6O_REMREF */
195 /*
196 * Alloc and free callers.
197 */
198 ctrace_t im6o_alloc;
199 ctrace_t im6o_free;
200 /*
201 * Circular lists of IM6O_ADDREF and IM6O_REMREF callers.
202 */
203 ctrace_t im6o_refhold[IM6O_TRACE_HIST_SIZE];
204 ctrace_t im6o_refrele[IM6O_TRACE_HIST_SIZE];
205 };
206
207 #if DEBUG
208 static unsigned int im6o_debug = 1; /* debugging (enabled) */
209 #else
210 static unsigned int im6o_debug; /* debugging (disabled) */
211 #endif /* !DEBUG */
212
213 static unsigned int im6o_size; /* size of zone element */
214 static struct zone *im6o_zone; /* zone for ip6_moptions */
215
216 #define IM6O_ZONE_MAX 64 /* maximum elements in zone */
217 #define IM6O_ZONE_NAME "ip6_moptions" /* zone name */
218
219
220 /*
221 * IP6 output. The packet in mbuf chain m contains a skeletal IP6
222 * header (with pri, len, nxt, hlim, src, dst).
223 * This function may modify ver and hlim only.
224 * The mbuf chain containing the packet will be freed.
225 * The mbuf opt, if present, will not be freed.
226 *
227 * type of "mtu": rt_rmx.rmx_mtu is u_int32_t, ifnet.ifr_mtu is int, and
228 * nd_ifinfo.linkmtu is u_int32_t. so we use u_int32_t to hold largest one,
229 * which is rt_rmx.rmx_mtu.
230 */
231 int
232 ip6_output(
233 struct mbuf *m0,
234 struct ip6_pktopts *opt,
235 struct route_in6 *ro,
236 int flags,
237 struct ip6_moptions *im6o,
238 struct ifnet **ifpp, /* XXX: just for statistics */
239 struct ip6_out_args *ip6oa)
240 {
241 struct ip6_hdr *ip6, *mhip6;
242 struct ifnet *ifp = NULL, *origifp = NULL;
243 struct mbuf *m = m0;
244 int hlen, tlen, len, off;
245 struct route_in6 ip6route;
246 struct rtentry *rt = NULL;
247 struct sockaddr_in6 *dst, src_sa, dst_sa;
248 int error = 0;
249 struct in6_ifaddr *ia = NULL;
250 u_int32_t mtu;
251 int alwaysfrag = 0, dontfrag = 0;
252 u_int32_t optlen = 0, plen = 0, unfragpartlen = 0;
253 struct ip6_exthdrs exthdrs;
254 struct in6_addr finaldst, src0, dst0;
255 u_int32_t zone;
256 struct route_in6 *ro_pmtu = NULL;
257 int hdrsplit = 0;
258 int needipsec = 0;
259 ipfilter_t inject_filter_ref;
260 int tso;
261 unsigned int ifscope;
262 unsigned int nocell;
263 boolean_t select_srcif;
264 struct ipf_pktopts *ippo = NULL, ipf_pktopts;
265 u_int32_t ifmtu;
266
267 #if IPSEC
268 int needipsectun = 0;
269 struct socket *so = NULL;
270 struct secpolicy *sp = NULL;
271 struct route_in6 *ipsec_saved_route = NULL;
272 struct ipsec_output_state ipsec_state;
273
274 bzero(&ipsec_state, sizeof(ipsec_state));
275
276 /* for AH processing. stupid to have "socket" variable in IP layer... */
277 if (ipsec_bypass == 0)
278 {
279 so = ipsec_getsocket(m);
280 (void)ipsec_setsocket(m, NULL);
281 }
282 #endif /* IPSEC */
283
284 bzero(&ipf_pktopts, sizeof(struct ipf_pktopts));
285 ippo = &ipf_pktopts;
286
287 ip6 = mtod(m, struct ip6_hdr *);
288 inject_filter_ref = ipf_get_inject_filter(m);
289
290 finaldst = ip6->ip6_dst;
291
292 if (ip6_doscopedroute && (flags & IPV6_OUTARGS)) {
293 select_srcif = !(flags & (IPV6_FORWARDING | IPV6_UNSPECSRC | IPV6_FLAG_NOSRCIFSEL));
294 ifscope = ip6oa->ip6oa_boundif;
295 ipf_pktopts.ippo_flags = IPPOF_BOUND_IF;
296 ipf_pktopts.ippo_flags |= (ifscope << IPPOF_SHIFT_IFSCOPE);
297 } else {
298 select_srcif = FALSE;
299 ifscope = IFSCOPE_NONE;
300 }
301
302 if (flags & IPV6_OUTARGS) {
303 nocell = ip6oa->ip6oa_nocell;
304 if (nocell)
305 ipf_pktopts.ippo_flags |= IPPOF_NO_IFT_CELLULAR;
306 } else {
307 nocell = 0;
308 }
309
310 #define MAKE_EXTHDR(hp, mp) \
311 do { \
312 if (hp) { \
313 struct ip6_ext *eh = (struct ip6_ext *)(hp); \
314 error = ip6_copyexthdr((mp), (caddr_t)(hp), \
315 ((eh)->ip6e_len + 1) << 3); \
316 if (error) \
317 goto freehdrs; \
318 } \
319 } while (0)
320
321 bzero(&exthdrs, sizeof(exthdrs));
322
323 if (opt) {
324 /* Hop-by-Hop options header */
325 MAKE_EXTHDR(opt->ip6po_hbh, &exthdrs.ip6e_hbh);
326 /* Destination options header(1st part) */
327 if (opt->ip6po_rthdr) {
328 /*
329 * Destination options header(1st part)
330 * This only makes sense with a routing header.
331 * See Section 9.2 of RFC 3542.
332 * Disabling this part just for MIP6 convenience is
333 * a bad idea. We need to think carefully about a
334 * way to make the advanced API coexist with MIP6
335 * options, which might automatically be inserted in
336 * the kernel.
337 */
338 MAKE_EXTHDR(opt->ip6po_dest1, &exthdrs.ip6e_dest1);
339 }
340 /* Routing header */
341 MAKE_EXTHDR(opt->ip6po_rthdr, &exthdrs.ip6e_rthdr);
342 /* Destination options header(2nd part) */
343 MAKE_EXTHDR(opt->ip6po_dest2, &exthdrs.ip6e_dest2);
344 }
345
346 #if IPSEC
347 if (ipsec_bypass != 0)
348 goto skip_ipsec;
349
350 /* get a security policy for this packet */
351 if (so == NULL)
352 sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, 0, &error);
353 else
354 sp = ipsec6_getpolicybysock(m, IPSEC_DIR_OUTBOUND, so, &error);
355
356 if (sp == NULL) {
357 IPSEC_STAT_INCREMENT(ipsec6stat.out_inval);
358 goto freehdrs;
359 }
360
361 error = 0;
362
363 /* check policy */
364 switch (sp->policy) {
365 case IPSEC_POLICY_DISCARD:
366 case IPSEC_POLICY_GENERATE:
367 /*
368 * This packet is just discarded.
369 */
370 IPSEC_STAT_INCREMENT(ipsec6stat.out_polvio);
371 goto freehdrs;
372
373 case IPSEC_POLICY_BYPASS:
374 case IPSEC_POLICY_NONE:
375 /* no need to do IPsec. */
376 needipsec = 0;
377 break;
378
379 case IPSEC_POLICY_IPSEC:
380 if (sp->req == NULL) {
381 /* acquire a policy */
382 error = key_spdacquire(sp);
383 goto freehdrs;
384 }
385 needipsec = 1;
386 break;
387
388 case IPSEC_POLICY_ENTRUST:
389 default:
390 printf("ip6_output: Invalid policy found. %d\n", sp->policy);
391 }
392 skip_ipsec:
393 #endif /* IPSEC */
394
395 /*
396 * Calculate the total length of the extension header chain.
397 * Keep the length of the unfragmentable part for fragmentation.
398 */
399 optlen = 0;
400 if (exthdrs.ip6e_hbh)
401 optlen += exthdrs.ip6e_hbh->m_len;
402 if (exthdrs.ip6e_dest1)
403 optlen += exthdrs.ip6e_dest1->m_len;
404 if (exthdrs.ip6e_rthdr)
405 optlen += exthdrs.ip6e_rthdr->m_len;
406 unfragpartlen = optlen + sizeof(struct ip6_hdr);
407
408 /* NOTE: we don't add AH/ESP length here. do that later. */
409 if (exthdrs.ip6e_dest2)
410 optlen += exthdrs.ip6e_dest2->m_len;
411
412
413 if (needipsec &&
414 (m->m_pkthdr.csum_flags & CSUM_DELAY_IPV6_DATA) != 0) {
415 in6_delayed_cksum(m, sizeof(struct ip6_hdr) + optlen);
416 m->m_pkthdr.csum_flags &= ~CSUM_DELAY_IPV6_DATA;
417 }
418
419 /*
420 * If we need IPsec, or there is at least one extension header,
421 * separate IP6 header from the payload.
422 */
423 if ((needipsec || optlen) && !hdrsplit) {
424 if ((error = ip6_splithdr(m, &exthdrs)) != 0) {
425 m = NULL;
426 goto freehdrs;
427 }
428 m = exthdrs.ip6e_ip6;
429 hdrsplit++;
430 }
431
432 /* adjust pointer */
433 ip6 = mtod(m, struct ip6_hdr *);
434
435 /* adjust mbuf packet header length */
436 m->m_pkthdr.len += optlen;
437 plen = m->m_pkthdr.len - sizeof(*ip6);
438
439 /* If this is a jumbo payload, insert a jumbo payload option. */
440 if (plen > IPV6_MAXPACKET) {
441 if (!hdrsplit) {
442 if ((error = ip6_splithdr(m, &exthdrs)) != 0) {
443 m = NULL;
444 goto freehdrs;
445 }
446 m = exthdrs.ip6e_ip6;
447 hdrsplit++;
448 }
449 /* adjust pointer */
450 ip6 = mtod(m, struct ip6_hdr *);
451 if ((error = ip6_insert_jumboopt(&exthdrs, plen)) != 0)
452 goto freehdrs;
453 ip6->ip6_plen = 0;
454 } else
455 ip6->ip6_plen = htons(plen);
456
457 /*
458 * Concatenate headers and fill in next header fields.
459 * Here we have, on "m"
460 * IPv6 payload
461 * and we insert headers accordingly. Finally, we should be getting:
462 * IPv6 hbh dest1 rthdr ah* [esp* dest2 payload]
463 *
464 * during the header composing process, "m" points to IPv6 header.
465 * "mprev" points to an extension header prior to esp.
466 */
467 {
468 u_char *nexthdrp = &ip6->ip6_nxt;
469 struct mbuf *mprev = m;
470
471 /*
472 * we treat dest2 specially. this makes IPsec processing
473 * much easier. the goal here is to make mprev point the
474 * mbuf prior to dest2.
475 *
476 * result: IPv6 dest2 payload
477 * m and mprev will point to IPv6 header.
478 */
479 if (exthdrs.ip6e_dest2) {
480 if (!hdrsplit)
481 panic("assumption failed: hdr not split");
482 exthdrs.ip6e_dest2->m_next = m->m_next;
483 m->m_next = exthdrs.ip6e_dest2;
484 *mtod(exthdrs.ip6e_dest2, u_char *) = ip6->ip6_nxt;
485 ip6->ip6_nxt = IPPROTO_DSTOPTS;
486 }
487
488 #define MAKE_CHAIN(m, mp, p, i)\
489 do {\
490 if (m) {\
491 if (!hdrsplit) \
492 panic("assumption failed: hdr not split"); \
493 *mtod((m), u_char *) = *(p);\
494 *(p) = (i);\
495 p = mtod((m), u_char *);\
496 (m)->m_next = (mp)->m_next;\
497 (mp)->m_next = (m);\
498 (mp) = (m);\
499 }\
500 } while (0)
501 /*
502 * result: IPv6 hbh dest1 rthdr dest2 payload
503 * m will point to IPv6 header. mprev will point to the
504 * extension header prior to dest2 (rthdr in the above case).
505 */
506 MAKE_CHAIN(exthdrs.ip6e_hbh, mprev,
507 nexthdrp, IPPROTO_HOPOPTS);
508 MAKE_CHAIN(exthdrs.ip6e_dest1, mprev,
509 nexthdrp, IPPROTO_DSTOPTS);
510 MAKE_CHAIN(exthdrs.ip6e_rthdr, mprev,
511 nexthdrp, IPPROTO_ROUTING);
512
513 if (!TAILQ_EMPTY(&ipv6_filters)) {
514 struct ipfilter *filter;
515 int seen = (inject_filter_ref == 0);
516 int fixscope = 0;
517
518 if (im6o != NULL && IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
519 ippo->ippo_flags |= IPPOF_MCAST_OPTS;
520 IM6O_LOCK(im6o);
521 ippo->ippo_mcast_ifnet = im6o->im6o_multicast_ifp;
522 ippo->ippo_mcast_ttl = im6o->im6o_multicast_hlim;
523 ippo->ippo_mcast_loop = im6o->im6o_multicast_loop;
524 IM6O_UNLOCK(im6o);
525 }
526
527 /* Hack: embed the scope_id in the destination */
528 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst) &&
529 (ip6->ip6_dst.s6_addr16[1] == 0) && (ro != NULL)) {
530 fixscope = 1;
531 ip6->ip6_dst.s6_addr16[1] = htons(ro->ro_dst.sin6_scope_id);
532 }
533 {
534 ipf_ref();
535 TAILQ_FOREACH(filter, &ipv6_filters, ipf_link) {
536 /*
537 * No need to proccess packet twice if we've
538 * already seen it
539 */
540 if (seen == 0) {
541 if ((struct ipfilter *)inject_filter_ref == filter)
542 seen = 1;
543 } else if (filter->ipf_filter.ipf_output) {
544 errno_t result;
545
546 result = filter->ipf_filter.ipf_output(filter->ipf_filter.cookie, (mbuf_t*)&m, ippo);
547 if (result == EJUSTRETURN) {
548 ipf_unref();
549 goto done;
550 }
551 if (result != 0) {
552 ipf_unref();
553 goto bad;
554 }
555 }
556 }
557 ipf_unref();
558 }
559 ip6 = mtod(m, struct ip6_hdr *);
560 /* Hack: cleanup embedded scope_id if we put it there */
561 if (fixscope)
562 ip6->ip6_dst.s6_addr16[1] = 0;
563 }
564
565 #if IPSEC
566 if (!needipsec)
567 goto skip_ipsec2;
568
569 /*
570 * pointers after IPsec headers are not valid any more.
571 * other pointers need a great care too.
572 * (IPsec routines should not mangle mbufs prior to AH/ESP)
573 */
574 exthdrs.ip6e_dest2 = NULL;
575
576 {
577 struct ip6_rthdr *rh = NULL;
578 int segleft_org = 0;
579
580 if (exthdrs.ip6e_rthdr) {
581 rh = mtod(exthdrs.ip6e_rthdr, struct ip6_rthdr *);
582 segleft_org = rh->ip6r_segleft;
583 rh->ip6r_segleft = 0;
584 }
585
586 ipsec_state.m = m;
587 error = ipsec6_output_trans(&ipsec_state, nexthdrp, mprev, sp, flags,
588 &needipsectun);
589 m = ipsec_state.m;
590 if (error) {
591 /* mbuf is already reclaimed in ipsec6_output_trans. */
592 m = NULL;
593 switch (error) {
594 case EHOSTUNREACH:
595 case ENETUNREACH:
596 case EMSGSIZE:
597 case ENOBUFS:
598 case ENOMEM:
599 break;
600 default:
601 printf("ip6_output (ipsec): error code %d\n", error);
602 /* fall through */
603 case ENOENT:
604 /* don't show these error codes to the user */
605 error = 0;
606 break;
607 }
608 goto bad;
609 }
610 if (exthdrs.ip6e_rthdr) {
611 /* ah6_output doesn't modify mbuf chain */
612 rh->ip6r_segleft = segleft_org;
613 }
614 }
615 }
616 skip_ipsec2:
617 #endif
618
619 /*
620 * If there is a routing header, replace the destination address field
621 * with the first hop of the routing header.
622 */
623 if (exthdrs.ip6e_rthdr) {
624 struct ip6_rthdr *rh =
625 (struct ip6_rthdr *)(mtod(exthdrs.ip6e_rthdr,
626 struct ip6_rthdr *));
627 struct ip6_rthdr0 *rh0;
628 struct in6_addr *addr;
629 struct sockaddr_in6 sa;
630
631 switch (rh->ip6r_type) {
632 case IPV6_RTHDR_TYPE_0:
633 rh0 = (struct ip6_rthdr0 *)rh;
634 addr = (struct in6_addr *)(rh0 + 1);
635
636 /*
637 * construct a sockaddr_in6 form of
638 * the first hop.
639 *
640 * XXX: we may not have enough
641 * information about its scope zone;
642 * there is no standard API to pass
643 * the information from the
644 * application.
645 */
646 bzero(&sa, sizeof(sa));
647 sa.sin6_family = AF_INET6;
648 sa.sin6_len = sizeof(sa);
649 sa.sin6_addr = addr[0];
650 if ((error = sa6_embedscope(&sa,
651 ip6_use_defzone)) != 0) {
652 goto bad;
653 }
654 ip6->ip6_dst = sa.sin6_addr;
655 bcopy(&addr[1], &addr[0], sizeof(struct in6_addr)
656 * (rh0->ip6r0_segleft - 1));
657 addr[rh0->ip6r0_segleft - 1] = finaldst;
658 /* XXX */
659 in6_clearscope(addr + rh0->ip6r0_segleft - 1);
660 break;
661 default: /* is it possible? */
662 error = EINVAL;
663 goto bad;
664 }
665 }
666
667 /* Source address validation */
668 if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src) &&
669 (flags & IPV6_UNSPECSRC) == 0) {
670 error = EOPNOTSUPP;
671 ip6stat.ip6s_badscope++;
672 goto bad;
673 }
674 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src)) {
675 error = EOPNOTSUPP;
676 ip6stat.ip6s_badscope++;
677 goto bad;
678 }
679
680 ip6stat.ip6s_localout++;
681
682 /*
683 * Route packet.
684 */
685 if (ro == 0) {
686 ro = &ip6route;
687 bzero((caddr_t)ro, sizeof(*ro));
688 }
689 ro_pmtu = ro;
690 if (opt && opt->ip6po_rthdr)
691 ro = &opt->ip6po_route;
692 dst = (struct sockaddr_in6 *)&ro->ro_dst;
693
694 if (ro && ro->ro_rt)
695 RT_LOCK_ASSERT_NOTHELD(ro->ro_rt);
696 /*
697 * if specified, try to fill in the traffic class field.
698 * do not override if a non-zero value is already set.
699 * we check the diffserv field and the ecn field separately.
700 */
701 if (opt && opt->ip6po_tclass >= 0) {
702 int mask = 0;
703
704 if ((ip6->ip6_flow & htonl(0xfc << 20)) == 0)
705 mask |= 0xfc;
706 if ((ip6->ip6_flow & htonl(0x03 << 20)) == 0)
707 mask |= 0x03;
708 if (mask != 0)
709 ip6->ip6_flow |= htonl((opt->ip6po_tclass & mask) << 20);
710 }
711
712 /* fill in or override the hop limit field, if necessary. */
713 if (opt && opt->ip6po_hlim != -1)
714 ip6->ip6_hlim = opt->ip6po_hlim & 0xff;
715 else if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
716 if (im6o != NULL) {
717 IM6O_LOCK(im6o);
718 ip6->ip6_hlim = im6o->im6o_multicast_hlim;
719 IM6O_UNLOCK(im6o);
720 } else {
721 ip6->ip6_hlim = ip6_defmcasthlim;
722 }
723 }
724
725 /*
726 * If there is a cached route, check that it is to the same
727 * destination and is still up. If not, free it and try again.
728 * Test rt_flags without holding rt_lock for performance reasons;
729 * if the route is down it will hopefully be caught by the layer
730 * below (since it uses this route as a hint) or during the
731 * next transmit.
732 */
733 if (ro->ro_rt != NULL && (!(ro->ro_rt->rt_flags & RTF_UP) ||
734 dst->sin6_family != AF_INET6 ||
735 !IN6_ARE_ADDR_EQUAL(&dst->sin6_addr, &ip6->ip6_dst) ||
736 ro->ro_rt->generation_id != route_generation)) {
737 rtfree(ro->ro_rt);
738 ro->ro_rt = NULL;
739 }
740 if (ro->ro_rt == NULL) {
741 bzero(dst, sizeof(*dst));
742 dst->sin6_family = AF_INET6;
743 dst->sin6_len = sizeof(struct sockaddr_in6);
744 dst->sin6_addr = ip6->ip6_dst;
745 }
746
747 #if IPSEC
748 if (needipsec && needipsectun) {
749 #if CONFIG_DTRACE
750 struct ifnet *trace_ifp = (ifpp != NULL) ? (*ifpp) : NULL;
751 #endif /* CONFIG_DTRACE */
752 /*
753 * All the extension headers will become inaccessible
754 * (since they can be encrypted).
755 * Don't panic, we need no more updates to extension headers
756 * on inner IPv6 packet (since they are now encapsulated).
757 *
758 * IPv6 [ESP|AH] IPv6 [extension headers] payload
759 */
760 bzero(&exthdrs, sizeof(exthdrs));
761 exthdrs.ip6e_ip6 = m;
762
763 ipsec_state.m = m;
764 route_copyout(&ipsec_state.ro, (struct route *)ro, sizeof(ipsec_state.ro));
765 ipsec_state.dst = (struct sockaddr *)dst;
766
767 /* Added a trace here so that we can see packets inside a tunnel */
768 DTRACE_IP6(send, struct mbuf *, m, struct inpcb *, NULL,
769 struct ip6_hdr *, ip6, struct ifnet *, trace_ifp,
770 struct ip *, NULL, struct ip6_hdr *, ip6);
771
772 error = ipsec6_output_tunnel(&ipsec_state, sp, flags);
773 if (ipsec_state.tunneled == 4) /* tunneled in IPv4 - packet is gone */
774 goto done;
775 m = ipsec_state.m;
776 ipsec_saved_route = ro;
777 ro = (struct route_in6 *)&ipsec_state.ro;
778 dst = (struct sockaddr_in6 *)ipsec_state.dst;
779 if (error) {
780 /* mbuf is already reclaimed in ipsec6_output_tunnel. */
781 m0 = m = NULL;
782 m = NULL;
783 switch (error) {
784 case EHOSTUNREACH:
785 case ENETUNREACH:
786 case EMSGSIZE:
787 case ENOBUFS:
788 case ENOMEM:
789 break;
790 default:
791 printf("ip6_output (ipsec): error code %d\n", error);
792 /* fall through */
793 case ENOENT:
794 /* don't show these error codes to the user */
795 error = 0;
796 break;
797 }
798 goto bad;
799 }
800 /*
801 * The packet has been encapsulated so the ifscope is no longer valid
802 * since it does not apply to the outer address: ignore the ifscope.
803 */
804 ifscope = IFSCOPE_NONE;
805 if (opt != NULL && opt->ip6po_pktinfo != NULL) {
806 if (opt->ip6po_pktinfo->ipi6_ifindex != IFSCOPE_NONE)
807 opt->ip6po_pktinfo->ipi6_ifindex = IFSCOPE_NONE;
808 }
809 exthdrs.ip6e_ip6 = m;
810 }
811 #endif /* IPSEC */
812
813 /* for safety */
814 if (ifp != NULL) {
815 ifnet_release(ifp);
816 ifp = NULL;
817 }
818
819 /* adjust pointer */
820 ip6 = mtod(m, struct ip6_hdr *);
821
822 if (select_srcif) {
823 bzero(&src_sa, sizeof(src_sa));
824 src_sa.sin6_family = AF_INET6;
825 src_sa.sin6_len = sizeof(src_sa);
826 src_sa.sin6_addr = ip6->ip6_src;
827 }
828 bzero(&dst_sa, sizeof(dst_sa));
829 dst_sa.sin6_family = AF_INET6;
830 dst_sa.sin6_len = sizeof(dst_sa);
831 dst_sa.sin6_addr = ip6->ip6_dst;
832
833 if ((error = in6_selectroute(select_srcif ? &src_sa : NULL,
834 &dst_sa, opt, im6o, ro, &ifp, &rt, 0, ifscope, nocell)) != 0) {
835 switch (error) {
836 case EHOSTUNREACH:
837 ip6stat.ip6s_noroute++;
838 break;
839 case EADDRNOTAVAIL:
840 default:
841 break; /* XXX statistics? */
842 }
843 if (ifp != NULL)
844 in6_ifstat_inc(ifp, ifs6_out_discard);
845 goto bad;
846 }
847 if (rt == NULL) {
848 /*
849 * If in6_selectroute() does not return a route entry,
850 * dst may not have been updated.
851 */
852 *dst = dst_sa; /* XXX */
853 }
854
855 /*
856 * then rt (for unicast) and ifp must be non-NULL valid values.
857 */
858 if ((flags & IPV6_FORWARDING) == 0) {
859 /* XXX: the FORWARDING flag can be set for mrouting. */
860 in6_ifstat_inc(ifp, ifs6_out_request);
861 }
862 if (rt != NULL) {
863 RT_LOCK(rt);
864 ia = (struct in6_ifaddr *)(rt->rt_ifa);
865 if (ia != NULL)
866 IFA_ADDREF(&ia->ia_ifa);
867 rt->rt_use++;
868 RT_UNLOCK(rt);
869 }
870
871 /*
872 * The outgoing interface must be in the zone of source and
873 * destination addresses. We should use ia_ifp to support the
874 * case of sending packets to an address of our own.
875 */
876 if (ia != NULL && ia->ia_ifp) {
877 ifnet_reference(ia->ia_ifp);
878 if (origifp != NULL)
879 ifnet_release(origifp);
880 origifp = ia->ia_ifp;
881 } else {
882 if (ifp != NULL)
883 ifnet_reference(ifp);
884 if (origifp != NULL)
885 ifnet_release(origifp);
886 origifp = ifp;
887 }
888 src0 = ip6->ip6_src;
889 if (in6_setscope(&src0, origifp, &zone))
890 goto badscope;
891 bzero(&src_sa, sizeof(src_sa));
892 src_sa.sin6_family = AF_INET6;
893 src_sa.sin6_len = sizeof(src_sa);
894 src_sa.sin6_addr = ip6->ip6_src;
895 if (sa6_recoverscope(&src_sa) || zone != src_sa.sin6_scope_id)
896 goto badscope;
897
898 dst0 = ip6->ip6_dst;
899 if (in6_setscope(&dst0, origifp, &zone))
900 goto badscope;
901 /* re-initialize to be sure */
902 bzero(&dst_sa, sizeof(dst_sa));
903 dst_sa.sin6_family = AF_INET6;
904 dst_sa.sin6_len = sizeof(dst_sa);
905 dst_sa.sin6_addr = ip6->ip6_dst;
906 if (sa6_recoverscope(&dst_sa) || zone != dst_sa.sin6_scope_id) {
907 goto badscope;
908 }
909
910 /* scope check is done. */
911 goto routefound;
912
913 badscope:
914 ip6stat.ip6s_badscope++;
915 in6_ifstat_inc(origifp, ifs6_out_discard);
916 if (error == 0)
917 error = EHOSTUNREACH; /* XXX */
918 goto bad;
919
920 routefound:
921 if (rt && !IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
922 if (opt && opt->ip6po_nextroute.ro_rt) {
923 /*
924 * The nexthop is explicitly specified by the
925 * application. We assume the next hop is an IPv6
926 * address.
927 */
928 dst = (struct sockaddr_in6 *)opt->ip6po_nexthop;
929 }
930 else if ((rt->rt_flags & RTF_GATEWAY))
931 dst = (struct sockaddr_in6 *)rt->rt_gateway;
932 }
933
934 if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
935 m->m_flags &= ~(M_BCAST | M_MCAST); /* just in case */
936 } else {
937 struct in6_multi *in6m;
938
939 m->m_flags = (m->m_flags & ~M_BCAST) | M_MCAST;
940
941 in6_ifstat_inc(ifp, ifs6_out_mcast);
942
943 /*
944 * Confirm that the outgoing interface supports multicast.
945 */
946 if ((ifp->if_flags & IFF_MULTICAST) == 0) {
947 ip6stat.ip6s_noroute++;
948 in6_ifstat_inc(ifp, ifs6_out_discard);
949 error = ENETUNREACH;
950 goto bad;
951 }
952 in6_multihead_lock_shared();
953 IN6_LOOKUP_MULTI(&ip6->ip6_dst, ifp, in6m);
954 in6_multihead_lock_done();
955 if (im6o != NULL)
956 IM6O_LOCK(im6o);
957 if (in6m != NULL &&
958 (im6o == NULL || im6o->im6o_multicast_loop)) {
959 if (im6o != NULL)
960 IM6O_UNLOCK(im6o);
961 /*
962 * If we belong to the destination multicast group
963 * on the outgoing interface, and the caller did not
964 * forbid loopback, loop back a copy.
965 */
966 ip6_mloopback(ifp, m, dst);
967 } else {
968 if (im6o != NULL)
969 IM6O_UNLOCK(im6o);
970 /*
971 * If we are acting as a multicast router, perform
972 * multicast forwarding as if the packet had just
973 * arrived on the interface to which we are about
974 * to send. The multicast forwarding function
975 * recursively calls this function, using the
976 * IPV6_FORWARDING flag to prevent infinite recursion.
977 *
978 * Multicasts that are looped back by ip6_mloopback(),
979 * above, will be forwarded by the ip6_input() routine,
980 * if necessary.
981 */
982 #if MROUTING
983 if (ip6_mrouter && (flags & IPV6_FORWARDING) == 0) {
984 /*
985 * XXX: ip6_mforward expects that rcvif is NULL
986 * when it is called from the originating path.
987 * However, it is not always the case, since
988 * some versions of MGETHDR() does not
989 * initialize the field.
990 */
991 m->m_pkthdr.rcvif = NULL;
992 if (ip6_mforward(ip6, ifp, m) != 0) {
993 m_freem(m);
994 if (in6m != NULL)
995 IN6M_REMREF(in6m);
996 goto done;
997 }
998 }
999 #endif
1000 }
1001 if (in6m != NULL)
1002 IN6M_REMREF(in6m);
1003 /*
1004 * Multicasts with a hoplimit of zero may be looped back,
1005 * above, but must not be transmitted on a network.
1006 * Also, multicasts addressed to the loopback interface
1007 * are not sent -- the above call to ip6_mloopback() will
1008 * loop back a copy if this host actually belongs to the
1009 * destination group on the loopback interface.
1010 */
1011 if (ip6->ip6_hlim == 0 || (ifp->if_flags & IFF_LOOPBACK) ||
1012 IN6_IS_ADDR_MC_INTFACELOCAL(&ip6->ip6_dst)) {
1013 m_freem(m);
1014 goto done;
1015 }
1016 }
1017
1018 /*
1019 * Fill the outgoing inteface to tell the upper layer
1020 * to increment per-interface statistics.
1021 */
1022 if (ifpp != NULL) {
1023 ifnet_reference(ifp); /* for caller */
1024 if (*ifpp != NULL)
1025 ifnet_release(*ifpp);
1026 *ifpp = ifp;
1027 }
1028
1029 /* Determine path MTU. */
1030 if ((error = ip6_getpmtu(ro_pmtu, ro, ifp, &finaldst, &mtu,
1031 &alwaysfrag)) != 0)
1032 goto bad;
1033
1034 /*
1035 * The caller of this function may specify to use the minimum MTU
1036 * in some cases.
1037 * An advanced API option (IPV6_USE_MIN_MTU) can also override MTU
1038 * setting. The logic is a bit complicated; by default, unicast
1039 * packets will follow path MTU while multicast packets will be sent at
1040 * the minimum MTU. If IP6PO_MINMTU_ALL is specified, all packets
1041 * including unicast ones will be sent at the minimum MTU. Multicast
1042 * packets will always be sent at the minimum MTU unless
1043 * IP6PO_MINMTU_DISABLE is explicitly specified.
1044 * See RFC 3542 for more details.
1045 */
1046 if (mtu > IPV6_MMTU) {
1047 if ((flags & IPV6_MINMTU))
1048 mtu = IPV6_MMTU;
1049 else if (opt && opt->ip6po_minmtu == IP6PO_MINMTU_ALL)
1050 mtu = IPV6_MMTU;
1051 else if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) &&
1052 (opt == NULL ||
1053 opt->ip6po_minmtu != IP6PO_MINMTU_DISABLE)) {
1054 mtu = IPV6_MMTU;
1055 }
1056 }
1057
1058 /*
1059 * clear embedded scope identifiers if necessary.
1060 * in6_clearscope will touch the addresses only when necessary.
1061 */
1062 in6_clearscope(&ip6->ip6_src);
1063 in6_clearscope(&ip6->ip6_dst);
1064
1065 #if IPFW2
1066 /*
1067 * Check with the firewall...
1068 */
1069 if (ip6_fw_enable && ip6_fw_chk_ptr) {
1070 u_short port = 0;
1071 m->m_pkthdr.rcvif = NULL; /* XXX */
1072 /* If ipfw says divert, we have to just drop packet */
1073 if (ip6_fw_chk_ptr(&ip6, ifp, &port, &m)) {
1074 m_freem(m);
1075 goto done;
1076 }
1077 if (!m) {
1078 error = EACCES;
1079 goto done;
1080 }
1081 }
1082 #endif
1083
1084 /*
1085 * If the outgoing packet contains a hop-by-hop options header,
1086 * it must be examined and processed even by the source node.
1087 * (RFC 2460, section 4.)
1088 */
1089 if (exthdrs.ip6e_hbh) {
1090 struct ip6_hbh *hbh = mtod(exthdrs.ip6e_hbh, struct ip6_hbh *);
1091 u_int32_t dummy; /* XXX unused */
1092
1093 #if DIAGNOSTIC
1094 if ((hbh->ip6h_len + 1) << 3 > exthdrs.ip6e_hbh->m_len)
1095 panic("ip6e_hbh is not continuous");
1096 #endif
1097 /*
1098 * XXX: if we have to send an ICMPv6 error to the sender,
1099 * we need the M_LOOP flag since icmp6_error() expects
1100 * the IPv6 and the hop-by-hop options header are
1101 * continuous unless the flag is set.
1102 */
1103 m->m_flags |= M_LOOP;
1104 m->m_pkthdr.rcvif = ifp;
1105 if (ip6_process_hopopts(m, (u_int8_t *)(hbh + 1),
1106 ((hbh->ip6h_len + 1) << 3) - sizeof(struct ip6_hbh),
1107 &dummy, &plen) < 0) {
1108 /* m was already freed at this point */
1109 error = EINVAL;/* better error? */
1110 goto done;
1111 }
1112 m->m_flags &= ~M_LOOP; /* XXX */
1113 m->m_pkthdr.rcvif = NULL;
1114 }
1115
1116 #if PF
1117 if (PF_IS_ENABLED) {
1118 /* Invoke outbound packet filter */
1119 error = pf_af_hook(ifp, NULL, &m, AF_INET6, FALSE);
1120
1121 if (error) {
1122 if (m != NULL) {
1123 panic("%s: unexpected packet %p\n", __func__, m);
1124 /* NOTREACHED */
1125 }
1126 /* Already freed by callee */
1127 goto done;
1128 }
1129 ip6 = mtod(m, struct ip6_hdr *);
1130 }
1131 #endif /* PF */
1132
1133 /*
1134 * Send the packet to the outgoing interface.
1135 * If necessary, do IPv6 fragmentation before sending.
1136 *
1137 * the logic here is rather complex:
1138 * 1: normal case (dontfrag == 0, alwaysfrag == 0)
1139 * 1-a: send as is if tlen <= path mtu
1140 * 1-b: fragment if tlen > path mtu
1141 *
1142 * 2: if user asks us not to fragment (dontfrag == 1)
1143 * 2-a: send as is if tlen <= interface mtu
1144 * 2-b: error if tlen > interface mtu
1145 *
1146 * 3: if we always need to attach fragment header (alwaysfrag == 1)
1147 * always fragment
1148 *
1149 * 4: if dontfrag == 1 && alwaysfrag == 1
1150 * error, as we cannot handle this conflicting request
1151 */
1152 tlen = m->m_pkthdr.len;
1153
1154 if (opt && (opt->ip6po_flags & IP6PO_DONTFRAG))
1155 dontfrag = 1;
1156 else
1157 dontfrag = 0;
1158 if (dontfrag && alwaysfrag) { /* case 4 */
1159 /* conflicting request - can't transmit */
1160 error = EMSGSIZE;
1161 goto bad;
1162 }
1163
1164 lck_rw_lock_shared(nd_if_rwlock);
1165 ifmtu = IN6_LINKMTU(ifp);
1166 lck_rw_done(nd_if_rwlock);
1167
1168 if (dontfrag && tlen > ifmtu) { /* case 2-b */
1169 /*
1170 * Even if the DONTFRAG option is specified, we cannot send the
1171 * packet when the data length is larger than the MTU of the
1172 * outgoing interface.
1173 * Notify the error by sending IPV6_PATHMTU ancillary data as
1174 * well as returning an error code (the latter is not described
1175 * in the API spec.)
1176 */
1177 u_int32_t mtu32;
1178 struct ip6ctlparam ip6cp;
1179
1180 mtu32 = (u_int32_t)mtu;
1181 bzero(&ip6cp, sizeof(ip6cp));
1182 ip6cp.ip6c_cmdarg = (void *)&mtu32;
1183 pfctlinput2(PRC_MSGSIZE, (struct sockaddr *)&ro_pmtu->ro_dst,
1184 (void *)&ip6cp);
1185
1186 error = EMSGSIZE;
1187 goto bad;
1188 }
1189
1190 /*
1191 * transmit packet without fragmentation
1192 */
1193 tso = (ifp->if_hwassist & IFNET_TSO_IPV6) &&
1194 (m->m_pkthdr.csum_flags & CSUM_TSO_IPV6);
1195 if (dontfrag || (!alwaysfrag && /* case 1-a and 2-a */
1196 (tlen <= mtu || tso || (ifp->if_hwassist & CSUM_FRAGMENT_IPV6)))) {
1197 int sw_csum;
1198
1199 ip6 = mtod(m, struct ip6_hdr *);
1200 #ifdef IPSEC
1201 /* clean ipsec history once it goes out of the node */
1202 ipsec_delaux(m);
1203 #endif
1204
1205 if (apple_hwcksum_tx == 0) /* Do not let HW handle cksum */
1206 sw_csum = m->m_pkthdr.csum_flags;
1207 else
1208 sw_csum = m->m_pkthdr.csum_flags &
1209 ~IF_HWASSIST_CSUM_FLAGS(ifp->if_hwassist);
1210
1211 if ((sw_csum & CSUM_DELAY_IPV6_DATA) != 0) {
1212 in6_delayed_cksum(m, sizeof(struct ip6_hdr) + optlen);
1213 m->m_pkthdr.csum_flags &= ~CSUM_DELAY_IPV6_DATA;
1214 }
1215 if (ro->ro_rt)
1216 RT_LOCK_ASSERT_NOTHELD(ro->ro_rt);
1217 error = nd6_output(ifp, origifp, m, dst, ro->ro_rt);
1218 goto done;
1219 }
1220
1221 /*
1222 * try to fragment the packet. case 1-b and 3
1223 */
1224 if (mtu < IPV6_MMTU) {
1225 /* path MTU cannot be less than IPV6_MMTU */
1226 error = EMSGSIZE;
1227 in6_ifstat_inc(ifp, ifs6_out_fragfail);
1228 goto bad;
1229 } else if (ip6->ip6_plen == 0) {
1230 /* jumbo payload cannot be fragmented */
1231 error = EMSGSIZE;
1232 in6_ifstat_inc(ifp, ifs6_out_fragfail);
1233 goto bad;
1234 } else {
1235 struct mbuf **mnext, *m_frgpart;
1236 struct ip6_frag *ip6f;
1237 u_int32_t id = htonl(ip6_randomid());
1238 u_char nextproto;
1239
1240 /*
1241 * Too large for the destination or interface;
1242 * fragment if possible.
1243 * Must be able to put at least 8 bytes per fragment.
1244 */
1245 hlen = unfragpartlen;
1246 if (mtu > IPV6_MAXPACKET)
1247 mtu = IPV6_MAXPACKET;
1248
1249 len = (mtu - hlen - sizeof(struct ip6_frag)) & ~7;
1250 if (len < 8) {
1251 error = EMSGSIZE;
1252 in6_ifstat_inc(ifp, ifs6_out_fragfail);
1253 goto bad;
1254 }
1255
1256 mnext = &m->m_nextpkt;
1257
1258 /*
1259 * Change the next header field of the last header in the
1260 * unfragmentable part.
1261 */
1262 if (exthdrs.ip6e_rthdr) {
1263 nextproto = *mtod(exthdrs.ip6e_rthdr, u_char *);
1264 *mtod(exthdrs.ip6e_rthdr, u_char *) = IPPROTO_FRAGMENT;
1265 } else if (exthdrs.ip6e_dest1) {
1266 nextproto = *mtod(exthdrs.ip6e_dest1, u_char *);
1267 *mtod(exthdrs.ip6e_dest1, u_char *) = IPPROTO_FRAGMENT;
1268 } else if (exthdrs.ip6e_hbh) {
1269 nextproto = *mtod(exthdrs.ip6e_hbh, u_char *);
1270 *mtod(exthdrs.ip6e_hbh, u_char *) = IPPROTO_FRAGMENT;
1271 } else {
1272 nextproto = ip6->ip6_nxt;
1273 ip6->ip6_nxt = IPPROTO_FRAGMENT;
1274 }
1275
1276 if ((m->m_pkthdr.csum_flags & CSUM_DELAY_IPV6_DATA) != 0) {
1277 in6_delayed_cksum(m, sizeof(struct ip6_hdr) + optlen);
1278 m->m_pkthdr.csum_flags &= ~CSUM_DELAY_IPV6_DATA;
1279 }
1280
1281 /*
1282 * Loop through length of segment after first fragment,
1283 * make new header and copy data of each part and link onto
1284 * chain.
1285 */
1286 m0 = m;
1287 for (off = hlen; off < tlen; off += len) {
1288 MGETHDR(m, M_DONTWAIT, MT_HEADER); /* MAC-OK */
1289 if (!m) {
1290 error = ENOBUFS;
1291 ip6stat.ip6s_odropped++;
1292 goto sendorfree;
1293 }
1294 m->m_pkthdr.rcvif = NULL;
1295 m->m_flags = m0->m_flags & M_COPYFLAGS;
1296 *mnext = m;
1297 mnext = &m->m_nextpkt;
1298 m->m_data += max_linkhdr;
1299 mhip6 = mtod(m, struct ip6_hdr *);
1300 *mhip6 = *ip6;
1301 m->m_len = sizeof(*mhip6);
1302 error = ip6_insertfraghdr(m0, m, hlen, &ip6f);
1303 if (error) {
1304 ip6stat.ip6s_odropped++;
1305 goto sendorfree;
1306 }
1307 ip6f->ip6f_offlg = htons((u_short)((off - hlen) & ~7));
1308 if (off + len >= tlen)
1309 len = tlen - off;
1310 else
1311 ip6f->ip6f_offlg |= IP6F_MORE_FRAG;
1312 mhip6->ip6_plen = htons((u_short)(len + hlen +
1313 sizeof(*ip6f) -
1314 sizeof(struct ip6_hdr)));
1315 if ((m_frgpart = m_copy(m0, off, len)) == 0) {
1316 error = ENOBUFS;
1317 ip6stat.ip6s_odropped++;
1318 goto sendorfree;
1319 }
1320 m_cat(m, m_frgpart);
1321 m->m_pkthdr.len = len + hlen + sizeof(*ip6f);
1322 m->m_pkthdr.rcvif = 0;
1323 m->m_pkthdr.socket_id = m0->m_pkthdr.socket_id;
1324 #ifdef __darwin8_notyet
1325 #if CONFIG_MACF_NET
1326 mac_create_fragment(m0, m);
1327 #endif
1328 #endif
1329 ip6f->ip6f_reserved = 0;
1330 ip6f->ip6f_ident = id;
1331 ip6f->ip6f_nxt = nextproto;
1332 ip6stat.ip6s_ofragments++;
1333 in6_ifstat_inc(ifp, ifs6_out_fragcreat);
1334 }
1335
1336 in6_ifstat_inc(ifp, ifs6_out_fragok);
1337 }
1338
1339 /*
1340 * Remove leading garbages.
1341 */
1342 sendorfree:
1343 m = m0->m_nextpkt;
1344 m0->m_nextpkt = 0;
1345 m_freem(m0);
1346 for (m0 = m; m; m = m0) {
1347 m0 = m->m_nextpkt;
1348 m->m_nextpkt = 0;
1349 if (error == 0) {
1350 /* Record statistics for this interface address. */
1351 if (ia) {
1352 #ifndef __APPLE__
1353 ia->ia_ifa.if_opackets++;
1354 ia->ia_ifa.if_obytes += m->m_pkthdr.len;
1355 #endif
1356 }
1357 #if IPSEC
1358 /* clean ipsec history once it goes out of the node */
1359 ipsec_delaux(m);
1360 #endif
1361 error = nd6_output(ifp, origifp, m, dst, ro->ro_rt);
1362
1363 } else
1364 m_freem(m);
1365 }
1366
1367 if (error == 0)
1368 ip6stat.ip6s_fragmented++;
1369
1370 done:
1371 #if IPSEC
1372 if (ipsec_saved_route) {
1373 ro = ipsec_saved_route;
1374 if (ipsec_state.ro.ro_rt) {
1375 rtfree(ipsec_state.ro.ro_rt);
1376 }
1377 }
1378 #endif /* IPSEC */
1379 if (ro == &ip6route && ro->ro_rt) { /* brace necessary for rtfree */
1380 rtfree(ro->ro_rt);
1381 } else if (ro_pmtu == &ip6route && ro_pmtu->ro_rt) {
1382 rtfree(ro_pmtu->ro_rt);
1383 }
1384
1385 #if IPSEC
1386 if (sp != NULL)
1387 key_freesp(sp, KEY_SADB_UNLOCKED);
1388 #endif /* IPSEC */
1389
1390 if (ia != NULL)
1391 IFA_REMREF(&ia->ia_ifa);
1392 if (ifp != NULL)
1393 ifnet_release(ifp);
1394 if (origifp != NULL)
1395 ifnet_release(origifp);
1396 return (error);
1397
1398 freehdrs:
1399 m_freem(exthdrs.ip6e_hbh); /* m_freem will check if mbuf is 0 */
1400 m_freem(exthdrs.ip6e_dest1);
1401 m_freem(exthdrs.ip6e_rthdr);
1402 m_freem(exthdrs.ip6e_dest2);
1403 /* fall through */
1404 bad:
1405 m_freem(m);
1406 goto done;
1407 }
1408
1409 static int
1410 ip6_copyexthdr(mp, hdr, hlen)
1411 struct mbuf **mp;
1412 caddr_t hdr;
1413 int hlen;
1414 {
1415 struct mbuf *m;
1416
1417 if (hlen > MCLBYTES)
1418 return(ENOBUFS); /* XXX */
1419
1420 MGET(m, M_DONTWAIT, MT_DATA);
1421 if (!m)
1422 return(ENOBUFS);
1423
1424 if (hlen > MLEN) {
1425 MCLGET(m, M_DONTWAIT);
1426 if ((m->m_flags & M_EXT) == 0) {
1427 m_free(m);
1428 return (ENOBUFS);
1429 }
1430 }
1431 m->m_len = hlen;
1432 if (hdr)
1433 bcopy(hdr, mtod(m, caddr_t), hlen);
1434
1435 *mp = m;
1436 return (0);
1437 }
1438
1439 /*
1440 * Process a delayed payload checksum calculation.
1441 */
1442 void
1443 in6_delayed_cksum(struct mbuf *m, uint16_t offset)
1444 {
1445 uint16_t csum;
1446
1447 csum = in6_cksum(m, 0, offset, m->m_pkthdr.len - offset);
1448 if (csum == 0 && (m->m_pkthdr.csum_flags & CSUM_UDPIPV6) != 0) {
1449 csum = 0xffff;
1450 }
1451
1452 offset += (m->m_pkthdr.csum_data & 0xffff);
1453 if ((offset + sizeof(csum)) > m->m_len) {
1454 m_copyback(m, offset, sizeof(csum), &csum);
1455 } else {
1456 *(uint16_t *)(mtod(m, char *) + offset) = csum;
1457 }
1458 }
1459 /*
1460 * Insert jumbo payload option.
1461 */
1462 static int
1463 ip6_insert_jumboopt(exthdrs, plen)
1464 struct ip6_exthdrs *exthdrs;
1465 u_int32_t plen;
1466 {
1467 struct mbuf *mopt;
1468 u_char *optbuf;
1469 u_int32_t v;
1470
1471 #define JUMBOOPTLEN 8 /* length of jumbo payload option and padding */
1472
1473 /*
1474 * If there is no hop-by-hop options header, allocate new one.
1475 * If there is one but it doesn't have enough space to store the
1476 * jumbo payload option, allocate a cluster to store the whole options.
1477 * Otherwise, use it to store the options.
1478 */
1479 if (exthdrs->ip6e_hbh == 0) {
1480 MGET(mopt, M_DONTWAIT, MT_DATA);
1481 if (mopt == 0)
1482 return (ENOBUFS);
1483 mopt->m_len = JUMBOOPTLEN;
1484 optbuf = mtod(mopt, u_char *);
1485 optbuf[1] = 0; /* = ((JUMBOOPTLEN) >> 3) - 1 */
1486 exthdrs->ip6e_hbh = mopt;
1487 } else {
1488 struct ip6_hbh *hbh;
1489
1490 mopt = exthdrs->ip6e_hbh;
1491 if (M_TRAILINGSPACE(mopt) < JUMBOOPTLEN) {
1492 /*
1493 * XXX assumption:
1494 * - exthdrs->ip6e_hbh is not referenced from places
1495 * other than exthdrs.
1496 * - exthdrs->ip6e_hbh is not an mbuf chain.
1497 */
1498 u_int32_t oldoptlen = mopt->m_len;
1499 struct mbuf *n;
1500
1501 /*
1502 * XXX: give up if the whole (new) hbh header does
1503 * not fit even in an mbuf cluster.
1504 */
1505 if (oldoptlen + JUMBOOPTLEN > MCLBYTES)
1506 return (ENOBUFS);
1507
1508 /*
1509 * As a consequence, we must always prepare a cluster
1510 * at this point.
1511 */
1512 MGET(n, M_DONTWAIT, MT_DATA);
1513 if (n) {
1514 MCLGET(n, M_DONTWAIT);
1515 if ((n->m_flags & M_EXT) == 0) {
1516 m_freem(n);
1517 n = NULL;
1518 }
1519 }
1520 if (!n)
1521 return (ENOBUFS);
1522 n->m_len = oldoptlen + JUMBOOPTLEN;
1523 bcopy(mtod(mopt, caddr_t), mtod(n, caddr_t),
1524 oldoptlen);
1525 optbuf = mtod(n, u_char *) + oldoptlen;
1526 m_freem(mopt);
1527 mopt = exthdrs->ip6e_hbh = n;
1528 } else {
1529 optbuf = mtod(mopt, u_char *) + mopt->m_len;
1530 mopt->m_len += JUMBOOPTLEN;
1531 }
1532 optbuf[0] = IP6OPT_PADN;
1533 optbuf[1] = 1;
1534
1535 /*
1536 * Adjust the header length according to the pad and
1537 * the jumbo payload option.
1538 */
1539 hbh = mtod(mopt, struct ip6_hbh *);
1540 hbh->ip6h_len += (JUMBOOPTLEN >> 3);
1541 }
1542
1543 /* fill in the option. */
1544 optbuf[2] = IP6OPT_JUMBO;
1545 optbuf[3] = 4;
1546 v = (u_int32_t)htonl(plen + JUMBOOPTLEN);
1547 bcopy(&v, &optbuf[4], sizeof(u_int32_t));
1548
1549 /* finally, adjust the packet header length */
1550 exthdrs->ip6e_ip6->m_pkthdr.len += JUMBOOPTLEN;
1551
1552 return (0);
1553 #undef JUMBOOPTLEN
1554 }
1555
1556 /*
1557 * Insert fragment header and copy unfragmentable header portions.
1558 */
1559 static int
1560 ip6_insertfraghdr(m0, m, hlen, frghdrp)
1561 struct mbuf *m0, *m;
1562 int hlen;
1563 struct ip6_frag **frghdrp;
1564 {
1565 struct mbuf *n, *mlast;
1566
1567 if (hlen > sizeof(struct ip6_hdr)) {
1568 n = m_copym(m0, sizeof(struct ip6_hdr),
1569 hlen - sizeof(struct ip6_hdr), M_DONTWAIT);
1570 if (n == 0)
1571 return (ENOBUFS);
1572 m->m_next = n;
1573 } else
1574 n = m;
1575
1576 /* Search for the last mbuf of unfragmentable part. */
1577 for (mlast = n; mlast->m_next; mlast = mlast->m_next)
1578 ;
1579
1580 if ((mlast->m_flags & M_EXT) == 0 &&
1581 M_TRAILINGSPACE(mlast) >= sizeof(struct ip6_frag)) {
1582 /* use the trailing space of the last mbuf for the fragment hdr */
1583 *frghdrp = (struct ip6_frag *)(mtod(mlast, caddr_t) +
1584 mlast->m_len);
1585 mlast->m_len += sizeof(struct ip6_frag);
1586 m->m_pkthdr.len += sizeof(struct ip6_frag);
1587 } else {
1588 /* allocate a new mbuf for the fragment header */
1589 struct mbuf *mfrg;
1590
1591 MGET(mfrg, M_DONTWAIT, MT_DATA);
1592 if (mfrg == 0)
1593 return (ENOBUFS);
1594 mfrg->m_len = sizeof(struct ip6_frag);
1595 *frghdrp = mtod(mfrg, struct ip6_frag *);
1596 mlast->m_next = mfrg;
1597 }
1598
1599 return (0);
1600 }
1601
1602 extern int load_ipfw(void);
1603 static int
1604 ip6_getpmtu(struct route_in6 *ro_pmtu, struct route_in6 *ro,
1605 struct ifnet *ifp, struct in6_addr *dst, u_int32_t *mtup,
1606 int *alwaysfragp)
1607 {
1608 u_int32_t mtu = 0;
1609 int alwaysfrag = 0;
1610 int error = 0;
1611
1612 if (ro_pmtu != ro) {
1613 /* The first hop and the final destination may differ. */
1614 struct sockaddr_in6 *sa6_dst =
1615 (struct sockaddr_in6 *)&ro_pmtu->ro_dst;
1616 if (ro_pmtu->ro_rt &&
1617 ((ro_pmtu->ro_rt->rt_flags & RTF_UP) == 0 ||
1618 ro_pmtu->ro_rt->generation_id != route_generation ||
1619 !IN6_ARE_ADDR_EQUAL(&sa6_dst->sin6_addr, dst))) {
1620 rtfree(ro_pmtu->ro_rt);
1621 ro_pmtu->ro_rt = (struct rtentry *)NULL;
1622 }
1623 if (ro_pmtu->ro_rt == NULL) {
1624 bzero(sa6_dst, sizeof(*sa6_dst));
1625 sa6_dst->sin6_family = AF_INET6;
1626 sa6_dst->sin6_len = sizeof(struct sockaddr_in6);
1627 sa6_dst->sin6_addr = *dst;
1628
1629 rtalloc_scoped((struct route *)ro_pmtu,
1630 ifp != NULL ? ifp->if_index : IFSCOPE_NONE);
1631 }
1632 }
1633
1634
1635 if (ro_pmtu->ro_rt != NULL) {
1636 u_int32_t ifmtu;
1637
1638 lck_rw_lock_shared(nd_if_rwlock);
1639 ifmtu = IN6_LINKMTU(ifp);
1640 lck_rw_done(nd_if_rwlock);
1641
1642 RT_LOCK_SPIN(ro_pmtu->ro_rt);
1643 mtu = ro_pmtu->ro_rt->rt_rmx.rmx_mtu;
1644 if (mtu > ifmtu || mtu == 0) {
1645 /*
1646 * The MTU on the route is larger than the MTU on
1647 * the interface! This shouldn't happen, unless the
1648 * MTU of the interface has been changed after the
1649 * interface was brought up. Change the MTU in the
1650 * route to match the interface MTU (as long as the
1651 * field isn't locked).
1652 *
1653 * if MTU on the route is 0, we need to fix the MTU.
1654 * this case happens with path MTU discovery timeouts.
1655 */
1656 mtu = ifmtu;
1657 if ((ro_pmtu->ro_rt->rt_rmx.rmx_locks & RTV_MTU) == 0)
1658 ro_pmtu->ro_rt->rt_rmx.rmx_mtu = mtu; /* XXX */
1659 }
1660 else if (mtu < IPV6_MMTU) {
1661 /*
1662 * RFC2460 section 5, last paragraph:
1663 * if we record ICMPv6 too big message with
1664 * mtu < IPV6_MMTU, transmit packets sized IPV6_MMTU
1665 * or smaller, with framgent header attached.
1666 * (fragment header is needed regardless from the
1667 * packet size, for translators to identify packets)
1668 */
1669 alwaysfrag = 1;
1670 mtu = IPV6_MMTU;
1671 }
1672 RT_UNLOCK(ro_pmtu->ro_rt);
1673 } else {
1674 if (ifp) {
1675 lck_rw_lock_shared(nd_if_rwlock);
1676 mtu = IN6_LINKMTU(ifp);
1677 lck_rw_done(nd_if_rwlock);
1678 } else
1679 error = EHOSTUNREACH; /* XXX */
1680 }
1681
1682 *mtup = mtu;
1683 if (alwaysfragp)
1684 *alwaysfragp = alwaysfrag;
1685 return (error);
1686 }
1687
1688 /*
1689 * IP6 socket option processing.
1690 */
1691 int
1692 ip6_ctloutput(so, sopt)
1693 struct socket *so;
1694 struct sockopt *sopt;
1695 {
1696 int optdatalen, uproto;
1697 void *optdata;
1698 int privileged;
1699 struct inpcb *in6p = sotoinpcb(so);
1700 int error = 0, optval = 0;
1701 int level, op = -1, optname = 0;
1702 int optlen = 0;
1703 struct proc *p;
1704
1705 if (sopt == NULL) {
1706 panic("ip6_ctloutput: arg soopt is NULL");
1707 /* NOTREACHED */
1708 }
1709 level = sopt->sopt_level;
1710 op = sopt->sopt_dir;
1711 optname = sopt->sopt_name;
1712 optlen = sopt->sopt_valsize;
1713 p = sopt->sopt_p;
1714 uproto = (int)so->so_proto->pr_protocol;
1715
1716 privileged = (proc_suser(p) == 0);
1717
1718 if (level == IPPROTO_IPV6) {
1719 switch (op) {
1720
1721 case SOPT_SET:
1722 switch (optname) {
1723 case IPV6_2292PKTOPTIONS:
1724 {
1725 struct mbuf *m;
1726
1727 error = soopt_getm(sopt, &m); /* XXX */
1728 if (error != 0)
1729 break;
1730 error = soopt_mcopyin(sopt, m); /* XXX */
1731 if (error != 0)
1732 break;
1733 error = ip6_pcbopts(&in6p->in6p_outputopts,
1734 m, so, sopt);
1735 m_freem(m); /* XXX */
1736 break;
1737 }
1738
1739 /*
1740 * Use of some Hop-by-Hop options or some
1741 * Destination options, might require special
1742 * privilege. That is, normal applications
1743 * (without special privilege) might be forbidden
1744 * from setting certain options in outgoing packets,
1745 * and might never see certain options in received
1746 * packets. [RFC 2292 Section 6]
1747 * KAME specific note:
1748 * KAME prevents non-privileged users from sending or
1749 * receiving ANY hbh/dst options in order to avoid
1750 * overhead of parsing options in the kernel.
1751 */
1752 case IPV6_RECVHOPOPTS:
1753 case IPV6_RECVDSTOPTS:
1754 case IPV6_RECVRTHDRDSTOPTS:
1755 if (!privileged)
1756 break;
1757 /* FALLTHROUGH */
1758 case IPV6_UNICAST_HOPS:
1759 case IPV6_HOPLIMIT:
1760 case IPV6_FAITH:
1761
1762 case IPV6_RECVPKTINFO:
1763 case IPV6_RECVHOPLIMIT:
1764 case IPV6_RECVRTHDR:
1765 case IPV6_RECVPATHMTU:
1766 case IPV6_RECVTCLASS:
1767 case IPV6_V6ONLY:
1768 case IPV6_AUTOFLOWLABEL:
1769 if (optlen != sizeof(int)) {
1770 error = EINVAL;
1771 break;
1772 }
1773 error = sooptcopyin(sopt, &optval,
1774 sizeof optval, sizeof optval);
1775 if (error)
1776 break;
1777 switch (optname) {
1778
1779 case IPV6_UNICAST_HOPS:
1780 if (optval < -1 || optval >= 256)
1781 error = EINVAL;
1782 else {
1783 /* -1 = kernel default */
1784 in6p->in6p_hops = optval;
1785 if ((in6p->inp_vflag &
1786 INP_IPV4) != 0)
1787 in6p->inp_ip_ttl = optval;
1788 }
1789 break;
1790 #define OPTSET(bit) \
1791 do { \
1792 if (optval) \
1793 in6p->inp_flags |= (bit); \
1794 else \
1795 in6p->inp_flags &= ~(bit); \
1796 } while (/*CONSTCOND*/ 0)
1797 #define OPTSET2292(bit) \
1798 do { \
1799 in6p->inp_flags |= IN6P_RFC2292; \
1800 if (optval) \
1801 in6p->inp_flags |= (bit); \
1802 else \
1803 in6p->inp_flags &= ~(bit); \
1804 } while (/*CONSTCOND*/ 0)
1805 #define OPTBIT(bit) (in6p->inp_flags & (bit) ? 1 : 0)
1806
1807 case IPV6_RECVPKTINFO:
1808 /* cannot mix with RFC2292 */
1809 if (OPTBIT(IN6P_RFC2292)) {
1810 error = EINVAL;
1811 break;
1812 }
1813 OPTSET(IN6P_PKTINFO);
1814 break;
1815
1816 case IPV6_HOPLIMIT:
1817 {
1818 struct ip6_pktopts **optp;
1819
1820 /* cannot mix with RFC2292 */
1821 if (OPTBIT(IN6P_RFC2292)) {
1822 error = EINVAL;
1823 break;
1824 }
1825 optp = &in6p->in6p_outputopts;
1826 error = ip6_pcbopt(IPV6_HOPLIMIT,
1827 (u_char *)&optval, sizeof(optval),
1828 optp, uproto);
1829 break;
1830 }
1831
1832 case IPV6_RECVHOPLIMIT:
1833 /* cannot mix with RFC2292 */
1834 if (OPTBIT(IN6P_RFC2292)) {
1835 error = EINVAL;
1836 break;
1837 }
1838 OPTSET(IN6P_HOPLIMIT);
1839 break;
1840
1841 case IPV6_RECVHOPOPTS:
1842 /* cannot mix with RFC2292 */
1843 if (OPTBIT(IN6P_RFC2292)) {
1844 error = EINVAL;
1845 break;
1846 }
1847 OPTSET(IN6P_HOPOPTS);
1848 break;
1849
1850 case IPV6_RECVDSTOPTS:
1851 /* cannot mix with RFC2292 */
1852 if (OPTBIT(IN6P_RFC2292)) {
1853 error = EINVAL;
1854 break;
1855 }
1856 OPTSET(IN6P_DSTOPTS);
1857 break;
1858
1859 case IPV6_RECVRTHDRDSTOPTS:
1860 /* cannot mix with RFC2292 */
1861 if (OPTBIT(IN6P_RFC2292)) {
1862 error = EINVAL;
1863 break;
1864 }
1865 OPTSET(IN6P_RTHDRDSTOPTS);
1866 break;
1867
1868 case IPV6_RECVRTHDR:
1869 /* cannot mix with RFC2292 */
1870 if (OPTBIT(IN6P_RFC2292)) {
1871 error = EINVAL;
1872 break;
1873 }
1874 OPTSET(IN6P_RTHDR);
1875 break;
1876
1877 case IPV6_FAITH:
1878 OPTSET(INP_FAITH);
1879 break;
1880
1881 case IPV6_RECVPATHMTU:
1882 /*
1883 * We ignore this option for TCP
1884 * sockets.
1885 * (RFC3542 leaves this case
1886 * unspecified.)
1887 */
1888 if (uproto != IPPROTO_TCP)
1889 OPTSET(IN6P_MTU);
1890 break;
1891
1892 case IPV6_V6ONLY:
1893 /*
1894 * make setsockopt(IPV6_V6ONLY)
1895 * available only prior to bind(2).
1896 * see ipng mailing list, Jun 22 2001.
1897 */
1898 if (in6p->inp_lport ||
1899 !IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr)) {
1900 error = EINVAL;
1901 break;
1902 }
1903 OPTSET(IN6P_IPV6_V6ONLY);
1904 if (optval)
1905 in6p->inp_vflag &= ~INP_IPV4;
1906 else
1907 in6p->inp_vflag |= INP_IPV4;
1908 break;
1909 case IPV6_RECVTCLASS:
1910 /* we can mix with RFC2292 */
1911 OPTSET(IN6P_TCLASS);
1912 break;
1913 case IPV6_AUTOFLOWLABEL:
1914 OPTSET(IN6P_AUTOFLOWLABEL);
1915 break;
1916
1917 }
1918 break;
1919
1920 case IPV6_TCLASS:
1921 case IPV6_DONTFRAG:
1922 case IPV6_USE_MIN_MTU:
1923 case IPV6_PREFER_TEMPADDR:
1924 if (optlen != sizeof(optval)) {
1925 error = EINVAL;
1926 break;
1927 }
1928 error = sooptcopyin(sopt, &optval,
1929 sizeof optval, sizeof optval);
1930 if (error)
1931 break;
1932 {
1933 struct ip6_pktopts **optp;
1934 optp = &in6p->in6p_outputopts;
1935 error = ip6_pcbopt(optname,
1936 (u_char *)&optval, sizeof(optval),
1937 optp, uproto);
1938 break;
1939 }
1940
1941 case IPV6_2292PKTINFO:
1942 case IPV6_2292HOPLIMIT:
1943 case IPV6_2292HOPOPTS:
1944 case IPV6_2292DSTOPTS:
1945 case IPV6_2292RTHDR:
1946 /* RFC 2292 */
1947 if (optlen != sizeof(int)) {
1948 error = EINVAL;
1949 break;
1950 }
1951 error = sooptcopyin(sopt, &optval,
1952 sizeof optval, sizeof optval);
1953 if (error)
1954 break;
1955 switch (optname) {
1956 case IPV6_2292PKTINFO:
1957 OPTSET2292(IN6P_PKTINFO);
1958 break;
1959 case IPV6_2292HOPLIMIT:
1960 OPTSET2292(IN6P_HOPLIMIT);
1961 break;
1962 case IPV6_2292HOPOPTS:
1963 /*
1964 * Check super-user privilege.
1965 * See comments for IPV6_RECVHOPOPTS.
1966 */
1967 if (!privileged)
1968 return(EPERM);
1969 OPTSET2292(IN6P_HOPOPTS);
1970 break;
1971 case IPV6_2292DSTOPTS:
1972 if (!privileged)
1973 return(EPERM);
1974 OPTSET2292(IN6P_DSTOPTS|IN6P_RTHDRDSTOPTS); /* XXX */
1975 break;
1976 case IPV6_2292RTHDR:
1977 OPTSET2292(IN6P_RTHDR);
1978 break;
1979 }
1980 break;
1981 case IPV6_3542PKTINFO:
1982 case IPV6_3542HOPOPTS:
1983 case IPV6_3542RTHDR:
1984 case IPV6_3542DSTOPTS:
1985 case IPV6_RTHDRDSTOPTS:
1986 case IPV6_3542NEXTHOP:
1987 {
1988 /* new advanced API (RFC3542) */
1989 struct mbuf *m;
1990
1991 /* cannot mix with RFC2292 */
1992 if (OPTBIT(IN6P_RFC2292)) {
1993 error = EINVAL;
1994 break;
1995 }
1996 error = soopt_getm(sopt, &m);
1997 if (error != 0)
1998 break;
1999 error = soopt_mcopyin(sopt, m);
2000 if (error) {
2001 m_freem(m);
2002 break;
2003 }
2004 error = ip6_pcbopt(optname, mtod(m, u_char *),
2005 m->m_len, &in6p->in6p_outputopts, uproto);
2006 m_freem(m);
2007 break;
2008 }
2009 #undef OPTSET
2010
2011 case IPV6_MULTICAST_IF:
2012 case IPV6_MULTICAST_HOPS:
2013 case IPV6_MULTICAST_LOOP:
2014 case IPV6_JOIN_GROUP:
2015 case IPV6_LEAVE_GROUP:
2016 case IPV6_MSFILTER:
2017 case MCAST_BLOCK_SOURCE:
2018 case MCAST_UNBLOCK_SOURCE:
2019 case MCAST_JOIN_GROUP:
2020 case MCAST_LEAVE_GROUP:
2021 case MCAST_JOIN_SOURCE_GROUP:
2022 case MCAST_LEAVE_SOURCE_GROUP:
2023 error = ip6_setmoptions(in6p, sopt);
2024 break;
2025
2026 case IPV6_PORTRANGE:
2027 error = sooptcopyin(sopt, &optval,
2028 sizeof optval, sizeof optval);
2029 if (error)
2030 break;
2031
2032 switch (optval) {
2033 case IPV6_PORTRANGE_DEFAULT:
2034 in6p->inp_flags &= ~(INP_LOWPORT);
2035 in6p->inp_flags &= ~(INP_HIGHPORT);
2036 break;
2037
2038 case IPV6_PORTRANGE_HIGH:
2039 in6p->inp_flags &= ~(INP_LOWPORT);
2040 in6p->inp_flags |= INP_HIGHPORT;
2041 break;
2042
2043 case IPV6_PORTRANGE_LOW:
2044 in6p->inp_flags &= ~(INP_HIGHPORT);
2045 in6p->inp_flags |= INP_LOWPORT;
2046 break;
2047
2048 default:
2049 error = EINVAL;
2050 break;
2051 }
2052 break;
2053
2054 #if IPSEC
2055 case IPV6_IPSEC_POLICY:
2056 {
2057 caddr_t req = NULL;
2058 size_t len = 0;
2059 struct mbuf *m;
2060
2061 if ((error = soopt_getm(sopt, &m)) != 0) /* XXX */
2062 break;
2063 if ((error = soopt_mcopyin(sopt, m)) != 0) /* XXX */
2064 break;
2065 if (m) {
2066 req = mtod(m, caddr_t);
2067 len = m->m_len;
2068 }
2069 error = ipsec6_set_policy(in6p, optname, req,
2070 len, privileged);
2071 m_freem(m);
2072 }
2073 break;
2074 #endif /* KAME IPSEC */
2075
2076 #if IPFIREWALL
2077 case IPV6_FW_ADD:
2078 case IPV6_FW_DEL:
2079 case IPV6_FW_FLUSH:
2080 case IPV6_FW_ZERO:
2081 {
2082 if (ip6_fw_ctl_ptr == NULL)
2083 load_ip6fw();
2084 if (ip6_fw_ctl_ptr != NULL)
2085 error = (*ip6_fw_ctl_ptr)(sopt);
2086 else
2087 return ENOPROTOOPT;
2088 }
2089 break;
2090 #endif /* IPFIREWALL */
2091
2092 /*
2093 * IPv6 variant of IP_BOUND_IF; for details see
2094 * comments on IP_BOUND_IF in ip_ctloutput().
2095 */
2096 case IPV6_BOUND_IF:
2097 /* This option is settable only on IPv6 */
2098 if (!(in6p->inp_vflag & INP_IPV6)) {
2099 error = EINVAL;
2100 break;
2101 }
2102
2103 error = sooptcopyin(sopt, &optval,
2104 sizeof (optval), sizeof (optval));
2105
2106 if (error)
2107 break;
2108
2109 inp_bindif(in6p, optval);
2110 break;
2111
2112 case IPV6_NO_IFT_CELLULAR:
2113 /* This option is settable only for IPv6 */
2114 if (!(in6p->inp_vflag & INP_IPV6)) {
2115 error = EINVAL;
2116 break;
2117 }
2118
2119 error = sooptcopyin(sopt, &optval,
2120 sizeof (optval), sizeof (optval));
2121
2122 if (error)
2123 break;
2124
2125 error = inp_nocellular(in6p, optval);
2126 break;
2127
2128 case IPV6_OUT_IF:
2129 /* This option is not settable */
2130 error = EINVAL;
2131 break;
2132
2133 default:
2134 error = ENOPROTOOPT;
2135 break;
2136 }
2137 break;
2138
2139 case SOPT_GET:
2140 switch (optname) {
2141
2142 case IPV6_2292PKTOPTIONS:
2143 /*
2144 * RFC3542 (effectively) deprecated the
2145 * semantics of the 2292-style pktoptions.
2146 * Since it was not reliable in nature (i.e.,
2147 * applications had to expect the lack of some
2148 * information after all), it would make sense
2149 * to simplify this part by always returning
2150 * empty data.
2151 */
2152 sopt->sopt_valsize = 0;
2153 break;
2154
2155 case IPV6_RECVHOPOPTS:
2156 case IPV6_RECVDSTOPTS:
2157 case IPV6_RECVRTHDRDSTOPTS:
2158 case IPV6_UNICAST_HOPS:
2159 case IPV6_RECVPKTINFO:
2160 case IPV6_RECVHOPLIMIT:
2161 case IPV6_RECVRTHDR:
2162 case IPV6_RECVPATHMTU:
2163
2164 case IPV6_FAITH:
2165 case IPV6_V6ONLY:
2166 case IPV6_PORTRANGE:
2167 case IPV6_RECVTCLASS:
2168 case IPV6_AUTOFLOWLABEL:
2169 switch (optname) {
2170
2171 case IPV6_RECVHOPOPTS:
2172 optval = OPTBIT(IN6P_HOPOPTS);
2173 break;
2174
2175 case IPV6_RECVDSTOPTS:
2176 optval = OPTBIT(IN6P_DSTOPTS);
2177 break;
2178
2179 case IPV6_RECVRTHDRDSTOPTS:
2180 optval = OPTBIT(IN6P_RTHDRDSTOPTS);
2181 break;
2182
2183 case IPV6_UNICAST_HOPS:
2184 optval = in6p->in6p_hops;
2185 break;
2186
2187 case IPV6_RECVPKTINFO:
2188 optval = OPTBIT(IN6P_PKTINFO);
2189 break;
2190
2191 case IPV6_RECVHOPLIMIT:
2192 optval = OPTBIT(IN6P_HOPLIMIT);
2193 break;
2194
2195 case IPV6_RECVRTHDR:
2196 optval = OPTBIT(IN6P_RTHDR);
2197 break;
2198
2199 case IPV6_RECVPATHMTU:
2200 optval = OPTBIT(IN6P_MTU);
2201 break;
2202
2203 case IPV6_FAITH:
2204 optval = OPTBIT(INP_FAITH);
2205 break;
2206
2207 case IPV6_V6ONLY:
2208 optval = OPTBIT(IN6P_IPV6_V6ONLY);
2209 break;
2210
2211 case IPV6_PORTRANGE:
2212 {
2213 int flags;
2214 flags = in6p->inp_flags;
2215 if (flags & INP_HIGHPORT)
2216 optval = IPV6_PORTRANGE_HIGH;
2217 else if (flags & INP_LOWPORT)
2218 optval = IPV6_PORTRANGE_LOW;
2219 else
2220 optval = 0;
2221 break;
2222 }
2223 case IPV6_RECVTCLASS:
2224 optval = OPTBIT(IN6P_TCLASS);
2225 break;
2226
2227 case IPV6_AUTOFLOWLABEL:
2228 optval = OPTBIT(IN6P_AUTOFLOWLABEL);
2229 break;
2230 }
2231 if (error)
2232 break;
2233 error = sooptcopyout(sopt, &optval,
2234 sizeof optval);
2235 break;
2236
2237 case IPV6_PATHMTU:
2238 {
2239 u_int32_t pmtu = 0;
2240 struct ip6_mtuinfo mtuinfo;
2241 struct route_in6 sro;
2242
2243 bzero(&sro, sizeof(sro));
2244
2245 if (!(so->so_state & SS_ISCONNECTED))
2246 return (ENOTCONN);
2247 /*
2248 * XXX: we dot not consider the case of source
2249 * routing, or optional information to specify
2250 * the outgoing interface.
2251 */
2252 error = ip6_getpmtu(&sro, NULL, NULL,
2253 &in6p->in6p_faddr, &pmtu, NULL);
2254 if (sro.ro_rt)
2255 rtfree(sro.ro_rt);
2256 if (error)
2257 break;
2258 if (pmtu > IPV6_MAXPACKET)
2259 pmtu = IPV6_MAXPACKET;
2260
2261 bzero(&mtuinfo, sizeof(mtuinfo));
2262 mtuinfo.ip6m_mtu = (u_int32_t)pmtu;
2263 optdata = (void *)&mtuinfo;
2264 optdatalen = sizeof(mtuinfo);
2265 error = sooptcopyout(sopt, optdata,
2266 optdatalen);
2267 break;
2268 }
2269
2270 case IPV6_2292PKTINFO:
2271 case IPV6_2292HOPLIMIT:
2272 case IPV6_2292HOPOPTS:
2273 case IPV6_2292RTHDR:
2274 case IPV6_2292DSTOPTS:
2275 switch (optname) {
2276 case IPV6_2292PKTINFO:
2277 optval = OPTBIT(IN6P_PKTINFO);
2278 break;
2279 case IPV6_2292HOPLIMIT:
2280 optval = OPTBIT(IN6P_HOPLIMIT);
2281 break;
2282 case IPV6_2292HOPOPTS:
2283 optval = OPTBIT(IN6P_HOPOPTS);
2284 break;
2285 case IPV6_2292RTHDR:
2286 optval = OPTBIT(IN6P_RTHDR);
2287 break;
2288 case IPV6_2292DSTOPTS:
2289 optval = OPTBIT(IN6P_DSTOPTS|IN6P_RTHDRDSTOPTS);
2290 break;
2291 }
2292 error = sooptcopyout(sopt, &optval,
2293 sizeof optval);
2294 break;
2295 case IPV6_PKTINFO:
2296 case IPV6_HOPOPTS:
2297 case IPV6_RTHDR:
2298 case IPV6_DSTOPTS:
2299 case IPV6_RTHDRDSTOPTS:
2300 case IPV6_NEXTHOP:
2301 case IPV6_TCLASS:
2302 case IPV6_DONTFRAG:
2303 case IPV6_USE_MIN_MTU:
2304 case IPV6_PREFER_TEMPADDR:
2305 error = ip6_getpcbopt(in6p->in6p_outputopts,
2306 optname, sopt);
2307 break;
2308
2309 case IPV6_MULTICAST_IF:
2310 case IPV6_MULTICAST_HOPS:
2311 case IPV6_MULTICAST_LOOP:
2312 case IPV6_MSFILTER:
2313 error = ip6_getmoptions(in6p, sopt);
2314 break;
2315
2316 #if IPSEC
2317 case IPV6_IPSEC_POLICY:
2318 {
2319 caddr_t req = NULL;
2320 size_t len = 0;
2321 struct mbuf *m = NULL;
2322 struct mbuf **mp = &m;
2323
2324 error = soopt_getm(sopt, &m); /* XXX */
2325 if (error != 0)
2326 break;
2327 error = soopt_mcopyin(sopt, m); /* XXX */
2328 if (error != 0)
2329 break;
2330 if (m) {
2331 req = mtod(m, caddr_t);
2332 len = m->m_len;
2333 }
2334 error = ipsec6_get_policy(in6p, req, len, mp);
2335 if (error == 0)
2336 error = soopt_mcopyout(sopt, m); /*XXX*/
2337 if (error == 0 && m)
2338 m_freem(m);
2339 break;
2340 }
2341 #endif /* KAME IPSEC */
2342
2343 #if IPFIREWALL
2344 case IPV6_FW_GET:
2345 {
2346 if (ip6_fw_ctl_ptr == NULL)
2347 load_ip6fw();
2348 if (ip6_fw_ctl_ptr != NULL)
2349 error = (*ip6_fw_ctl_ptr)(sopt);
2350 else
2351 return ENOPROTOOPT;
2352 }
2353 break;
2354 #endif /* IPFIREWALL */
2355
2356 case IPV6_BOUND_IF:
2357 if (in6p->inp_flags & INP_BOUND_IF)
2358 optval = in6p->inp_boundif;
2359 error = sooptcopyout(sopt, &optval,
2360 sizeof (optval));
2361 break;
2362
2363 case IPV6_NO_IFT_CELLULAR:
2364 optval = (in6p->inp_flags & INP_NO_IFT_CELLULAR)
2365 ? 1 : 0;
2366 error = sooptcopyout(sopt, &optval,
2367 sizeof (optval));
2368 break;
2369
2370 case IPV6_OUT_IF:
2371 optval = in6p->in6p_last_outif;
2372 error = sooptcopyout(sopt, &optval,
2373 sizeof (optval));
2374 break;
2375
2376 default:
2377 error = ENOPROTOOPT;
2378 break;
2379 }
2380 break;
2381 }
2382 } else {
2383 error = EINVAL;
2384 }
2385 return(error);
2386 }
2387
2388 int
2389 ip6_raw_ctloutput(struct socket *so, struct sockopt *sopt)
2390 {
2391 int error = 0, optval, optlen;
2392 const int icmp6off = offsetof(struct icmp6_hdr, icmp6_cksum);
2393 struct inpcb *in6p = sotoinpcb(so);
2394 int level, op, optname;
2395
2396 level = sopt->sopt_level;
2397 op = sopt->sopt_dir;
2398 optname = sopt->sopt_name;
2399 optlen = sopt->sopt_valsize;
2400
2401 if (level != IPPROTO_IPV6) {
2402 return (EINVAL);
2403 }
2404
2405 switch (optname) {
2406 case IPV6_CHECKSUM:
2407 /*
2408 * For ICMPv6 sockets, no modification allowed for checksum
2409 * offset, permit "no change" values to help existing apps.
2410 *
2411 * RFC3542 says: "An attempt to set IPV6_CHECKSUM
2412 * for an ICMPv6 socket will fail."
2413 * The current behavior does not meet RFC3542.
2414 */
2415 switch (op) {
2416 case SOPT_SET:
2417 if (optlen != sizeof(int)) {
2418 error = EINVAL;
2419 break;
2420 }
2421 error = sooptcopyin(sopt, &optval, sizeof(optval),
2422 sizeof(optval));
2423 if (error)
2424 break;
2425 if ((optval % 2) != 0) {
2426 /* the API assumes even offset values */
2427 error = EINVAL;
2428 } else if (so->so_proto->pr_protocol ==
2429 IPPROTO_ICMPV6) {
2430 if (optval != icmp6off)
2431 error = EINVAL;
2432 } else
2433 in6p->in6p_cksum = optval;
2434 break;
2435
2436 case SOPT_GET:
2437 if (so->so_proto->pr_protocol == IPPROTO_ICMPV6)
2438 optval = icmp6off;
2439 else
2440 optval = in6p->in6p_cksum;
2441
2442 error = sooptcopyout(sopt, &optval, sizeof(optval));
2443 break;
2444
2445 default:
2446 error = EINVAL;
2447 break;
2448 }
2449 break;
2450
2451 default:
2452 error = ENOPROTOOPT;
2453 break;
2454 }
2455
2456 return (error);
2457 }
2458
2459 /*
2460 * Set up IP6 options in pcb for insertion in output packets or
2461 * specifying behavior of outgoing packets.
2462 */
2463 static int
2464 ip6_pcbopts(
2465 struct ip6_pktopts **pktopt,
2466 struct mbuf *m,
2467 __unused struct socket *so,
2468 __unused struct sockopt *sopt)
2469 {
2470 struct ip6_pktopts *opt = *pktopt;
2471 int error = 0;
2472
2473 /* turn off any old options. */
2474 if (opt) {
2475 #if DIAGNOSTIC
2476 if (opt->ip6po_pktinfo || opt->ip6po_nexthop ||
2477 opt->ip6po_hbh || opt->ip6po_dest1 || opt->ip6po_dest2 ||
2478 opt->ip6po_rhinfo.ip6po_rhi_rthdr)
2479 printf("ip6_pcbopts: all specified options are cleared.\n");
2480 #endif
2481 ip6_clearpktopts(opt, -1);
2482 } else {
2483 opt = _MALLOC(sizeof(*opt), M_IP6OPT, M_WAITOK);
2484 if (opt == NULL)
2485 return ENOBUFS;
2486 }
2487 *pktopt = NULL;
2488
2489 if (!m || m->m_len == 0) {
2490 /*
2491 * Only turning off any previous options, regardless of
2492 * whether the opt is just created or given.
2493 */
2494 if (opt)
2495 FREE(opt, M_IP6OPT);
2496 return(0);
2497 }
2498
2499 /* set options specified by user. */
2500 if ((error = ip6_setpktopts(m, opt, NULL, so->so_proto->pr_protocol)) != 0) {
2501 ip6_clearpktopts(opt, -1); /* XXX: discard all options */
2502 FREE(opt, M_IP6OPT);
2503 return(error);
2504 }
2505 *pktopt = opt;
2506 return(0);
2507 }
2508
2509 /*
2510 * initialize ip6_pktopts. beware that there are non-zero default values in
2511 * the struct.
2512 */
2513 void
2514 ip6_initpktopts(struct ip6_pktopts *opt)
2515 {
2516
2517 bzero(opt, sizeof(*opt));
2518 opt->ip6po_hlim = -1; /* -1 means default hop limit */
2519 opt->ip6po_tclass = -1; /* -1 means default traffic class */
2520 opt->ip6po_minmtu = IP6PO_MINMTU_MCASTONLY;
2521 opt->ip6po_prefer_tempaddr = IP6PO_TEMPADDR_SYSTEM;
2522 }
2523
2524 static int
2525 ip6_pcbopt(int optname, u_char *buf, int len, struct ip6_pktopts **pktopt, int uproto)
2526 {
2527 struct ip6_pktopts *opt;
2528
2529 opt = *pktopt;
2530 if (opt == NULL) {
2531 opt = _MALLOC(sizeof(*opt), M_IP6OPT, M_WAITOK);
2532 if (opt == NULL)
2533 return(ENOBUFS);
2534 ip6_initpktopts(opt);
2535 *pktopt = opt;
2536 }
2537
2538 return (ip6_setpktopt(optname, buf, len, opt, 1, 0, uproto));
2539 }
2540
2541 static int
2542 ip6_getpcbopt(struct ip6_pktopts *pktopt, int optname, struct sockopt *sopt)
2543 {
2544 void *optdata = NULL;
2545 int optdatalen = 0;
2546 struct ip6_ext *ip6e;
2547 int error = 0;
2548 struct in6_pktinfo null_pktinfo;
2549 int deftclass = 0, on;
2550 int defminmtu = IP6PO_MINMTU_MCASTONLY;
2551 int defpreftemp = IP6PO_TEMPADDR_SYSTEM;
2552
2553 switch (optname) {
2554 case IPV6_PKTINFO:
2555 if (pktopt && pktopt->ip6po_pktinfo)
2556 optdata = (void *)pktopt->ip6po_pktinfo;
2557 else {
2558 /* XXX: we don't have to do this every time... */
2559 bzero(&null_pktinfo, sizeof(null_pktinfo));
2560 optdata = (void *)&null_pktinfo;
2561 }
2562 optdatalen = sizeof(struct in6_pktinfo);
2563 break;
2564 case IPV6_TCLASS:
2565 if (pktopt && pktopt->ip6po_tclass >= 0)
2566 optdata = (void *)&pktopt->ip6po_tclass;
2567 else
2568 optdata = (void *)&deftclass;
2569 optdatalen = sizeof(int);
2570 break;
2571 case IPV6_HOPOPTS:
2572 if (pktopt && pktopt->ip6po_hbh) {
2573 optdata = (void *)pktopt->ip6po_hbh;
2574 ip6e = (struct ip6_ext *)pktopt->ip6po_hbh;
2575 optdatalen = (ip6e->ip6e_len + 1) << 3;
2576 }
2577 break;
2578 case IPV6_RTHDR:
2579 if (pktopt && pktopt->ip6po_rthdr) {
2580 optdata = (void *)pktopt->ip6po_rthdr;
2581 ip6e = (struct ip6_ext *)pktopt->ip6po_rthdr;
2582 optdatalen = (ip6e->ip6e_len + 1) << 3;
2583 }
2584 break;
2585 case IPV6_RTHDRDSTOPTS:
2586 if (pktopt && pktopt->ip6po_dest1) {
2587 optdata = (void *)pktopt->ip6po_dest1;
2588 ip6e = (struct ip6_ext *)pktopt->ip6po_dest1;
2589 optdatalen = (ip6e->ip6e_len + 1) << 3;
2590 }
2591 break;
2592 case IPV6_DSTOPTS:
2593 if (pktopt && pktopt->ip6po_dest2) {
2594 optdata = (void *)pktopt->ip6po_dest2;
2595 ip6e = (struct ip6_ext *)pktopt->ip6po_dest2;
2596 optdatalen = (ip6e->ip6e_len + 1) << 3;
2597 }
2598 break;
2599 case IPV6_NEXTHOP:
2600 if (pktopt && pktopt->ip6po_nexthop) {
2601 optdata = (void *)pktopt->ip6po_nexthop;
2602 optdatalen = pktopt->ip6po_nexthop->sa_len;
2603 }
2604 break;
2605 case IPV6_USE_MIN_MTU:
2606 if (pktopt)
2607 optdata = (void *)&pktopt->ip6po_minmtu;
2608 else
2609 optdata = (void *)&defminmtu;
2610 optdatalen = sizeof(int);
2611 break;
2612 case IPV6_DONTFRAG:
2613 if (pktopt && ((pktopt->ip6po_flags) & IP6PO_DONTFRAG))
2614 on = 1;
2615 else
2616 on = 0;
2617 optdata = (void *)&on;
2618 optdatalen = sizeof(on);
2619 break;
2620 case IPV6_PREFER_TEMPADDR:
2621 if (pktopt)
2622 optdata = (void *)&pktopt->ip6po_prefer_tempaddr;
2623 else
2624 optdata = (void *)&defpreftemp;
2625 optdatalen = sizeof(int);
2626 break;
2627 default: /* should not happen */
2628 #ifdef DIAGNOSTIC
2629 panic("ip6_getpcbopt: unexpected option\n");
2630 #endif
2631 return (ENOPROTOOPT);
2632 }
2633
2634 error = sooptcopyout(sopt, optdata, optdatalen);
2635
2636 return (error);
2637 }
2638
2639 void
2640 ip6_clearpktopts(pktopt, optname)
2641 struct ip6_pktopts *pktopt;
2642 int optname;
2643 {
2644 if (pktopt == NULL)
2645 return;
2646
2647 if (optname == -1 || optname == IPV6_PKTINFO) {
2648 if (pktopt->ip6po_pktinfo)
2649 FREE(pktopt->ip6po_pktinfo, M_IP6OPT);
2650 pktopt->ip6po_pktinfo = NULL;
2651 }
2652 if (optname == -1 || optname == IPV6_HOPLIMIT)
2653 pktopt->ip6po_hlim = -1;
2654 if (optname == -1 || optname == IPV6_TCLASS)
2655 pktopt->ip6po_tclass = -1;
2656 if (optname == -1 || optname == IPV6_NEXTHOP) {
2657 if (pktopt->ip6po_nextroute.ro_rt) {
2658 rtfree(pktopt->ip6po_nextroute.ro_rt);
2659 pktopt->ip6po_nextroute.ro_rt = NULL;
2660 }
2661 if (pktopt->ip6po_nexthop)
2662 FREE(pktopt->ip6po_nexthop, M_IP6OPT);
2663 pktopt->ip6po_nexthop = NULL;
2664 }
2665 if (optname == -1 || optname == IPV6_HOPOPTS) {
2666 if (pktopt->ip6po_hbh)
2667 FREE(pktopt->ip6po_hbh, M_IP6OPT);
2668 pktopt->ip6po_hbh = NULL;
2669 }
2670 if (optname == -1 || optname == IPV6_RTHDRDSTOPTS) {
2671 if (pktopt->ip6po_dest1)
2672 FREE(pktopt->ip6po_dest1, M_IP6OPT);
2673 pktopt->ip6po_dest1 = NULL;
2674 }
2675 if (optname == -1 || optname == IPV6_RTHDR) {
2676 if (pktopt->ip6po_rhinfo.ip6po_rhi_rthdr)
2677 FREE(pktopt->ip6po_rhinfo.ip6po_rhi_rthdr, M_IP6OPT);
2678 pktopt->ip6po_rhinfo.ip6po_rhi_rthdr = NULL;
2679 if (pktopt->ip6po_route.ro_rt) {
2680 rtfree(pktopt->ip6po_route.ro_rt);
2681 pktopt->ip6po_route.ro_rt = NULL;
2682 }
2683 }
2684 if (optname == -1 || optname == IPV6_DSTOPTS) {
2685 if (pktopt->ip6po_dest2)
2686 FREE(pktopt->ip6po_dest2, M_IP6OPT);
2687 pktopt->ip6po_dest2 = NULL;
2688 }
2689 }
2690
2691 #define PKTOPT_EXTHDRCPY(type) \
2692 do {\
2693 if (src->type) {\
2694 int hlen =\
2695 (((struct ip6_ext *)src->type)->ip6e_len + 1) << 3;\
2696 dst->type = _MALLOC(hlen, M_IP6OPT, canwait);\
2697 if (dst->type == NULL && canwait == M_NOWAIT)\
2698 goto bad;\
2699 bcopy(src->type, dst->type, hlen);\
2700 }\
2701 } while (0)
2702
2703 static int
2704 copypktopts(struct ip6_pktopts *dst, struct ip6_pktopts *src, int canwait)
2705 {
2706 if (dst == NULL || src == NULL) {
2707 printf("ip6_clearpktopts: invalid argument\n");
2708 return (EINVAL);
2709 }
2710
2711 dst->ip6po_hlim = src->ip6po_hlim;
2712 dst->ip6po_tclass = src->ip6po_tclass;
2713 dst->ip6po_flags = src->ip6po_flags;
2714 if (src->ip6po_pktinfo) {
2715 dst->ip6po_pktinfo = _MALLOC(sizeof(*dst->ip6po_pktinfo),
2716 M_IP6OPT, canwait);
2717 if (dst->ip6po_pktinfo == NULL && canwait == M_NOWAIT)
2718 goto bad;
2719 *dst->ip6po_pktinfo = *src->ip6po_pktinfo;
2720 }
2721 if (src->ip6po_nexthop) {
2722 dst->ip6po_nexthop = _MALLOC(src->ip6po_nexthop->sa_len,
2723 M_IP6OPT, canwait);
2724 if (dst->ip6po_nexthop == NULL && canwait == M_NOWAIT)
2725 goto bad;
2726 bcopy(src->ip6po_nexthop, dst->ip6po_nexthop,
2727 src->ip6po_nexthop->sa_len);
2728 }
2729 PKTOPT_EXTHDRCPY(ip6po_hbh);
2730 PKTOPT_EXTHDRCPY(ip6po_dest1);
2731 PKTOPT_EXTHDRCPY(ip6po_dest2);
2732 PKTOPT_EXTHDRCPY(ip6po_rthdr); /* not copy the cached route */
2733 return (0);
2734
2735 bad:
2736 ip6_clearpktopts(dst, -1);
2737 return (ENOBUFS);
2738 }
2739 #undef PKTOPT_EXTHDRCPY
2740
2741 struct ip6_pktopts *
2742 ip6_copypktopts(struct ip6_pktopts *src, int canwait)
2743 {
2744 int error;
2745 struct ip6_pktopts *dst;
2746
2747 dst = _MALLOC(sizeof(*dst), M_IP6OPT, canwait);
2748 if (dst == NULL)
2749 return (NULL);
2750 ip6_initpktopts(dst);
2751
2752 if ((error = copypktopts(dst, src, canwait)) != 0) {
2753 FREE(dst, M_IP6OPT);
2754 return (NULL);
2755 }
2756
2757 return (dst);
2758 }
2759
2760 void
2761 ip6_freepcbopts(pktopt)
2762 struct ip6_pktopts *pktopt;
2763 {
2764 if (pktopt == NULL)
2765 return;
2766
2767 ip6_clearpktopts(pktopt, -1);
2768
2769 FREE(pktopt, M_IP6OPT);
2770 }
2771
2772 void
2773 ip6_moptions_init(void)
2774 {
2775 PE_parse_boot_argn("ifa_debug", &im6o_debug, sizeof (im6o_debug));
2776
2777 im6o_size = (im6o_debug == 0) ? sizeof (struct ip6_moptions) :
2778 sizeof (struct ip6_moptions_dbg);
2779
2780 im6o_zone = zinit(im6o_size, IM6O_ZONE_MAX * im6o_size, 0,
2781 IM6O_ZONE_NAME);
2782 if (im6o_zone == NULL) {
2783 panic("%s: failed allocating %s", __func__, IM6O_ZONE_NAME);
2784 /* NOTREACHED */
2785 }
2786 zone_change(im6o_zone, Z_EXPAND, TRUE);
2787 }
2788
2789 void
2790 im6o_addref(struct ip6_moptions *im6o, int locked)
2791 {
2792 if (!locked)
2793 IM6O_LOCK(im6o);
2794 else
2795 IM6O_LOCK_ASSERT_HELD(im6o);
2796
2797 if (++im6o->im6o_refcnt == 0) {
2798 panic("%s: im6o %p wraparound refcnt\n", __func__, im6o);
2799 /* NOTREACHED */
2800 } else if (im6o->im6o_trace != NULL) {
2801 (*im6o->im6o_trace)(im6o, TRUE);
2802 }
2803
2804 if (!locked)
2805 IM6O_UNLOCK(im6o);
2806 }
2807
2808 void
2809 im6o_remref(struct ip6_moptions *im6o)
2810 {
2811 int i;
2812
2813 IM6O_LOCK(im6o);
2814 if (im6o->im6o_refcnt == 0) {
2815 panic("%s: im6o %p negative refcnt", __func__, im6o);
2816 /* NOTREACHED */
2817 } else if (im6o->im6o_trace != NULL) {
2818 (*im6o->im6o_trace)(im6o, FALSE);
2819 }
2820
2821 --im6o->im6o_refcnt;
2822 if (im6o->im6o_refcnt > 0) {
2823 IM6O_UNLOCK(im6o);
2824 return;
2825 }
2826
2827 for (i = 0; i < im6o->im6o_num_memberships; ++i) {
2828 struct in6_mfilter *imf;
2829
2830 imf = im6o->im6o_mfilters ? &im6o->im6o_mfilters[i] : NULL;
2831 if (imf != NULL)
2832 im6f_leave(imf);
2833
2834 (void) in6_mc_leave(im6o->im6o_membership[i], imf);
2835
2836 if (imf != NULL)
2837 im6f_purge(imf);
2838
2839 IN6M_REMREF(im6o->im6o_membership[i]);
2840 im6o->im6o_membership[i] = NULL;
2841 }
2842 im6o->im6o_num_memberships = 0;
2843 if (im6o->im6o_mfilters != NULL) {
2844 FREE(im6o->im6o_mfilters, M_IN6MFILTER);
2845 im6o->im6o_mfilters = NULL;
2846 }
2847 if (im6o->im6o_membership != NULL) {
2848 FREE(im6o->im6o_membership, M_IP6MOPTS);
2849 im6o->im6o_membership = NULL;
2850 }
2851 IM6O_UNLOCK(im6o);
2852
2853 lck_mtx_destroy(&im6o->im6o_lock, ifa_mtx_grp);
2854
2855 if (!(im6o->im6o_debug & IFD_ALLOC)) {
2856 panic("%s: im6o %p cannot be freed", __func__, im6o);
2857 /* NOTREACHED */
2858 }
2859 zfree(im6o_zone, im6o);
2860 }
2861
2862 static void
2863 im6o_trace(struct ip6_moptions *im6o, int refhold)
2864 {
2865 struct ip6_moptions_dbg *im6o_dbg = (struct ip6_moptions_dbg *)im6o;
2866 ctrace_t *tr;
2867 u_int32_t idx;
2868 u_int16_t *cnt;
2869
2870 if (!(im6o->im6o_debug & IFD_DEBUG)) {
2871 panic("%s: im6o %p has no debug structure", __func__, im6o);
2872 /* NOTREACHED */
2873 }
2874 if (refhold) {
2875 cnt = &im6o_dbg->im6o_refhold_cnt;
2876 tr = im6o_dbg->im6o_refhold;
2877 } else {
2878 cnt = &im6o_dbg->im6o_refrele_cnt;
2879 tr = im6o_dbg->im6o_refrele;
2880 }
2881
2882 idx = atomic_add_16_ov(cnt, 1) % IM6O_TRACE_HIST_SIZE;
2883 ctrace_record(&tr[idx]);
2884 }
2885
2886 struct ip6_moptions *
2887 ip6_allocmoptions(int how)
2888 {
2889 struct ip6_moptions *im6o;
2890
2891 im6o = (how == M_WAITOK) ?
2892 zalloc(im6o_zone) : zalloc_noblock(im6o_zone);
2893 if (im6o != NULL) {
2894 bzero(im6o, im6o_size);
2895 lck_mtx_init(&im6o->im6o_lock, ifa_mtx_grp, ifa_mtx_attr);
2896 im6o->im6o_debug |= IFD_ALLOC;
2897 if (im6o_debug != 0) {
2898 im6o->im6o_debug |= IFD_DEBUG;
2899 im6o->im6o_trace = im6o_trace;
2900 }
2901 IM6O_ADDREF(im6o);
2902 }
2903
2904 return (im6o);
2905 }
2906
2907 /*
2908 * Set IPv6 outgoing packet options based on advanced API.
2909 */
2910 int
2911 ip6_setpktopts(struct mbuf *control, struct ip6_pktopts *opt,
2912 struct ip6_pktopts *stickyopt, int uproto)
2913 {
2914 struct cmsghdr *cm = 0;
2915
2916 if (control == NULL || opt == NULL)
2917 return (EINVAL);
2918
2919 ip6_initpktopts(opt);
2920 if (stickyopt) {
2921 int error;
2922
2923 /*
2924 * If stickyopt is provided, make a local copy of the options
2925 * for this particular packet, then override them by ancillary
2926 * objects.
2927 * XXX: copypktopts() does not copy the cached route to a next
2928 * hop (if any). This is not very good in terms of efficiency,
2929 * but we can allow this since this option should be rarely
2930 * used.
2931 */
2932 if ((error = copypktopts(opt, stickyopt, M_NOWAIT)) != 0)
2933 return (error);
2934 }
2935
2936 /*
2937 * XXX: Currently, we assume all the optional information is stored
2938 * in a single mbuf.
2939 */
2940 if (control->m_next)
2941 return (EINVAL);
2942
2943 if (control->m_len < CMSG_LEN(0))
2944 return (EINVAL);
2945
2946 for (cm = M_FIRST_CMSGHDR(control); cm; cm = M_NXT_CMSGHDR(control, cm)) {
2947 int error;
2948
2949 if (cm->cmsg_len < sizeof(struct cmsghdr) || cm->cmsg_len > control->m_len)
2950 return (EINVAL);
2951 if (cm->cmsg_level != IPPROTO_IPV6)
2952 continue;
2953
2954 error = ip6_setpktopt(cm->cmsg_type, CMSG_DATA(cm),
2955 cm->cmsg_len - CMSG_LEN(0), opt, 0, 1, uproto);
2956 if (error)
2957 return (error);
2958 }
2959
2960 return (0);
2961 }
2962 /*
2963 * Set a particular packet option, as a sticky option or an ancillary data
2964 * item. "len" can be 0 only when it's a sticky option.
2965 * We have 4 cases of combination of "sticky" and "cmsg":
2966 * "sticky=0, cmsg=0": impossible
2967 * "sticky=0, cmsg=1": RFC2292 or RFC3542 ancillary data
2968 * "sticky=1, cmsg=0": RFC3542 socket option
2969 * "sticky=1, cmsg=1": RFC2292 socket option
2970 */
2971 static int
2972 ip6_setpktopt(int optname, u_char *buf, int len, struct ip6_pktopts *opt,
2973 int sticky, int cmsg, int uproto)
2974 {
2975 int minmtupolicy, preftemp;
2976 int error;
2977
2978 if (!sticky && !cmsg) {
2979 #ifdef DIAGNOSTIC
2980 printf("ip6_setpktopt: impossible case\n");
2981 #endif
2982 return (EINVAL);
2983 }
2984
2985 /*
2986 * IPV6_2292xxx is for backward compatibility to RFC2292, and should
2987 * not be specified in the context of RFC3542. Conversely,
2988 * RFC3542 types should not be specified in the context of RFC2292.
2989 */
2990 if (!cmsg) {
2991 switch (optname) {
2992 case IPV6_2292PKTINFO:
2993 case IPV6_2292HOPLIMIT:
2994 case IPV6_2292NEXTHOP:
2995 case IPV6_2292HOPOPTS:
2996 case IPV6_2292DSTOPTS:
2997 case IPV6_2292RTHDR:
2998 case IPV6_2292PKTOPTIONS:
2999 return (ENOPROTOOPT);
3000 }
3001 }
3002 if (sticky && cmsg) {
3003 switch (optname) {
3004 case IPV6_PKTINFO:
3005 case IPV6_HOPLIMIT:
3006 case IPV6_NEXTHOP:
3007 case IPV6_HOPOPTS:
3008 case IPV6_DSTOPTS:
3009 case IPV6_RTHDRDSTOPTS:
3010 case IPV6_RTHDR:
3011 case IPV6_USE_MIN_MTU:
3012 case IPV6_DONTFRAG:
3013 case IPV6_TCLASS:
3014 case IPV6_PREFER_TEMPADDR: /* XXX: not an RFC3542 option */
3015 return (ENOPROTOOPT);
3016 }
3017 }
3018
3019 switch (optname) {
3020 case IPV6_2292PKTINFO:
3021 case IPV6_PKTINFO:
3022 {
3023 struct ifnet *ifp = NULL;
3024 struct in6_pktinfo *pktinfo;
3025
3026 if (len != sizeof(struct in6_pktinfo))
3027 return (EINVAL);
3028
3029 pktinfo = (struct in6_pktinfo *)buf;
3030
3031 /*
3032 * An application can clear any sticky IPV6_PKTINFO option by
3033 * doing a "regular" setsockopt with ipi6_addr being
3034 * in6addr_any and ipi6_ifindex being zero.
3035 * [RFC 3542, Section 6]
3036 */
3037 if (optname == IPV6_PKTINFO && opt->ip6po_pktinfo &&
3038 pktinfo->ipi6_ifindex == 0 &&
3039 IN6_IS_ADDR_UNSPECIFIED(&pktinfo->ipi6_addr)) {
3040 ip6_clearpktopts(opt, optname);
3041 break;
3042 }
3043
3044 if (uproto == IPPROTO_TCP && optname == IPV6_PKTINFO &&
3045 sticky && !IN6_IS_ADDR_UNSPECIFIED(&pktinfo->ipi6_addr)) {
3046 return (EINVAL);
3047 }
3048
3049 /* validate the interface index if specified. */
3050 ifnet_head_lock_shared();
3051
3052 if (pktinfo->ipi6_ifindex > if_index) {
3053 ifnet_head_done();
3054 return (ENXIO);
3055 }
3056
3057 if (pktinfo->ipi6_ifindex) {
3058 ifp = ifindex2ifnet[pktinfo->ipi6_ifindex];
3059 if (ifp == NULL) {
3060 ifnet_head_done();
3061 return (ENXIO);
3062 }
3063 }
3064
3065 ifnet_head_done();
3066
3067 /*
3068 * We store the address anyway, and let in6_selectsrc()
3069 * validate the specified address. This is because ipi6_addr
3070 * may not have enough information about its scope zone, and
3071 * we may need additional information (such as outgoing
3072 * interface or the scope zone of a destination address) to
3073 * disambiguate the scope.
3074 * XXX: the delay of the validation may confuse the
3075 * application when it is used as a sticky option.
3076 */
3077 if (opt->ip6po_pktinfo == NULL) {
3078 opt->ip6po_pktinfo = _MALLOC(sizeof(*pktinfo),
3079 M_IP6OPT, M_NOWAIT);
3080 if (opt->ip6po_pktinfo == NULL)
3081 return (ENOBUFS);
3082 }
3083 bcopy(pktinfo, opt->ip6po_pktinfo, sizeof(*pktinfo));
3084 break;
3085 }
3086
3087 case IPV6_2292HOPLIMIT:
3088 case IPV6_HOPLIMIT:
3089 {
3090 int *hlimp;
3091
3092 /*
3093 * RFC 3542 deprecated the usage of sticky IPV6_HOPLIMIT
3094 * to simplify the ordering among hoplimit options.
3095 */
3096 if (optname == IPV6_HOPLIMIT && sticky)
3097 return (ENOPROTOOPT);
3098
3099 if (len != sizeof(int))
3100 return (EINVAL);
3101 hlimp = (int *)buf;
3102 if (*hlimp < -1 || *hlimp > 255)
3103 return (EINVAL);
3104
3105 opt->ip6po_hlim = *hlimp;
3106 break;
3107 }
3108
3109 case IPV6_TCLASS:
3110 {
3111 int tclass;
3112
3113 if (len != sizeof(int))
3114 return (EINVAL);
3115 tclass = *(int *)buf;
3116 if (tclass < -1 || tclass > 255)
3117 return (EINVAL);
3118
3119 opt->ip6po_tclass = tclass;
3120 break;
3121 }
3122
3123 case IPV6_2292NEXTHOP:
3124 case IPV6_NEXTHOP:
3125 error = suser(kauth_cred_get(), 0);
3126 if (error)
3127 return (EACCES);
3128
3129 if (len == 0) { /* just remove the option */
3130 ip6_clearpktopts(opt, IPV6_NEXTHOP);
3131 break;
3132 }
3133
3134 /* check if cmsg_len is large enough for sa_len */
3135 if (len < sizeof(struct sockaddr) || len < *buf)
3136 return (EINVAL);
3137
3138 switch (((struct sockaddr *)buf)->sa_family) {
3139 case AF_INET6:
3140 {
3141 struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)buf;
3142
3143 if (sa6->sin6_len != sizeof(struct sockaddr_in6))
3144 return (EINVAL);
3145
3146 if (IN6_IS_ADDR_UNSPECIFIED(&sa6->sin6_addr) ||
3147 IN6_IS_ADDR_MULTICAST(&sa6->sin6_addr)) {
3148 return (EINVAL);
3149 }
3150 if ((error = sa6_embedscope(sa6, ip6_use_defzone))
3151 != 0) {
3152 return (error);
3153 }
3154 break;
3155 }
3156 case AF_LINK: /* should eventually be supported */
3157 default:
3158 return (EAFNOSUPPORT);
3159 }
3160
3161 /* turn off the previous option, then set the new option. */
3162 ip6_clearpktopts(opt, IPV6_NEXTHOP);
3163 opt->ip6po_nexthop = _MALLOC(*buf, M_IP6OPT, M_NOWAIT);
3164 if (opt->ip6po_nexthop == NULL)
3165 return (ENOBUFS);
3166 bcopy(buf, opt->ip6po_nexthop, *buf);
3167 break;
3168
3169 case IPV6_2292HOPOPTS:
3170 case IPV6_HOPOPTS:
3171 {
3172 struct ip6_hbh *hbh;
3173 int hbhlen;
3174
3175 /*
3176 * XXX: We don't allow a non-privileged user to set ANY HbH
3177 * options, since per-option restriction has too much
3178 * overhead.
3179 */
3180 error = suser(kauth_cred_get(), 0);
3181 if (error)
3182 return (EACCES);
3183
3184 if (len == 0) {
3185 ip6_clearpktopts(opt, IPV6_HOPOPTS);
3186 break; /* just remove the option */
3187 }
3188
3189 /* message length validation */
3190 if (len < sizeof(struct ip6_hbh))
3191 return (EINVAL);
3192 hbh = (struct ip6_hbh *)buf;
3193 hbhlen = (hbh->ip6h_len + 1) << 3;
3194 if (len != hbhlen)
3195 return (EINVAL);
3196
3197 /* turn off the previous option, then set the new option. */
3198 ip6_clearpktopts(opt, IPV6_HOPOPTS);
3199 opt->ip6po_hbh = _MALLOC(hbhlen, M_IP6OPT, M_NOWAIT);
3200 if (opt->ip6po_hbh == NULL)
3201 return (ENOBUFS);
3202 bcopy(hbh, opt->ip6po_hbh, hbhlen);
3203
3204 break;
3205 }
3206
3207 case IPV6_2292DSTOPTS:
3208 case IPV6_DSTOPTS:
3209 case IPV6_RTHDRDSTOPTS:
3210 {
3211 struct ip6_dest *dest, **newdest = NULL;
3212 int destlen;
3213
3214 error = suser(kauth_cred_get(), 0);
3215 if (error)
3216 return (EACCES);
3217
3218 if (len == 0) {
3219 ip6_clearpktopts(opt, optname);
3220 break; /* just remove the option */
3221 }
3222
3223 /* message length validation */
3224 if (len < sizeof(struct ip6_dest))
3225 return (EINVAL);
3226 dest = (struct ip6_dest *)buf;
3227 destlen = (dest->ip6d_len + 1) << 3;
3228 if (len != destlen)
3229 return (EINVAL);
3230
3231 /*
3232 * Determine the position that the destination options header
3233 * should be inserted; before or after the routing header.
3234 */
3235 switch (optname) {
3236 case IPV6_2292DSTOPTS:
3237 /*
3238 * The old advacned API is ambiguous on this point.
3239 * Our approach is to determine the position based
3240 * according to the existence of a routing header.
3241 * Note, however, that this depends on the order of the
3242 * extension headers in the ancillary data; the 1st
3243 * part of the destination options header must appear
3244 * before the routing header in the ancillary data,
3245 * too.
3246 * RFC3542 solved the ambiguity by introducing
3247 * separate ancillary data or option types.
3248 */
3249 if (opt->ip6po_rthdr == NULL)
3250 newdest = &opt->ip6po_dest1;
3251 else
3252 newdest = &opt->ip6po_dest2;
3253 break;
3254 case IPV6_RTHDRDSTOPTS:
3255 newdest = &opt->ip6po_dest1;
3256 break;
3257 case IPV6_DSTOPTS:
3258 newdest = &opt->ip6po_dest2;
3259 break;
3260 }
3261
3262 /* turn off the previous option, then set the new option. */
3263 ip6_clearpktopts(opt, optname);
3264 *newdest = _MALLOC(destlen, M_IP6OPT, M_NOWAIT);
3265 if (*newdest == NULL)
3266 return (ENOBUFS);
3267 bcopy(dest, *newdest, destlen);
3268
3269 break;
3270 }
3271
3272 case IPV6_2292RTHDR:
3273 case IPV6_RTHDR:
3274 {
3275 struct ip6_rthdr *rth;
3276 int rthlen;
3277
3278 if (len == 0) {
3279 ip6_clearpktopts(opt, IPV6_RTHDR);
3280 break; /* just remove the option */
3281 }
3282
3283 /* message length validation */
3284 if (len < sizeof(struct ip6_rthdr))
3285 return (EINVAL);
3286 rth = (struct ip6_rthdr *)buf;
3287 rthlen = (rth->ip6r_len + 1) << 3;
3288 if (len != rthlen)
3289 return (EINVAL);
3290
3291 switch (rth->ip6r_type) {
3292 case IPV6_RTHDR_TYPE_0:
3293 if (rth->ip6r_len == 0) /* must contain one addr */
3294 return (EINVAL);
3295 if (rth->ip6r_len % 2) /* length must be even */
3296 return (EINVAL);
3297 if (rth->ip6r_len / 2 != rth->ip6r_segleft)
3298 return (EINVAL);
3299 break;
3300 default:
3301 return (EINVAL); /* not supported */
3302 }
3303
3304 /* turn off the previous option */
3305 ip6_clearpktopts(opt, IPV6_RTHDR);
3306 opt->ip6po_rthdr = _MALLOC(rthlen, M_IP6OPT, M_NOWAIT);
3307 if (opt->ip6po_rthdr == NULL)
3308 return (ENOBUFS);
3309 bcopy(rth, opt->ip6po_rthdr, rthlen);
3310
3311 break;
3312 }
3313
3314 case IPV6_USE_MIN_MTU:
3315 if (len != sizeof(int))
3316 return (EINVAL);
3317 minmtupolicy = *(int *)buf;
3318 if (minmtupolicy != IP6PO_MINMTU_MCASTONLY &&
3319 minmtupolicy != IP6PO_MINMTU_DISABLE &&
3320 minmtupolicy != IP6PO_MINMTU_ALL) {
3321 return (EINVAL);
3322 }
3323 opt->ip6po_minmtu = minmtupolicy;
3324 break;
3325
3326 case IPV6_DONTFRAG:
3327 if (len != sizeof(int))
3328 return (EINVAL);
3329
3330 if (uproto == IPPROTO_TCP || *(int *)buf == 0) {
3331 /*
3332 * we ignore this option for TCP sockets.
3333 * (RFC3542 leaves this case unspecified.)
3334 */
3335 opt->ip6po_flags &= ~IP6PO_DONTFRAG;
3336 } else
3337 opt->ip6po_flags |= IP6PO_DONTFRAG;
3338 break;
3339
3340 case IPV6_PREFER_TEMPADDR:
3341 if (len != sizeof(int))
3342 return (EINVAL);
3343 preftemp = *(int *)buf;
3344 if (preftemp != IP6PO_TEMPADDR_SYSTEM &&
3345 preftemp != IP6PO_TEMPADDR_NOTPREFER &&
3346 preftemp != IP6PO_TEMPADDR_PREFER) {
3347 return (EINVAL);
3348 }
3349 opt->ip6po_prefer_tempaddr = preftemp;
3350 break;
3351
3352 default:
3353 return (ENOPROTOOPT);
3354 } /* end of switch */
3355
3356 return (0);
3357 }
3358
3359 /*
3360 * Routine called from ip6_output() to loop back a copy of an IP6 multicast
3361 * packet to the input queue of a specified interface. Note that this
3362 * calls the output routine of the loopback "driver", but with an interface
3363 * pointer that might NOT be &loif -- easier than replicating that code here.
3364 */
3365 void
3366 ip6_mloopback(
3367 struct ifnet *ifp,
3368 struct mbuf *m,
3369 struct sockaddr_in6 *dst)
3370 {
3371 struct mbuf *copym;
3372 struct ip6_hdr *ip6;
3373
3374 copym = m_copy(m, 0, M_COPYALL);
3375 if (copym == NULL)
3376 return;
3377
3378 /*
3379 * Make sure to deep-copy IPv6 header portion in case the data
3380 * is in an mbuf cluster, so that we can safely override the IPv6
3381 * header portion later.
3382 */
3383 if ((copym->m_flags & M_EXT) != 0 ||
3384 copym->m_len < sizeof(struct ip6_hdr)) {
3385 copym = m_pullup(copym, sizeof(struct ip6_hdr));
3386 if (copym == NULL)
3387 return;
3388 }
3389
3390 #if DIAGNOSTIC
3391 if (copym->m_len < sizeof(*ip6)) {
3392 m_freem(copym);
3393 return;
3394 }
3395 #endif
3396
3397 ip6 = mtod(copym, struct ip6_hdr *);
3398 /*
3399 * clear embedded scope identifiers if necessary.
3400 * in6_clearscope will touch the addresses only when necessary.
3401 */
3402 in6_clearscope(&ip6->ip6_src);
3403 in6_clearscope(&ip6->ip6_dst);
3404
3405 #ifdef __APPLE__
3406
3407 /* Makes sure the HW checksum flags are cleaned before sending the packet */
3408
3409 if ((copym->m_pkthdr.csum_flags & CSUM_DELAY_IPV6_DATA) != 0) {
3410 in6_delayed_cksum(copym, sizeof(struct ip6_hdr));
3411 copym->m_pkthdr.csum_flags &= ~CSUM_DELAY_IPV6_DATA;
3412 }
3413 copym->m_pkthdr.rcvif = 0;
3414 copym->m_pkthdr.csum_data = 0;
3415 copym->m_pkthdr.csum_flags = 0;
3416
3417 if (lo_ifp) {
3418 copym->m_pkthdr.rcvif = ifp;
3419 dlil_output(lo_ifp, PF_INET6, copym, 0, (struct sockaddr *)dst, 0);
3420 } else
3421 m_free(copym);
3422 #else
3423 (void)if_simloop(ifp, copym, dst->sin6_family, NULL);
3424 #endif
3425 }
3426
3427 /*
3428 * Chop IPv6 header off from the payload.
3429 */
3430 static int
3431 ip6_splithdr(m, exthdrs)
3432 struct mbuf *m;
3433 struct ip6_exthdrs *exthdrs;
3434 {
3435 struct mbuf *mh;
3436 struct ip6_hdr *ip6;
3437
3438 ip6 = mtod(m, struct ip6_hdr *);
3439 if (m->m_len > sizeof(*ip6)) {
3440 MGETHDR(mh, M_DONTWAIT, MT_HEADER); /* MAC-OK */
3441 if (mh == 0) {
3442 m_freem(m);
3443 return ENOBUFS;
3444 }
3445 M_COPY_PKTHDR(mh, m);
3446 MH_ALIGN(mh, sizeof(*ip6));
3447 m->m_flags &= ~M_PKTHDR;
3448 m->m_len -= sizeof(*ip6);
3449 m->m_data += sizeof(*ip6);
3450 mh->m_next = m;
3451 m = mh;
3452 m->m_len = sizeof(*ip6);
3453 bcopy((caddr_t)ip6, mtod(m, caddr_t), sizeof(*ip6));
3454 }
3455 exthdrs->ip6e_ip6 = m;
3456 return 0;
3457 }
3458
3459 /*
3460 * Compute IPv6 extension header length.
3461 */
3462 int
3463 ip6_optlen(in6p)
3464 struct in6pcb *in6p;
3465 {
3466 int len;
3467
3468 if (!in6p->in6p_outputopts)
3469 return 0;
3470
3471 len = 0;
3472 #define elen(x) \
3473 (((struct ip6_ext *)(x)) ? (((struct ip6_ext *)(x))->ip6e_len + 1) << 3 : 0)
3474
3475 len += elen(in6p->in6p_outputopts->ip6po_hbh);
3476 if (in6p->in6p_outputopts->ip6po_rthdr)
3477 /* dest1 is valid with rthdr only */
3478 len += elen(in6p->in6p_outputopts->ip6po_dest1);
3479 len += elen(in6p->in6p_outputopts->ip6po_rthdr);
3480 len += elen(in6p->in6p_outputopts->ip6po_dest2);
3481 return len;
3482 #undef elen
3483 }