]> git.saurik.com Git - apple/xnu.git/blame - bsd/netinet6/ip6_output.c
xnu-1504.3.12.tar.gz
[apple/xnu.git] / bsd / netinet6 / ip6_output.c
CommitLineData
b0d623f7
A
1/*
2 * Copyright (c) 2008 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
55e303ae
A
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 $ */
1c79356b
A
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 */
2d21ac55
A
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 */
1c79356b
A
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>
1c79356b 110#include <sys/kernel.h>
1c79356b 111#include <sys/proc.h>
91447636 112#include <sys/kauth.h>
1c79356b
A
113
114#include <net/if.h>
115#include <net/route.h>
2d21ac55 116#include <net/dlil.h>
1c79356b
A
117
118#include <netinet/in.h>
119#include <netinet/in_var.h>
55e303ae 120#include <netinet/ip_var.h>
9bccf70c 121#include <netinet6/in6_var.h>
1c79356b
A
122#include <netinet/ip6.h>
123#include <netinet/icmp6.h>
124#include <netinet6/ip6_var.h>
1c79356b 125#include <netinet/in_pcb.h>
1c79356b
A
126#include <netinet6/nd6.h>
127
128#if IPSEC
129#include <netinet6/ipsec.h>
9bccf70c
A
130#if INET6
131#include <netinet6/ipsec6.h>
132#endif
1c79356b 133#include <netkey/key.h>
9bccf70c 134extern int ipsec_bypass;
1c79356b 135#endif /* IPSEC */
2d21ac55
A
136extern lck_mtx_t *nd6_mutex;
137
138#if CONFIG_MACF_NET
139#include <security/mac.h>
140#endif /* MAC_NET */
1c79356b 141
9bccf70c 142#include <netinet6/ip6_fw.h>
1c79356b
A
143
144#include <net/net_osdep.h>
145
91447636
A
146#include <netinet/kpi_ipfilter_var.h>
147
b0d623f7
A
148#if PF
149#include <net/pfvar.h>
150#endif /* PF */
151
9bccf70c 152#ifndef __APPLE__
1c79356b
A
153static MALLOC_DEFINE(M_IPMOPTS, "ip6_moptions", "internet multicast options");
154#endif
155
156struct ip6_exthdrs {
157 struct mbuf *ip6e_ip6;
158 struct mbuf *ip6e_hbh;
159 struct mbuf *ip6e_dest1;
160 struct mbuf *ip6e_rthdr;
161 struct mbuf *ip6e_dest2;
162};
163
91447636
A
164static int ip6_pcbopts(struct ip6_pktopts **, struct mbuf *,
165 struct socket *, struct sockopt *sopt);
b0d623f7
A
166static int ip6_pcbopt(int optname, u_char *buf, int len, struct ip6_pktopts **pktopt);
167static int ip6_getpcbopt(struct ip6_pktopts *pktopt, int optname, struct sockopt *sopt);
168static int ip6_setpktopt(int optname, u_char *buf, int len, struct ip6_pktopts *opt);
91447636
A
169static int ip6_setmoptions(int, struct inpcb *, struct mbuf *);
170static int ip6_getmoptions(int, struct ip6_moptions *, struct mbuf **);
171static int ip6_copyexthdr(struct mbuf **, caddr_t, int);
172static int ip6_insertfraghdr(struct mbuf *, struct mbuf *, int,
173 struct ip6_frag **);
174static int ip6_insert_jumboopt(struct ip6_exthdrs *, u_int32_t);
175static int ip6_splithdr(struct mbuf *, struct ip6_exthdrs *);
1c79356b 176
55e303ae
A
177extern int ip_createmoptions(struct ip_moptions **imop);
178extern int ip_addmembership(struct ip_moptions *imo, struct ip_mreq *mreq);
179extern int ip_dropmembership(struct ip_moptions *imo, struct ip_mreq *mreq);
91447636 180extern lck_mtx_t *ip6_mutex;
55e303ae 181
1c79356b
A
182/*
183 * IP6 output. The packet in mbuf chain m contains a skeletal IP6
184 * header (with pri, len, nxt, hlim, src, dst).
185 * This function may modify ver and hlim only.
186 * The mbuf chain containing the packet will be freed.
187 * The mbuf opt, if present, will not be freed.
9bccf70c 188 *
b0d623f7
A
189 * type of "mtu": rt_rmx.rmx_mtu is u_int32_t, ifnet.ifr_mtu is int, and
190 * nd_ifinfo.linkmtu is u_int32_t. so we use u_int32_t to hold largest one,
9bccf70c 191 * which is rt_rmx.rmx_mtu.
1c79356b
A
192 */
193int
91447636
A
194ip6_output(
195 struct mbuf *m0,
196 struct ip6_pktopts *opt,
197 struct route_in6 *ro,
198 int flags,
199 struct ip6_moptions *im6o,
200 struct ifnet **ifpp, /* XXX: just for statistics */
201 int locked)
1c79356b
A
202{
203 struct ip6_hdr *ip6, *mhip6;
9bccf70c 204 struct ifnet *ifp, *origifp;
1c79356b
A
205 struct mbuf *m = m0;
206 int hlen, tlen, len, off;
207 struct route_in6 ip6route;
208 struct sockaddr_in6 *dst;
209 int error = 0;
9bccf70c 210 struct in6_ifaddr *ia = NULL;
b0d623f7 211 u_int32_t mtu;
1c79356b
A
212 u_int32_t optlen = 0, plen = 0, unfragpartlen = 0;
213 struct ip6_exthdrs exthdrs;
214 struct in6_addr finaldst;
215 struct route_in6 *ro_pmtu = NULL;
216 int hdrsplit = 0;
217 int needipsec = 0;
91447636
A
218 ipfilter_t inject_filter_ref;
219
1c79356b
A
220#if IPSEC
221 int needipsectun = 0;
9bccf70c 222 struct socket *so = NULL;
1c79356b
A
223 struct secpolicy *sp = NULL;
224
91447636
A
225 if (!locked)
226 lck_mtx_lock(ip6_mutex);
1c79356b 227 /* for AH processing. stupid to have "socket" variable in IP layer... */
9bccf70c
A
228 if (ipsec_bypass == 0)
229 {
230 so = ipsec_getsocket(m);
231 (void)ipsec_setsocket(m, NULL);
232 }
1c79356b
A
233#endif /* IPSEC */
234
91447636
A
235 ip6 = mtod(m, struct ip6_hdr *);
236 inject_filter_ref = ipf_get_inject_filter(m);
237
9bccf70c
A
238#define MAKE_EXTHDR(hp, mp) \
239 do { \
1c79356b
A
240 if (hp) { \
241 struct ip6_ext *eh = (struct ip6_ext *)(hp); \
242 error = ip6_copyexthdr((mp), (caddr_t)(hp), \
243 ((eh)->ip6e_len + 1) << 3); \
244 if (error) \
245 goto freehdrs; \
246 } \
9bccf70c 247 } while (0)
1c79356b
A
248
249 bzero(&exthdrs, sizeof(exthdrs));
250
1c79356b
A
251 if (opt) {
252 /* Hop-by-Hop options header */
253 MAKE_EXTHDR(opt->ip6po_hbh, &exthdrs.ip6e_hbh);
9bccf70c
A
254 /* Destination options header(1st part) */
255 MAKE_EXTHDR(opt->ip6po_dest1, &exthdrs.ip6e_dest1);
1c79356b
A
256 /* Routing header */
257 MAKE_EXTHDR(opt->ip6po_rthdr, &exthdrs.ip6e_rthdr);
258 /* Destination options header(2nd part) */
259 MAKE_EXTHDR(opt->ip6po_dest2, &exthdrs.ip6e_dest2);
260 }
261
262#if IPSEC
9bccf70c
A
263 if (ipsec_bypass != 0)
264 goto skip_ipsec;
91447636 265
1c79356b
A
266 /* get a security policy for this packet */
267 if (so == NULL)
268 sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, 0, &error);
269 else
270 sp = ipsec6_getpolicybysock(m, IPSEC_DIR_OUTBOUND, so, &error);
271
272 if (sp == NULL) {
2d21ac55 273 IPSEC_STAT_INCREMENT(ipsec6stat.out_inval);
9bccf70c 274 goto freehdrs;
1c79356b
A
275 }
276
277 error = 0;
278
279 /* check policy */
280 switch (sp->policy) {
281 case IPSEC_POLICY_DISCARD:
2d21ac55 282 case IPSEC_POLICY_GENERATE:
1c79356b
A
283 /*
284 * This packet is just discarded.
285 */
2d21ac55 286 IPSEC_STAT_INCREMENT(ipsec6stat.out_polvio);
9bccf70c 287 goto freehdrs;
1c79356b
A
288
289 case IPSEC_POLICY_BYPASS:
290 case IPSEC_POLICY_NONE:
291 /* no need to do IPsec. */
292 needipsec = 0;
293 break;
294
295 case IPSEC_POLICY_IPSEC:
296 if (sp->req == NULL) {
297 /* acquire a policy */
298 error = key_spdacquire(sp);
9bccf70c 299 goto freehdrs;
1c79356b
A
300 }
301 needipsec = 1;
302 break;
303
304 case IPSEC_POLICY_ENTRUST:
305 default:
306 printf("ip6_output: Invalid policy found. %d\n", sp->policy);
307 }
9bccf70c 308 skip_ipsec:
1c79356b
A
309#endif /* IPSEC */
310
311 /*
312 * Calculate the total length of the extension header chain.
313 * Keep the length of the unfragmentable part for fragmentation.
314 */
315 optlen = 0;
316 if (exthdrs.ip6e_hbh) optlen += exthdrs.ip6e_hbh->m_len;
317 if (exthdrs.ip6e_dest1) optlen += exthdrs.ip6e_dest1->m_len;
318 if (exthdrs.ip6e_rthdr) optlen += exthdrs.ip6e_rthdr->m_len;
319 unfragpartlen = optlen + sizeof(struct ip6_hdr);
320 /* NOTE: we don't add AH/ESP length here. do that later. */
321 if (exthdrs.ip6e_dest2) optlen += exthdrs.ip6e_dest2->m_len;
322
323 /*
324 * If we need IPsec, or there is at least one extension header,
325 * separate IP6 header from the payload.
326 */
327 if ((needipsec || optlen) && !hdrsplit) {
328 if ((error = ip6_splithdr(m, &exthdrs)) != 0) {
329 m = NULL;
330 goto freehdrs;
331 }
332 m = exthdrs.ip6e_ip6;
333 hdrsplit++;
334 }
335
336 /* adjust pointer */
337 ip6 = mtod(m, struct ip6_hdr *);
338
339 /* adjust mbuf packet header length */
340 m->m_pkthdr.len += optlen;
341 plen = m->m_pkthdr.len - sizeof(*ip6);
342
343 /* If this is a jumbo payload, insert a jumbo payload option. */
344 if (plen > IPV6_MAXPACKET) {
345 if (!hdrsplit) {
346 if ((error = ip6_splithdr(m, &exthdrs)) != 0) {
347 m = NULL;
348 goto freehdrs;
349 }
350 m = exthdrs.ip6e_ip6;
351 hdrsplit++;
352 }
353 /* adjust pointer */
354 ip6 = mtod(m, struct ip6_hdr *);
355 if ((error = ip6_insert_jumboopt(&exthdrs, plen)) != 0)
356 goto freehdrs;
357 ip6->ip6_plen = 0;
358 } else
359 ip6->ip6_plen = htons(plen);
360
361 /*
362 * Concatenate headers and fill in next header fields.
363 * Here we have, on "m"
364 * IPv6 payload
365 * and we insert headers accordingly. Finally, we should be getting:
366 * IPv6 hbh dest1 rthdr ah* [esp* dest2 payload]
367 *
368 * during the header composing process, "m" points to IPv6 header.
369 * "mprev" points to an extension header prior to esp.
370 */
371 {
372 u_char *nexthdrp = &ip6->ip6_nxt;
373 struct mbuf *mprev = m;
374
375 /*
376 * we treat dest2 specially. this makes IPsec processing
55e303ae
A
377 * much easier. the goal here is to make mprev point the
378 * mbuf prior to dest2.
1c79356b
A
379 *
380 * result: IPv6 dest2 payload
381 * m and mprev will point to IPv6 header.
382 */
383 if (exthdrs.ip6e_dest2) {
384 if (!hdrsplit)
385 panic("assumption failed: hdr not split");
386 exthdrs.ip6e_dest2->m_next = m->m_next;
387 m->m_next = exthdrs.ip6e_dest2;
388 *mtod(exthdrs.ip6e_dest2, u_char *) = ip6->ip6_nxt;
389 ip6->ip6_nxt = IPPROTO_DSTOPTS;
390 }
391
9bccf70c
A
392#define MAKE_CHAIN(m, mp, p, i)\
393 do {\
1c79356b
A
394 if (m) {\
395 if (!hdrsplit) \
396 panic("assumption failed: hdr not split"); \
397 *mtod((m), u_char *) = *(p);\
398 *(p) = (i);\
399 p = mtod((m), u_char *);\
400 (m)->m_next = (mp)->m_next;\
401 (mp)->m_next = (m);\
402 (mp) = (m);\
403 }\
9bccf70c 404 } while (0)
1c79356b
A
405 /*
406 * result: IPv6 hbh dest1 rthdr dest2 payload
407 * m will point to IPv6 header. mprev will point to the
408 * extension header prior to dest2 (rthdr in the above case).
409 */
410 MAKE_CHAIN(exthdrs.ip6e_hbh, mprev,
411 nexthdrp, IPPROTO_HOPOPTS);
412 MAKE_CHAIN(exthdrs.ip6e_dest1, mprev,
413 nexthdrp, IPPROTO_DSTOPTS);
414 MAKE_CHAIN(exthdrs.ip6e_rthdr, mprev,
415 nexthdrp, IPPROTO_ROUTING);
416
91447636
A
417 if (!TAILQ_EMPTY(&ipv6_filters)) {
418 struct ipfilter *filter;
419 int seen = (inject_filter_ref == 0);
420 int fixscope = 0;
421 struct ipf_pktopts *ippo = 0, ipf_pktopts;
422
423 if (im6o != NULL && IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
424 ippo = &ipf_pktopts;
425 ippo->ippo_flags = IPPOF_MCAST_OPTS;
426 ippo->ippo_mcast_ifnet = im6o->im6o_multicast_ifp;
427 ippo->ippo_mcast_ttl = im6o->im6o_multicast_hlim;
428 ippo->ippo_mcast_loop = im6o->im6o_multicast_loop;
429 }
430
431 /* Hack: embed the scope_id in the destination */
432 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst) &&
433 (ip6->ip6_dst.s6_addr16[1] == 0) && (ro != NULL)) {
434 fixscope = 1;
435 ip6->ip6_dst.s6_addr16[1] = htons(ro->ro_dst.sin6_scope_id);
436 }
437 {
438 lck_mtx_unlock(ip6_mutex);
439 ipf_ref();
440 TAILQ_FOREACH(filter, &ipv6_filters, ipf_link) {
441 /*
442 * No need to proccess packet twice if we've
443 * already seen it
444 */
445 if (seen == 0) {
446 if ((struct ipfilter *)inject_filter_ref == filter)
447 seen = 1;
448 } else if (filter->ipf_filter.ipf_output) {
449 errno_t result;
450
451 result = filter->ipf_filter.ipf_output(filter->ipf_filter.cookie, (mbuf_t*)&m, ippo);
452 if (result == EJUSTRETURN) {
453 ipf_unref();
454 locked = 1; /* Don't want to take lock to unlock it right away */
455 goto done;
456 }
457 if (result != 0) {
458 ipf_unref();
459 locked = 1; /* Don't want to take lock to unlock it right away */
460 goto bad;
461 }
462 }
463 }
464 ipf_unref();
465 lck_mtx_lock(ip6_mutex);
466 }
6601e61a 467 ip6 = mtod(m, struct ip6_hdr *);
91447636
A
468 /* Hack: cleanup embedded scope_id if we put it there */
469 if (fixscope)
470 ip6->ip6_dst.s6_addr16[1] = 0;
471 }
472
1c79356b
A
473#if IPSEC
474 if (!needipsec)
475 goto skip_ipsec2;
476
477 /*
478 * pointers after IPsec headers are not valid any more.
479 * other pointers need a great care too.
480 * (IPsec routines should not mangle mbufs prior to AH/ESP)
481 */
482 exthdrs.ip6e_dest2 = NULL;
483
484 {
485 struct ip6_rthdr *rh = NULL;
486 int segleft_org = 0;
487 struct ipsec_output_state state;
488
489 if (exthdrs.ip6e_rthdr) {
490 rh = mtod(exthdrs.ip6e_rthdr, struct ip6_rthdr *);
491 segleft_org = rh->ip6r_segleft;
492 rh->ip6r_segleft = 0;
493 }
494
495 bzero(&state, sizeof(state));
496 state.m = m;
13fec989 497 lck_mtx_unlock(ip6_mutex);
1c79356b
A
498 error = ipsec6_output_trans(&state, nexthdrp, mprev, sp, flags,
499 &needipsectun);
13fec989 500 lck_mtx_lock(ip6_mutex);
1c79356b
A
501 m = state.m;
502 if (error) {
503 /* mbuf is already reclaimed in ipsec6_output_trans. */
504 m = NULL;
505 switch (error) {
506 case EHOSTUNREACH:
507 case ENETUNREACH:
508 case EMSGSIZE:
509 case ENOBUFS:
510 case ENOMEM:
511 break;
512 default:
513 printf("ip6_output (ipsec): error code %d\n", error);
55e303ae 514 /* fall through */
1c79356b
A
515 case ENOENT:
516 /* don't show these error codes to the user */
517 error = 0;
518 break;
519 }
520 goto bad;
521 }
522 if (exthdrs.ip6e_rthdr) {
523 /* ah6_output doesn't modify mbuf chain */
524 rh->ip6r_segleft = segleft_org;
525 }
526 }
527skip_ipsec2:;
528#endif
529 }
530
531 /*
532 * If there is a routing header, replace destination address field
533 * with the first hop of the routing header.
534 */
535 if (exthdrs.ip6e_rthdr) {
536 struct ip6_rthdr *rh =
537 (struct ip6_rthdr *)(mtod(exthdrs.ip6e_rthdr,
538 struct ip6_rthdr *));
539 struct ip6_rthdr0 *rh0;
1c79356b
A
540
541 finaldst = ip6->ip6_dst;
9bccf70c 542 switch (rh->ip6r_type) {
1c79356b
A
543 case IPV6_RTHDR_TYPE_0:
544 rh0 = (struct ip6_rthdr0 *)rh;
9bccf70c
A
545 ip6->ip6_dst = rh0->ip6r0_addr[0];
546 bcopy((caddr_t)&rh0->ip6r0_addr[1],
547 (caddr_t)&rh0->ip6r0_addr[0],
548 sizeof(struct in6_addr)*(rh0->ip6r0_segleft - 1)
1c79356b 549 );
9bccf70c 550 rh0->ip6r0_addr[rh0->ip6r0_segleft - 1] = finaldst;
1c79356b
A
551 break;
552 default: /* is it possible? */
553 error = EINVAL;
554 goto bad;
555 }
556 }
557
558 /* Source address validation */
559 if (IN6_IS_ADDR_UNSPECIFIED(&ip6->ip6_src) &&
560 (flags & IPV6_DADOUTPUT) == 0) {
561 error = EOPNOTSUPP;
562 ip6stat.ip6s_badscope++;
563 goto bad;
564 }
565 if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_src)) {
566 error = EOPNOTSUPP;
567 ip6stat.ip6s_badscope++;
568 goto bad;
569 }
570
571 ip6stat.ip6s_localout++;
572
573 /*
574 * Route packet.
575 */
576 if (ro == 0) {
577 ro = &ip6route;
578 bzero((caddr_t)ro, sizeof(*ro));
579 }
580 ro_pmtu = ro;
581 if (opt && opt->ip6po_rthdr)
582 ro = &opt->ip6po_route;
583 dst = (struct sockaddr_in6 *)&ro->ro_dst;
584 /*
b0d623f7
A
585 * If there is a cached route, check that it is to the same
586 * destination and is still up. If not, free it and try again.
587 * Test rt_flags without holding rt_lock for performance reasons;
588 * if the route is down it will hopefully be caught by the layer
589 * below (since it uses this route as a hint) or during the
590 * next transmit.
1c79356b 591 */
b0d623f7
A
592 if (ro->ro_rt != NULL && (!(ro->ro_rt->rt_flags & RTF_UP) ||
593 dst->sin6_family != AF_INET6 ||
594 !IN6_ARE_ADDR_EQUAL(&dst->sin6_addr, &ip6->ip6_dst) ||
595 ro->ro_rt->generation_id != route_generation)) {
9bccf70c 596 rtfree(ro->ro_rt);
b0d623f7 597 ro->ro_rt = NULL;
1c79356b 598 }
b0d623f7 599 if (ro->ro_rt == NULL) {
1c79356b
A
600 bzero(dst, sizeof(*dst));
601 dst->sin6_family = AF_INET6;
602 dst->sin6_len = sizeof(struct sockaddr_in6);
603 dst->sin6_addr = ip6->ip6_dst;
9bccf70c
A
604#if SCOPEDROUTING
605 /* XXX: sin6_scope_id should already be fixed at this point */
606 if (IN6_IS_SCOPE_LINKLOCAL(&dst->sin6_addr))
607 dst->sin6_scope_id = ntohs(dst->sin6_addr.s6_addr16[1]);
608#endif
1c79356b
A
609 }
610#if IPSEC
611 if (needipsec && needipsectun) {
612 struct ipsec_output_state state;
2d21ac55 613 int tunneledv4 = 0;
1c79356b
A
614
615 /*
616 * All the extension headers will become inaccessible
617 * (since they can be encrypted).
618 * Don't panic, we need no more updates to extension headers
619 * on inner IPv6 packet (since they are now encapsulated).
620 *
621 * IPv6 [ESP|AH] IPv6 [extension headers] payload
622 */
623 bzero(&exthdrs, sizeof(exthdrs));
624 exthdrs.ip6e_ip6 = m;
625
626 bzero(&state, sizeof(state));
627 state.m = m;
628 state.ro = (struct route *)ro;
629 state.dst = (struct sockaddr *)dst;
13fec989 630 lck_mtx_unlock(ip6_mutex);
2d21ac55 631 error = ipsec6_output_tunnel(&state, sp, flags, &tunneledv4);
13fec989 632 lck_mtx_lock(ip6_mutex);
2d21ac55
A
633 if (tunneledv4) /* tunneled in IPv4 - packet is gone */
634 goto done;
1c79356b
A
635 m = state.m;
636 ro = (struct route_in6 *)state.ro;
637 dst = (struct sockaddr_in6 *)state.dst;
638 if (error) {
639 /* mbuf is already reclaimed in ipsec6_output_tunnel. */
640 m0 = m = NULL;
641 m = NULL;
642 switch (error) {
643 case EHOSTUNREACH:
644 case ENETUNREACH:
645 case EMSGSIZE:
646 case ENOBUFS:
647 case ENOMEM:
648 break;
649 default:
650 printf("ip6_output (ipsec): error code %d\n", error);
55e303ae 651 /* fall through */
1c79356b
A
652 case ENOENT:
653 /* don't show these error codes to the user */
654 error = 0;
655 break;
656 }
657 goto bad;
658 }
659
660 exthdrs.ip6e_ip6 = m;
661 }
55e303ae 662#endif /* IPSEC */
1c79356b
A
663
664 if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
665 /* Unicast */
666
667#define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa))
668#define sin6tosa(sin6) ((struct sockaddr *)(sin6))
669 /* xxx
670 * interface selection comes here
671 * if an interface is specified from an upper layer,
672 * ifp must point it.
673 */
b0d623f7 674 if (ro->ro_rt == NULL) {
1c79356b
A
675 /*
676 * non-bsdi always clone routes, if parent is
677 * PRF_CLONING.
678 */
b0d623f7 679 rtalloc_ign((struct route *)ro, 0);
1c79356b 680 }
b0d623f7 681 if (ro->ro_rt == NULL) {
1c79356b
A
682 ip6stat.ip6s_noroute++;
683 error = EHOSTUNREACH;
684 /* XXX in6_ifstat_inc(ifp, ifs6_out_discard); */
685 goto bad;
686 }
b0d623f7 687 RT_LOCK_SPIN(ro->ro_rt);
1c79356b 688 ia = ifatoia6(ro->ro_rt->rt_ifa);
b0d623f7
A
689 if (ia != NULL)
690 ifaref(&ia->ia_ifa);
1c79356b
A
691 ifp = ro->ro_rt->rt_ifp;
692 ro->ro_rt->rt_use++;
693 if (ro->ro_rt->rt_flags & RTF_GATEWAY)
694 dst = (struct sockaddr_in6 *)ro->ro_rt->rt_gateway;
b0d623f7 695 RT_UNLOCK(ro->ro_rt);
1c79356b
A
696 m->m_flags &= ~(M_BCAST | M_MCAST); /* just in case */
697
698 in6_ifstat_inc(ifp, ifs6_out_request);
699
700 /*
701 * Check if the outgoing interface conflicts with
702 * the interface specified by ifi6_ifindex (if specified).
703 * Note that loopback interface is always okay.
704 * (this may happen when we are sending a packet to one of
705 * our own addresses.)
706 */
707 if (opt && opt->ip6po_pktinfo
708 && opt->ip6po_pktinfo->ipi6_ifindex) {
709 if (!(ifp->if_flags & IFF_LOOPBACK)
710 && ifp->if_index != opt->ip6po_pktinfo->ipi6_ifindex) {
711 ip6stat.ip6s_noroute++;
712 in6_ifstat_inc(ifp, ifs6_out_discard);
713 error = EHOSTUNREACH;
714 goto bad;
715 }
716 }
717
b0d623f7
A
718 /*
719 * if specified, try to fill in the traffic class field.
720 * do not override if a non-zero value is already set.
721 * we check the diffserv field and the ecn field separately.
722 */
723 if (opt && opt->ip6po_tclass >= 0) {
724 int mask = 0;
725
726 if ((ip6->ip6_flow & htonl(0xfc << 20)) == 0)
727 mask |= 0xfc;
728 if ((ip6->ip6_flow & htonl(0x03 << 20)) == 0)
729 mask |= 0x03;
730 if (mask != 0)
731 ip6->ip6_flow |= htonl((opt->ip6po_tclass & mask) << 20);
732 }
733
1c79356b
A
734 if (opt && opt->ip6po_hlim != -1)
735 ip6->ip6_hlim = opt->ip6po_hlim & 0xff;
736 } else {
737 /* Multicast */
738 struct in6_multi *in6m;
739
740 m->m_flags = (m->m_flags & ~M_BCAST) | M_MCAST;
741
742 /*
743 * See if the caller provided any multicast options
744 */
745 ifp = NULL;
746 if (im6o != NULL) {
747 ip6->ip6_hlim = im6o->im6o_multicast_hlim;
748 if (im6o->im6o_multicast_ifp != NULL)
749 ifp = im6o->im6o_multicast_ifp;
750 } else
751 ip6->ip6_hlim = ip6_defmcasthlim;
752
753 /*
754 * See if the caller provided the outgoing interface
755 * as an ancillary data.
756 * Boundary check for ifindex is assumed to be already done.
757 */
b0d623f7
A
758 if (opt && opt->ip6po_pktinfo && opt->ip6po_pktinfo->ipi6_ifindex) {
759 unsigned int index = opt->ip6po_pktinfo->ipi6_ifindex;
760 ifnet_head_lock_shared();
761 if (index > 0 && index <= if_index) {
762 ifp = ifindex2ifnet[index];
763 }
764 ifnet_head_done();
765 }
1c79356b
A
766
767 /*
768 * If the destination is a node-local scope multicast,
769 * the packet should be loop-backed only.
770 */
771 if (IN6_IS_ADDR_MC_NODELOCAL(&ip6->ip6_dst)) {
772 /*
773 * If the outgoing interface is already specified,
774 * it should be a loopback interface.
775 */
776 if (ifp && (ifp->if_flags & IFF_LOOPBACK) == 0) {
777 ip6stat.ip6s_badscope++;
778 error = ENETUNREACH; /* XXX: better error? */
779 /* XXX correct ifp? */
780 in6_ifstat_inc(ifp, ifs6_out_discard);
781 goto bad;
782 } else {
2d21ac55 783 ifp = lo_ifp;
1c79356b
A
784 }
785 }
786
b0d623f7
A
787 /*
788 * if specified, try to fill in the traffic class field.
789 * do not override if a non-zero value is already set.
790 * we check the diffserv field and the ecn field separately.
791 */
792 if (opt && opt->ip6po_tclass >= 0) {
793 int mask = 0;
794
795 if ((ip6->ip6_flow & htonl(0xfc << 20)) == 0)
796 mask |= 0xfc;
797 if ((ip6->ip6_flow & htonl(0x03 << 20)) == 0)
798 mask |= 0x03;
799 if (mask != 0)
800 ip6->ip6_flow |= htonl((opt->ip6po_tclass & mask) << 20);
801 }
802
1c79356b
A
803 if (opt && opt->ip6po_hlim != -1)
804 ip6->ip6_hlim = opt->ip6po_hlim & 0xff;
805
806 /*
807 * If caller did not provide an interface lookup a
808 * default in the routing table. This is either a
809 * default for the speicfied group (i.e. a host
810 * route), or a multicast default (a route for the
811 * ``net'' ff00::/8).
812 */
813 if (ifp == NULL) {
b0d623f7
A
814 if (ro->ro_rt == NULL) {
815 ro->ro_rt = rtalloc1(
816 (struct sockaddr *)&ro->ro_dst, 0, 0);
1c79356b 817 }
b0d623f7 818 if (ro->ro_rt == NULL) {
1c79356b
A
819 ip6stat.ip6s_noroute++;
820 error = EHOSTUNREACH;
821 /* XXX in6_ifstat_inc(ifp, ifs6_out_discard) */
822 goto bad;
823 }
b0d623f7 824 RT_LOCK_SPIN(ro->ro_rt);
1c79356b 825 ia = ifatoia6(ro->ro_rt->rt_ifa);
b0d623f7
A
826 if (ia != NULL)
827 ifaref(&ia->ia_ifa);
1c79356b
A
828 ifp = ro->ro_rt->rt_ifp;
829 ro->ro_rt->rt_use++;
b0d623f7 830 RT_UNLOCK(ro->ro_rt);
1c79356b
A
831 }
832
833 if ((flags & IPV6_FORWARDING) == 0)
834 in6_ifstat_inc(ifp, ifs6_out_request);
835 in6_ifstat_inc(ifp, ifs6_out_mcast);
836
837 /*
838 * Confirm that the outgoing interface supports multicast.
839 */
840 if ((ifp->if_flags & IFF_MULTICAST) == 0) {
841 ip6stat.ip6s_noroute++;
842 in6_ifstat_inc(ifp, ifs6_out_discard);
843 error = ENETUNREACH;
844 goto bad;
845 }
91447636 846 ifnet_lock_shared(ifp);
1c79356b 847 IN6_LOOKUP_MULTI(ip6->ip6_dst, ifp, in6m);
91447636 848 ifnet_lock_done(ifp);
1c79356b
A
849 if (in6m != NULL &&
850 (im6o == NULL || im6o->im6o_multicast_loop)) {
851 /*
852 * If we belong to the destination multicast group
853 * on the outgoing interface, and the caller did not
854 * forbid loopback, loop back a copy.
855 */
856 ip6_mloopback(ifp, m, dst);
857 } else {
858 /*
859 * If we are acting as a multicast router, perform
860 * multicast forwarding as if the packet had just
861 * arrived on the interface to which we are about
862 * to send. The multicast forwarding function
863 * recursively calls this function, using the
864 * IPV6_FORWARDING flag to prevent infinite recursion.
865 *
866 * Multicasts that are looped back by ip6_mloopback(),
867 * above, will be forwarded by the ip6_input() routine,
868 * if necessary.
869 */
b7266188 870#if MROUTING
1c79356b 871 if (ip6_mrouter && (flags & IPV6_FORWARDING) == 0) {
2d21ac55 872 if (ip6_mforward(ip6, ifp, m) != 0) {
1c79356b
A
873 m_freem(m);
874 goto done;
875 }
876 }
b7266188 877#endif
1c79356b
A
878 }
879 /*
880 * Multicasts with a hoplimit of zero may be looped back,
881 * above, but must not be transmitted on a network.
882 * Also, multicasts addressed to the loopback interface
883 * are not sent -- the above call to ip6_mloopback() will
884 * loop back a copy if this host actually belongs to the
885 * destination group on the loopback interface.
886 */
887 if (ip6->ip6_hlim == 0 || (ifp->if_flags & IFF_LOOPBACK)) {
888 m_freem(m);
889 goto done;
890 }
891 }
892
893 /*
894 * Fill the outgoing inteface to tell the upper layer
895 * to increment per-interface statistics.
896 */
897 if (ifpp)
898 *ifpp = ifp;
899
1c79356b
A
900 /*
901 * Determine path MTU.
902 */
903 if (ro_pmtu != ro) {
904 /* The first hop and the final destination may differ. */
905 struct sockaddr_in6 *sin6_fin =
906 (struct sockaddr_in6 *)&ro_pmtu->ro_dst;
b0d623f7
A
907 if (ro_pmtu->ro_rt != NULL &&
908 (!(ro_pmtu->ro_rt->rt_flags & RTF_UP) ||
909 ro_pmtu->ro_rt->generation_id != route_generation ||
910 !IN6_ARE_ADDR_EQUAL(&sin6_fin->sin6_addr, &finaldst))) {
9bccf70c 911 rtfree(ro_pmtu->ro_rt);
b0d623f7 912 ro_pmtu->ro_rt = NULL;
1c79356b 913 }
b0d623f7 914 if (ro_pmtu->ro_rt == NULL) {
1c79356b
A
915 bzero(sin6_fin, sizeof(*sin6_fin));
916 sin6_fin->sin6_family = AF_INET6;
917 sin6_fin->sin6_len = sizeof(struct sockaddr_in6);
918 sin6_fin->sin6_addr = finaldst;
919
1c79356b 920 rtalloc((struct route *)ro_pmtu);
1c79356b
A
921 }
922 }
923 if (ro_pmtu->ro_rt != NULL) {
b0d623f7 924 u_int32_t ifmtu;
1c79356b 925
b0d623f7
A
926 lck_rw_lock_shared(nd_if_rwlock);
927 ifmtu = IN6_LINKMTU(ifp);
928 lck_rw_done(nd_if_rwlock);
929
930 RT_LOCK_SPIN(ro_pmtu->ro_rt);
1c79356b 931 mtu = ro_pmtu->ro_rt->rt_rmx.rmx_mtu;
9bccf70c 932 if (mtu > ifmtu || mtu == 0) {
1c79356b
A
933 /*
934 * The MTU on the route is larger than the MTU on
935 * the interface! This shouldn't happen, unless the
936 * MTU of the interface has been changed after the
937 * interface was brought up. Change the MTU in the
938 * route to match the interface MTU (as long as the
939 * field isn't locked).
9bccf70c
A
940 *
941 * if MTU on the route is 0, we need to fix the MTU.
942 * this case happens with path MTU discovery timeouts.
1c79356b
A
943 */
944 mtu = ifmtu;
945 if ((ro_pmtu->ro_rt->rt_rmx.rmx_locks & RTV_MTU) == 0)
946 ro_pmtu->ro_rt->rt_rmx.rmx_mtu = mtu; /* XXX */
947 }
b0d623f7 948 RT_UNLOCK(ro_pmtu->ro_rt);
1c79356b 949 } else {
b0d623f7 950 lck_rw_lock_shared(nd_if_rwlock);
2d21ac55 951 mtu = IN6_LINKMTU(ifp);
b0d623f7 952 lck_rw_done(nd_if_rwlock);
1c79356b
A
953 }
954
955 /*
956 * advanced API (IPV6_USE_MIN_MTU) overrides mtu setting
957 */
9bccf70c
A
958 if ((flags & IPV6_MINMTU) != 0 && mtu > IPV6_MMTU)
959 mtu = IPV6_MMTU;
1c79356b 960
9bccf70c
A
961 /* Fake scoped addresses */
962 if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
963 /*
964 * If source or destination address is a scoped address, and
965 * the packet is going to be sent to a loopback interface,
966 * we should keep the original interface.
967 */
968
969 /*
970 * XXX: this is a very experimental and temporary solution.
971 * We eventually have sockaddr_in6 and use the sin6_scope_id
972 * field of the structure here.
973 * We rely on the consistency between two scope zone ids
55e303ae
A
974 * of source and destination, which should already be assured.
975 * Larger scopes than link will be supported in the future.
9bccf70c 976 */
b0d623f7 977 u_short index = 0;
9bccf70c 978 origifp = NULL;
1c79356b 979 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
b0d623f7 980 index = ntohs(ip6->ip6_src.s6_addr16[1]);
9bccf70c 981 else if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
b0d623f7
A
982 index = ntohs(ip6->ip6_dst.s6_addr16[1]);
983 ifnet_head_lock_shared();
984 if (index > 0 && index <= if_index) {
985 origifp = ifindex2ifnet[index];
986 }
987 ifnet_head_done();
9bccf70c
A
988 /*
989 * XXX: origifp can be NULL even in those two cases above.
990 * For example, if we remove the (only) link-local address
991 * from the loopback interface, and try to send a link-local
992 * address without link-id information. Then the source
993 * address is ::1, and the destination address is the
994 * link-local address with its s6_addr16[1] being zero.
995 * What is worse, if the packet goes to the loopback interface
996 * by a default rejected route, the null pointer would be
997 * passed to looutput, and the kernel would hang.
998 * The following last resort would prevent such disaster.
999 */
1000 if (origifp == NULL)
1001 origifp = ifp;
1c79356b 1002 }
9bccf70c
A
1003 else
1004 origifp = ifp;
1005#ifndef SCOPEDROUTING
1006 /*
1007 * clear embedded scope identifiers if necessary.
1008 * in6_clearscope will touch the addresses only when necessary.
1009 */
1010 in6_clearscope(&ip6->ip6_src);
1011 in6_clearscope(&ip6->ip6_dst);
1012#endif
1c79356b 1013
7e4a7d39 1014#if IPFW2
1c79356b
A
1015 /*
1016 * Check with the firewall...
1017 */
9bccf70c 1018 if (ip6_fw_enable && ip6_fw_chk_ptr) {
1c79356b 1019 u_short port = 0;
55e303ae 1020 m->m_pkthdr.rcvif = NULL; /* XXX */
1c79356b 1021 /* If ipfw says divert, we have to just drop packet */
91447636 1022 if (ip6_fw_chk_ptr(&ip6, ifp, &port, &m)) {
1c79356b
A
1023 m_freem(m);
1024 goto done;
1025 }
1026 if (!m) {
1027 error = EACCES;
1028 goto done;
1029 }
1030 }
7e4a7d39 1031#endif
1c79356b
A
1032
1033 /*
1034 * If the outgoing packet contains a hop-by-hop options header,
1035 * it must be examined and processed even by the source node.
1036 * (RFC 2460, section 4.)
1037 */
1038 if (exthdrs.ip6e_hbh) {
9bccf70c 1039 struct ip6_hbh *hbh = mtod(exthdrs.ip6e_hbh, struct ip6_hbh *);
1c79356b
A
1040 u_int32_t dummy1; /* XXX unused */
1041 u_int32_t dummy2; /* XXX unused */
1042
9bccf70c
A
1043#if DIAGNOSTIC
1044 if ((hbh->ip6h_len + 1) << 3 > exthdrs.ip6e_hbh->m_len)
1045 panic("ip6e_hbh is not continuous");
1046#endif
1c79356b
A
1047 /*
1048 * XXX: if we have to send an ICMPv6 error to the sender,
1049 * we need the M_LOOP flag since icmp6_error() expects
1050 * the IPv6 and the hop-by-hop options header are
1051 * continuous unless the flag is set.
1052 */
1053 m->m_flags |= M_LOOP;
1054 m->m_pkthdr.rcvif = ifp;
1055 if (ip6_process_hopopts(m,
1056 (u_int8_t *)(hbh + 1),
1057 ((hbh->ip6h_len + 1) << 3) -
1058 sizeof(struct ip6_hbh),
1059 &dummy1, &dummy2) < 0) {
1060 /* m was already freed at this point */
1061 error = EINVAL;/* better error? */
1062 goto done;
1063 }
1064 m->m_flags &= ~M_LOOP; /* XXX */
1065 m->m_pkthdr.rcvif = NULL;
1066 }
1067
b0d623f7
A
1068#if PF
1069 lck_mtx_unlock(ip6_mutex);
1070
1071 /* Invoke outbound packet filter */
1072 error = pf_af_hook(ifp, NULL, &m, AF_INET6, FALSE);
1073
1074 lck_mtx_lock(ip6_mutex);
1075
1076 if (error) {
1077 if (m != NULL) {
1078 panic("%s: unexpected packet %p\n", __func__, m);
1079 /* NOTREACHED */
1080 }
1081 /* Already freed by callee */
1082 goto done;
1083 }
1084 ip6 = mtod(m, struct ip6_hdr *);
1085#endif /* PF */
1086
1c79356b
A
1087 /*
1088 * Send the packet to the outgoing interface.
1089 * If necessary, do IPv6 fragmentation before sending.
1090 */
1091 tlen = m->m_pkthdr.len;
1092 if (tlen <= mtu
1093#if notyet
1094 /*
1095 * On any link that cannot convey a 1280-octet packet in one piece,
1096 * link-specific fragmentation and reassembly must be provided at
1097 * a layer below IPv6. [RFC 2460, sec.5]
1098 * Thus if the interface has ability of link-level fragmentation,
1099 * we can just send the packet even if the packet size is
1100 * larger than the link's MTU.
1101 * XXX: IFF_FRAGMENTABLE (or such) flag has not been defined yet...
1102 */
1103
1104 || ifp->if_flags & IFF_FRAGMENTABLE
1105#endif
1106 )
1107 {
9bccf70c
A
1108 /* Record statistics for this interface address. */
1109 if (ia && !(flags & IPV6_FORWARDING)) {
1110#ifndef __APPLE__
1111 ia->ia_ifa.if_opackets++;
1112 ia->ia_ifa.if_obytes += m->m_pkthdr.len;
1c79356b 1113#endif
9bccf70c
A
1114 }
1115#ifdef IPSEC
1116 /* clean ipsec history once it goes out of the node */
1117 ipsec_delaux(m);
1c79356b 1118#endif
9bccf70c 1119
91447636 1120 error = nd6_output(ifp, origifp, m, dst, ro->ro_rt, 1);
1c79356b
A
1121 goto done;
1122 } else if (mtu < IPV6_MMTU) {
1123 /*
1124 * note that path MTU is never less than IPV6_MMTU
1125 * (see icmp6_input).
1126 */
1127 error = EMSGSIZE;
1128 in6_ifstat_inc(ifp, ifs6_out_fragfail);
1129 goto bad;
1130 } else if (ip6->ip6_plen == 0) { /* jumbo payload cannot be fragmented */
1131 error = EMSGSIZE;
1132 in6_ifstat_inc(ifp, ifs6_out_fragfail);
1133 goto bad;
1134 } else {
1135 struct mbuf **mnext, *m_frgpart;
2d21ac55 1136 struct ip6_frag *ip6f = NULL;
1c79356b
A
1137 u_int32_t id = htonl(ip6_id++);
1138 u_char nextproto;
1139
1140 /*
1141 * Too large for the destination or interface;
1142 * fragment if possible.
1143 * Must be able to put at least 8 bytes per fragment.
1144 */
1145 hlen = unfragpartlen;
1146 if (mtu > IPV6_MAXPACKET)
1147 mtu = IPV6_MAXPACKET;
9bccf70c 1148
1c79356b
A
1149 len = (mtu - hlen - sizeof(struct ip6_frag)) & ~7;
1150 if (len < 8) {
1151 error = EMSGSIZE;
1152 in6_ifstat_inc(ifp, ifs6_out_fragfail);
1153 goto bad;
1154 }
1155
1156 mnext = &m->m_nextpkt;
1157
1158 /*
1159 * Change the next header field of the last header in the
1160 * unfragmentable part.
1161 */
1162 if (exthdrs.ip6e_rthdr) {
1163 nextproto = *mtod(exthdrs.ip6e_rthdr, u_char *);
1164 *mtod(exthdrs.ip6e_rthdr, u_char *) = IPPROTO_FRAGMENT;
1165 } else if (exthdrs.ip6e_dest1) {
1166 nextproto = *mtod(exthdrs.ip6e_dest1, u_char *);
1167 *mtod(exthdrs.ip6e_dest1, u_char *) = IPPROTO_FRAGMENT;
1168 } else if (exthdrs.ip6e_hbh) {
1169 nextproto = *mtod(exthdrs.ip6e_hbh, u_char *);
1170 *mtod(exthdrs.ip6e_hbh, u_char *) = IPPROTO_FRAGMENT;
1171 } else {
1172 nextproto = ip6->ip6_nxt;
1173 ip6->ip6_nxt = IPPROTO_FRAGMENT;
1174 }
1175
1176 /*
1177 * Loop through length of segment after first fragment,
55e303ae
A
1178 * make new header and copy data of each part and link onto
1179 * chain.
1c79356b
A
1180 */
1181 m0 = m;
1182 for (off = hlen; off < tlen; off += len) {
2d21ac55 1183 MGETHDR(m, M_DONTWAIT, MT_HEADER); /* MAC-OK */
1c79356b
A
1184 if (!m) {
1185 error = ENOBUFS;
1186 ip6stat.ip6s_odropped++;
1187 goto sendorfree;
1188 }
9bccf70c 1189 m->m_pkthdr.rcvif = NULL;
1c79356b
A
1190 m->m_flags = m0->m_flags & M_COPYFLAGS;
1191 *mnext = m;
1192 mnext = &m->m_nextpkt;
1193 m->m_data += max_linkhdr;
1194 mhip6 = mtod(m, struct ip6_hdr *);
1195 *mhip6 = *ip6;
1196 m->m_len = sizeof(*mhip6);
1197 error = ip6_insertfraghdr(m0, m, hlen, &ip6f);
1198 if (error) {
1199 ip6stat.ip6s_odropped++;
1200 goto sendorfree;
1201 }
1202 ip6f->ip6f_offlg = htons((u_short)((off - hlen) & ~7));
1203 if (off + len >= tlen)
1204 len = tlen - off;
1205 else
1206 ip6f->ip6f_offlg |= IP6F_MORE_FRAG;
1207 mhip6->ip6_plen = htons((u_short)(len + hlen +
1208 sizeof(*ip6f) -
1209 sizeof(struct ip6_hdr)));
1210 if ((m_frgpart = m_copy(m0, off, len)) == 0) {
1211 error = ENOBUFS;
1212 ip6stat.ip6s_odropped++;
1213 goto sendorfree;
1214 }
1215 m_cat(m, m_frgpart);
1216 m->m_pkthdr.len = len + hlen + sizeof(*ip6f);
91447636
A
1217 m->m_pkthdr.rcvif = 0;
1218 m->m_pkthdr.socket_id = m0->m_pkthdr.socket_id;
2d21ac55
A
1219#ifdef __darwin8_notyet
1220#if CONFIG_MACF_NET
1221 mac_create_fragment(m0, m);
1222#endif
1223#endif
1c79356b
A
1224 ip6f->ip6f_reserved = 0;
1225 ip6f->ip6f_ident = id;
1226 ip6f->ip6f_nxt = nextproto;
1227 ip6stat.ip6s_ofragments++;
1228 in6_ifstat_inc(ifp, ifs6_out_fragcreat);
1229 }
1230
1231 in6_ifstat_inc(ifp, ifs6_out_fragok);
1232 }
1233
1234 /*
1235 * Remove leading garbages.
1236 */
1237sendorfree:
1238 m = m0->m_nextpkt;
1239 m0->m_nextpkt = 0;
1240 m_freem(m0);
1241 for (m0 = m; m; m = m0) {
1242 m0 = m->m_nextpkt;
1243 m->m_nextpkt = 0;
1244 if (error == 0) {
9bccf70c
A
1245 /* Record statistics for this interface address. */
1246 if (ia) {
1247#ifndef __APPLE__
1248 ia->ia_ifa.if_opackets++;
1249 ia->ia_ifa.if_obytes += m->m_pkthdr.len;
1c79356b 1250#endif
9bccf70c
A
1251 }
1252#if IPSEC
1253 /* clean ipsec history once it goes out of the node */
1254 ipsec_delaux(m);
1c79356b 1255#endif
91447636
A
1256 error = nd6_output(ifp, origifp, m, dst, ro->ro_rt, 1);
1257
1c79356b
A
1258 } else
1259 m_freem(m);
1260 }
1261
1262 if (error == 0)
1263 ip6stat.ip6s_fragmented++;
1264
1265done:
91447636
A
1266 if (!locked)
1267 lck_mtx_unlock(ip6_mutex);
9bccf70c
A
1268 if (ro == &ip6route && ro->ro_rt) { /* brace necessary for rtfree */
1269 rtfree(ro->ro_rt);
1c79356b 1270 } else if (ro_pmtu == &ip6route && ro_pmtu->ro_rt) {
9bccf70c 1271 rtfree(ro_pmtu->ro_rt);
1c79356b
A
1272 }
1273
1274#if IPSEC
2d21ac55
A
1275 if (sp != NULL)
1276 key_freesp(sp, KEY_SADB_UNLOCKED);
1c79356b
A
1277#endif /* IPSEC */
1278
b0d623f7
A
1279 if (ia != NULL)
1280 ifafree(&ia->ia_ifa);
1c79356b
A
1281 return(error);
1282
1283freehdrs:
1284 m_freem(exthdrs.ip6e_hbh); /* m_freem will check if mbuf is 0 */
1285 m_freem(exthdrs.ip6e_dest1);
1286 m_freem(exthdrs.ip6e_rthdr);
1287 m_freem(exthdrs.ip6e_dest2);
1288 /* fall through */
1289bad:
1290 m_freem(m);
1291 goto done;
1292}
1293
1294static int
1295ip6_copyexthdr(mp, hdr, hlen)
1296 struct mbuf **mp;
1297 caddr_t hdr;
1298 int hlen;
1299{
1300 struct mbuf *m;
1301
1302 if (hlen > MCLBYTES)
1303 return(ENOBUFS); /* XXX */
1304
1305 MGET(m, M_DONTWAIT, MT_DATA);
1306 if (!m)
1307 return(ENOBUFS);
1308
1309 if (hlen > MLEN) {
1310 MCLGET(m, M_DONTWAIT);
1311 if ((m->m_flags & M_EXT) == 0) {
1312 m_free(m);
1313 return(ENOBUFS);
1314 }
1315 }
1316 m->m_len = hlen;
1317 if (hdr)
1318 bcopy(hdr, mtod(m, caddr_t), hlen);
1319
1320 *mp = m;
1321 return(0);
1322}
1323
1324/*
1325 * Insert jumbo payload option.
1326 */
1327static int
1328ip6_insert_jumboopt(exthdrs, plen)
1329 struct ip6_exthdrs *exthdrs;
1330 u_int32_t plen;
1331{
1332 struct mbuf *mopt;
1333 u_char *optbuf;
9bccf70c 1334 u_int32_t v;
1c79356b
A
1335
1336#define JUMBOOPTLEN 8 /* length of jumbo payload option and padding */
1337
1338 /*
1339 * If there is no hop-by-hop options header, allocate new one.
1340 * If there is one but it doesn't have enough space to store the
1341 * jumbo payload option, allocate a cluster to store the whole options.
1342 * Otherwise, use it to store the options.
1343 */
1344 if (exthdrs->ip6e_hbh == 0) {
1345 MGET(mopt, M_DONTWAIT, MT_DATA);
1346 if (mopt == 0)
1347 return(ENOBUFS);
1348 mopt->m_len = JUMBOOPTLEN;
1349 optbuf = mtod(mopt, u_char *);
1350 optbuf[1] = 0; /* = ((JUMBOOPTLEN) >> 3) - 1 */
1351 exthdrs->ip6e_hbh = mopt;
1352 } else {
1353 struct ip6_hbh *hbh;
1354
1355 mopt = exthdrs->ip6e_hbh;
1356 if (M_TRAILINGSPACE(mopt) < JUMBOOPTLEN) {
9bccf70c
A
1357 /*
1358 * XXX assumption:
1359 * - exthdrs->ip6e_hbh is not referenced from places
1360 * other than exthdrs.
1361 * - exthdrs->ip6e_hbh is not an mbuf chain.
1362 */
1c79356b 1363 int oldoptlen = mopt->m_len;
9bccf70c 1364 struct mbuf *n;
1c79356b 1365
9bccf70c
A
1366 /*
1367 * XXX: give up if the whole (new) hbh header does
1368 * not fit even in an mbuf cluster.
1369 */
1370 if (oldoptlen + JUMBOOPTLEN > MCLBYTES)
1c79356b
A
1371 return(ENOBUFS);
1372
9bccf70c
A
1373 /*
1374 * As a consequence, we must always prepare a cluster
1375 * at this point.
1376 */
1377 MGET(n, M_DONTWAIT, MT_DATA);
1378 if (n) {
1379 MCLGET(n, M_DONTWAIT);
1380 if ((n->m_flags & M_EXT) == 0) {
1381 m_freem(n);
1382 n = NULL;
1383 }
1384 }
1385 if (!n)
1386 return(ENOBUFS);
1387 n->m_len = oldoptlen + JUMBOOPTLEN;
1388 bcopy(mtod(mopt, caddr_t), mtod(n, caddr_t),
1389 oldoptlen);
2d21ac55 1390 optbuf = (u_char *) (mtod(n, caddr_t) + oldoptlen);
9bccf70c
A
1391 m_freem(mopt);
1392 mopt = exthdrs->ip6e_hbh = n;
1c79356b
A
1393 } else {
1394 optbuf = mtod(mopt, u_char *) + mopt->m_len;
1395 mopt->m_len += JUMBOOPTLEN;
1396 }
1397 optbuf[0] = IP6OPT_PADN;
1398 optbuf[1] = 1;
1399
1400 /*
1401 * Adjust the header length according to the pad and
1402 * the jumbo payload option.
1403 */
1404 hbh = mtod(mopt, struct ip6_hbh *);
1405 hbh->ip6h_len += (JUMBOOPTLEN >> 3);
1406 }
1407
1408 /* fill in the option. */
1409 optbuf[2] = IP6OPT_JUMBO;
1410 optbuf[3] = 4;
9bccf70c
A
1411 v = (u_int32_t)htonl(plen + JUMBOOPTLEN);
1412 bcopy(&v, &optbuf[4], sizeof(u_int32_t));
1c79356b
A
1413
1414 /* finally, adjust the packet header length */
1415 exthdrs->ip6e_ip6->m_pkthdr.len += JUMBOOPTLEN;
1416
1417 return(0);
1418#undef JUMBOOPTLEN
1419}
1420
1421/*
1422 * Insert fragment header and copy unfragmentable header portions.
1423 */
1424static int
1425ip6_insertfraghdr(m0, m, hlen, frghdrp)
1426 struct mbuf *m0, *m;
1427 int hlen;
1428 struct ip6_frag **frghdrp;
1429{
1430 struct mbuf *n, *mlast;
1431
1432 if (hlen > sizeof(struct ip6_hdr)) {
1433 n = m_copym(m0, sizeof(struct ip6_hdr),
1434 hlen - sizeof(struct ip6_hdr), M_DONTWAIT);
1435 if (n == 0)
1436 return(ENOBUFS);
1437 m->m_next = n;
1438 } else
1439 n = m;
1440
1441 /* Search for the last mbuf of unfragmentable part. */
1442 for (mlast = n; mlast->m_next; mlast = mlast->m_next)
1443 ;
1444
1445 if ((mlast->m_flags & M_EXT) == 0 &&
9bccf70c 1446 M_TRAILINGSPACE(mlast) >= sizeof(struct ip6_frag)) {
1c79356b
A
1447 /* use the trailing space of the last mbuf for the fragment hdr */
1448 *frghdrp =
1449 (struct ip6_frag *)(mtod(mlast, caddr_t) + mlast->m_len);
1450 mlast->m_len += sizeof(struct ip6_frag);
1451 m->m_pkthdr.len += sizeof(struct ip6_frag);
1452 } else {
1453 /* allocate a new mbuf for the fragment header */
1454 struct mbuf *mfrg;
1455
1456 MGET(mfrg, M_DONTWAIT, MT_DATA);
1457 if (mfrg == 0)
1458 return(ENOBUFS);
1459 mfrg->m_len = sizeof(struct ip6_frag);
1460 *frghdrp = mtod(mfrg, struct ip6_frag *);
1461 mlast->m_next = mfrg;
1462 }
1463
1464 return(0);
1465}
1466
2d21ac55 1467extern int load_ipfw(void);
55e303ae 1468
1c79356b
A
1469/*
1470 * IP6 socket option processing.
1471 */
1c79356b
A
1472int
1473ip6_ctloutput(so, sopt)
1474 struct socket *so;
1475 struct sockopt *sopt;
1c79356b 1476{
9bccf70c
A
1477 int privileged;
1478 struct inpcb *in6p = sotoinpcb(so);
b0d623f7 1479 int error = 0, optval = 0;
2d21ac55
A
1480 int level, op = -1, optname = 0;
1481 int optlen = 0;
b0d623f7 1482 struct proc *p;
1c79356b 1483
b0d623f7 1484 if (sopt == NULL) {
55e303ae 1485 panic("ip6_ctloutput: arg soopt is NULL");
b0d623f7 1486 /* NOTREACHED */
1c79356b 1487 }
b0d623f7
A
1488 level = sopt->sopt_level;
1489 op = sopt->sopt_dir;
1490 optname = sopt->sopt_name;
1491 optlen = sopt->sopt_valsize;
1492 p = sopt->sopt_p;
1c79356b 1493
b0d623f7 1494 privileged = (proc_suser(p) == 0);
1c79356b
A
1495
1496 if (level == IPPROTO_IPV6) {
1497 switch (op) {
1498
1c79356b 1499 case SOPT_SET:
1c79356b
A
1500 switch (optname) {
1501 case IPV6_PKTOPTIONS:
9bccf70c 1502 {
1c79356b
A
1503 struct mbuf *m;
1504
a3d08fcd
A
1505 if (sopt->sopt_valsize > MCLBYTES) {
1506 error = EMSGSIZE;
1507 break;
1508 }
9bccf70c 1509 error = soopt_getm(sopt, &m); /* XXX */
2d21ac55 1510 if (error != 0)
1c79356b 1511 break;
9bccf70c 1512 error = soopt_mcopyin(sopt, m); /* XXX */
2d21ac55 1513 if (error != 0)
1c79356b
A
1514 break;
1515 error = ip6_pcbopts(&in6p->in6p_outputopts,
1516 m, so, sopt);
1517 m_freem(m); /* XXX */
1c79356b
A
1518 break;
1519 }
9bccf70c 1520
1c79356b
A
1521 /*
1522 * Use of some Hop-by-Hop options or some
1523 * Destination options, might require special
1524 * privilege. That is, normal applications
1525 * (without special privilege) might be forbidden
1526 * from setting certain options in outgoing packets,
1527 * and might never see certain options in received
1528 * packets. [RFC 2292 Section 6]
1529 * KAME specific note:
1530 * KAME prevents non-privileged users from sending or
1531 * receiving ANY hbh/dst options in order to avoid
1532 * overhead of parsing options in the kernel.
1533 */
1c79356b 1534 case IPV6_UNICAST_HOPS:
1c79356b
A
1535 case IPV6_CHECKSUM:
1536 case IPV6_FAITH:
1537
b0d623f7 1538 case IPV6_RECVTCLASS:
9bccf70c
A
1539 case IPV6_V6ONLY:
1540 if (optlen != sizeof(int)) {
1c79356b 1541 error = EINVAL;
9bccf70c
A
1542 break;
1543 }
1544 error = sooptcopyin(sopt, &optval,
1545 sizeof optval, sizeof optval);
1546 if (error)
1547 break;
1548 switch (optname) {
1c79356b 1549
9bccf70c
A
1550 case IPV6_UNICAST_HOPS:
1551 if (optval < -1 || optval >= 256)
1552 error = EINVAL;
1553 else {
1554 /* -1 = kernel default */
1555 in6p->in6p_hops = optval;
1556
1557 if ((in6p->in6p_vflag &
1558 INP_IPV4) != 0)
1559 in6p->inp_ip_ttl = optval;
1560 }
1561 break;
1c79356b 1562#define OPTSET(bit) \
9bccf70c 1563do { \
1c79356b
A
1564 if (optval) \
1565 in6p->in6p_flags |= (bit); \
1566 else \
9bccf70c
A
1567 in6p->in6p_flags &= ~(bit); \
1568} while (0)
1c79356b 1569#define OPTBIT(bit) (in6p->in6p_flags & (bit) ? 1 : 0)
1c79356b 1570
9bccf70c
A
1571 case IPV6_CHECKSUM:
1572 in6p->in6p_cksum = optval;
1573 break;
1c79356b 1574
9bccf70c
A
1575 case IPV6_FAITH:
1576 OPTSET(IN6P_FAITH);
1577 break;
1c79356b 1578
9bccf70c
A
1579 case IPV6_V6ONLY:
1580 /*
1581 * make setsockopt(IPV6_V6ONLY)
1582 * available only prior to bind(2).
1583 * see ipng mailing list, Jun 22 2001.
1584 */
1585 if (in6p->in6p_lport ||
1586 !IN6_IS_ADDR_UNSPECIFIED(&in6p->in6p_laddr))
1587 {
1588 error = EINVAL;
1c79356b 1589 break;
1c79356b 1590 }
9bccf70c 1591 OPTSET(IN6P_IPV6_V6ONLY);
55e303ae
A
1592 if (optval)
1593 in6p->in6p_vflag &= ~INP_IPV4;
1594 else
1595 in6p->in6p_vflag |= INP_IPV4;
9bccf70c 1596 break;
b0d623f7
A
1597 case IPV6_RECVTCLASS:
1598 /* cannot mix with RFC2292 XXX */
1599 OPTSET(IN6P_TCLASS);
1600 break;
1c79356b
A
1601 }
1602 break;
9bccf70c 1603
1c79356b 1604 case IPV6_PKTINFO:
9bccf70c 1605 case IPV6_HOPLIMIT:
1c79356b 1606 case IPV6_HOPOPTS:
1c79356b 1607 case IPV6_DSTOPTS:
9bccf70c
A
1608 case IPV6_RTHDR:
1609 /* RFC 2292 */
1610 if (optlen != sizeof(int)) {
1611 error = EINVAL;
1612 break;
1613 }
1614 error = sooptcopyin(sopt, &optval,
1615 sizeof optval, sizeof optval);
1616 if (error)
1617 break;
1618 switch (optname) {
1619 case IPV6_PKTINFO:
1620 OPTSET(IN6P_PKTINFO);
1621 break;
1622 case IPV6_HOPLIMIT:
1623 OPTSET(IN6P_HOPLIMIT);
1624 break;
1625 case IPV6_HOPOPTS:
1626 /*
1627 * Check super-user privilege.
1628 * See comments for IPV6_RECVHOPOPTS.
1629 */
1630 if (!privileged)
1631 return(EPERM);
1632 OPTSET(IN6P_HOPOPTS);
1633 break;
1634 case IPV6_DSTOPTS:
1635 if (!privileged)
1636 return(EPERM);
1637 OPTSET(IN6P_DSTOPTS|IN6P_RTHDRDSTOPTS); /* XXX */
1638 break;
1639 case IPV6_RTHDR:
1640 OPTSET(IN6P_RTHDR);
1c79356b 1641 break;
1c79356b
A
1642 }
1643 break;
1644#undef OPTSET
1645
b0d623f7
A
1646 case IPV6_TCLASS:
1647 if (optlen != sizeof(optval)) {
1648 error = EINVAL;
1649 break;
1650 }
1651 error = sooptcopyin(sopt, &optval, sizeof optval, sizeof optval);
1652 if (error)
1653 break;
1654 error = ip6_pcbopt(optname, (u_char *)&optval, sizeof(optval), &in6p->in6p_outputopts);
1655 break;
1656
1c79356b
A
1657 case IPV6_MULTICAST_IF:
1658 case IPV6_MULTICAST_HOPS:
1659 case IPV6_MULTICAST_LOOP:
1660 case IPV6_JOIN_GROUP:
1661 case IPV6_LEAVE_GROUP:
1c79356b
A
1662 {
1663 struct mbuf *m;
1664 if (sopt->sopt_valsize > MLEN) {
1665 error = EMSGSIZE;
1666 break;
1667 }
1668 /* XXX */
b0d623f7
A
1669 MGET(m, sopt->sopt_p != kernproc ?
1670 M_WAIT : M_DONTWAIT, MT_HEADER);
1c79356b
A
1671 if (m == 0) {
1672 error = ENOBUFS;
1673 break;
1674 }
1675 m->m_len = sopt->sopt_valsize;
1676 error = sooptcopyin(sopt, mtod(m, char *),
1677 m->m_len, m->m_len);
55e303ae 1678 error = ip6_setmoptions(sopt->sopt_name, in6p, m);
1c79356b
A
1679 (void)m_free(m);
1680 }
1c79356b
A
1681 break;
1682
9bccf70c
A
1683 case IPV6_PORTRANGE:
1684 error = sooptcopyin(sopt, &optval,
1685 sizeof optval, sizeof optval);
1686 if (error)
1687 break;
1c79356b 1688
9bccf70c
A
1689 switch (optval) {
1690 case IPV6_PORTRANGE_DEFAULT:
1691 in6p->in6p_flags &= ~(IN6P_LOWPORT);
1692 in6p->in6p_flags &= ~(IN6P_HIGHPORT);
1693 break;
1c79356b 1694
9bccf70c
A
1695 case IPV6_PORTRANGE_HIGH:
1696 in6p->in6p_flags &= ~(IN6P_LOWPORT);
1697 in6p->in6p_flags |= IN6P_HIGHPORT;
1698 break;
1c79356b 1699
9bccf70c
A
1700 case IPV6_PORTRANGE_LOW:
1701 in6p->in6p_flags &= ~(IN6P_HIGHPORT);
1702 in6p->in6p_flags |= IN6P_LOWPORT;
1703 break;
1c79356b 1704
9bccf70c
A
1705 default:
1706 error = EINVAL;
1707 break;
1708 }
1c79356b 1709 break;
1c79356b
A
1710
1711#if IPSEC
1712 case IPV6_IPSEC_POLICY:
1713 {
1714 caddr_t req = NULL;
1715 size_t len = 0;
1c79356b 1716 struct mbuf *m;
1c79356b 1717
91447636
A
1718 if (sopt->sopt_valsize > MCLBYTES) {
1719 error = EMSGSIZE;
1720 break;
1721 }
9bccf70c 1722 if ((error = soopt_getm(sopt, &m)) != 0) /* XXX */
1c79356b 1723 break;
55e303ae 1724 if ((error = soopt_mcopyin(sopt, m)) != 0) /* XXX */
1c79356b 1725 break;
1c79356b
A
1726 if (m) {
1727 req = mtod(m, caddr_t);
1728 len = m->m_len;
1729 }
1c79356b
A
1730 error = ipsec6_set_policy(in6p, optname, req,
1731 len, privileged);
1c79356b 1732 m_freem(m);
1c79356b
A
1733 }
1734 break;
9bccf70c 1735#endif /* KAME IPSEC */
1c79356b 1736
2d21ac55 1737#if IPFIREWALL
1c79356b
A
1738 case IPV6_FW_ADD:
1739 case IPV6_FW_DEL:
1740 case IPV6_FW_FLUSH:
1741 case IPV6_FW_ZERO:
55e303ae
A
1742 {
1743 if (ip6_fw_ctl_ptr == NULL && load_ipfw() != 0)
1c79356b 1744 return EINVAL;
55e303ae
A
1745
1746 error = (*ip6_fw_ctl_ptr)(sopt);
1747 }
1c79356b 1748 break;
2d21ac55 1749#endif /* IPFIREWALL */
1c79356b
A
1750
1751 default:
1752 error = ENOPROTOOPT;
1753 break;
1754 }
1c79356b
A
1755 break;
1756
1c79356b 1757 case SOPT_GET:
1c79356b
A
1758 switch (optname) {
1759
1760 case IPV6_PKTOPTIONS:
9bccf70c
A
1761 if (in6p->in6p_options) {
1762 struct mbuf *m;
1763 m = m_copym(in6p->in6p_options,
1764 0, M_COPYALL, M_WAIT);
b0d623f7
A
1765 if (m == NULL) {
1766 error = ENOBUFS;
1767 break;
1768 }
9bccf70c
A
1769 error = soopt_mcopyout(sopt, m);
1770 if (error == 0)
1771 m_freem(m);
1c79356b
A
1772 } else
1773 sopt->sopt_valsize = 0;
1c79356b
A
1774 break;
1775
1c79356b
A
1776 case IPV6_UNICAST_HOPS:
1777 case IPV6_CHECKSUM:
1778
1c79356b 1779 case IPV6_FAITH:
9bccf70c 1780 case IPV6_V6ONLY:
1c79356b 1781 case IPV6_PORTRANGE:
b0d623f7 1782 case IPV6_RECVTCLASS:
1c79356b
A
1783 switch (optname) {
1784
1785 case IPV6_UNICAST_HOPS:
1c79356b 1786 optval = in6p->in6p_hops;
1c79356b
A
1787 break;
1788
1789 case IPV6_CHECKSUM:
1c79356b 1790 optval = in6p->in6p_cksum;
1c79356b
A
1791 break;
1792
1793 case IPV6_FAITH:
1794 optval = OPTBIT(IN6P_FAITH);
1795 break;
1796
9bccf70c 1797 case IPV6_V6ONLY:
55e303ae 1798 optval = OPTBIT(IN6P_IPV6_V6ONLY);
1c79356b 1799 break;
1c79356b 1800
1c79356b
A
1801 case IPV6_PORTRANGE:
1802 {
1803 int flags;
1c79356b 1804 flags = in6p->in6p_flags;
1c79356b
A
1805 if (flags & IN6P_HIGHPORT)
1806 optval = IPV6_PORTRANGE_HIGH;
1807 else if (flags & IN6P_LOWPORT)
1808 optval = IPV6_PORTRANGE_LOW;
1809 else
1810 optval = 0;
1811 break;
1812 }
b0d623f7
A
1813 case IPV6_RECVTCLASS:
1814 optval = OPTBIT(IN6P_TCLASS);
1815 break;
1816
1c79356b 1817 }
1c79356b
A
1818 error = sooptcopyout(sopt, &optval,
1819 sizeof optval);
1c79356b
A
1820 break;
1821
1822 case IPV6_PKTINFO:
9bccf70c 1823 case IPV6_HOPLIMIT:
1c79356b
A
1824 case IPV6_HOPOPTS:
1825 case IPV6_RTHDR:
1826 case IPV6_DSTOPTS:
91447636
A
1827 if ((optname == IPV6_HOPOPTS ||
1828 optname == IPV6_DSTOPTS) &&
1c79356b
A
1829 !privileged)
1830 return(EPERM);
9bccf70c 1831 switch (optname) {
1c79356b 1832 case IPV6_PKTINFO:
9bccf70c 1833 optval = OPTBIT(IN6P_PKTINFO);
1c79356b
A
1834 break;
1835 case IPV6_HOPLIMIT:
1836 optval = OPTBIT(IN6P_HOPLIMIT);
1837 break;
1838 case IPV6_HOPOPTS:
9bccf70c
A
1839 if (!privileged)
1840 return(EPERM);
1841 optval = OPTBIT(IN6P_HOPOPTS);
1c79356b
A
1842 break;
1843 case IPV6_RTHDR:
9bccf70c 1844 optval = OPTBIT(IN6P_RTHDR);
1c79356b
A
1845 break;
1846 case IPV6_DSTOPTS:
9bccf70c
A
1847 if (!privileged)
1848 return(EPERM);
1849 optval = OPTBIT(IN6P_DSTOPTS|IN6P_RTHDRDSTOPTS);
1c79356b 1850 break;
1c79356b 1851 }
1c79356b
A
1852 error = sooptcopyout(sopt, &optval,
1853 sizeof optval);
1c79356b
A
1854 break;
1855
b0d623f7
A
1856 case IPV6_TCLASS:
1857 error = ip6_getpcbopt(in6p->in6p_outputopts, optname, sopt);
1858 break;
1859
1c79356b
A
1860 case IPV6_MULTICAST_IF:
1861 case IPV6_MULTICAST_HOPS:
1862 case IPV6_MULTICAST_LOOP:
1863 case IPV6_JOIN_GROUP:
1864 case IPV6_LEAVE_GROUP:
1c79356b
A
1865 {
1866 struct mbuf *m;
1867 error = ip6_getmoptions(sopt->sopt_name,
1868 in6p->in6p_moptions, &m);
1869 if (error == 0)
1870 error = sooptcopyout(sopt,
1871 mtod(m, char *), m->m_len);
b0d623f7
A
1872 if (m != NULL)
1873 m_freem(m);
1c79356b 1874 }
1c79356b
A
1875 break;
1876
1877#if IPSEC
1878 case IPV6_IPSEC_POLICY:
1879 {
1880 caddr_t req = NULL;
1881 size_t len = 0;
1c79356b
A
1882 struct mbuf *m = NULL;
1883 struct mbuf **mp = &m;
1884
91447636
A
1885 if (sopt->sopt_valsize > MCLBYTES) {
1886 error = EMSGSIZE;
1887 break;
1888 }
9bccf70c 1889 error = soopt_getm(sopt, &m); /* XXX */
2d21ac55 1890 if (error != 0)
1c79356b 1891 break;
9bccf70c 1892 error = soopt_mcopyin(sopt, m); /* XXX */
2d21ac55 1893 if (error != 0)
1c79356b 1894 break;
1c79356b
A
1895 if (m) {
1896 req = mtod(m, caddr_t);
1897 len = m->m_len;
1898 }
1c79356b 1899 error = ipsec6_get_policy(in6p, req, len, mp);
1c79356b 1900 if (error == 0)
9bccf70c
A
1901 error = soopt_mcopyout(sopt, m); /*XXX*/
1902 if (error == 0 && m)
1903 m_freem(m);
1c79356b
A
1904 break;
1905 }
9bccf70c 1906#endif /* KAME IPSEC */
1c79356b 1907
2d21ac55 1908#if IPFIREWALL
1c79356b 1909 case IPV6_FW_GET:
55e303ae
A
1910 {
1911 if (ip6_fw_ctl_ptr == NULL && load_ipfw() != 0)
1c79356b 1912 return EINVAL;
55e303ae
A
1913
1914 error = (*ip6_fw_ctl_ptr)(sopt);
1c79356b 1915 }
1c79356b 1916 break;
2d21ac55 1917#endif /* IPFIREWALL */
1c79356b
A
1918
1919 default:
1920 error = ENOPROTOOPT;
1921 break;
1922 }
1923 break;
1924 }
1925 } else {
1926 error = EINVAL;
1c79356b
A
1927 }
1928 return(error);
1929}
1930
1931/*
1932 * Set up IP6 options in pcb for insertion in output packets or
1933 * specifying behavior of outgoing packets.
1934 */
1935static int
2d21ac55
A
1936ip6_pcbopts(
1937 struct ip6_pktopts **pktopt,
1938 struct mbuf *m,
1939 __unused struct socket *so,
1940 struct sockopt *sopt)
1c79356b 1941{
9bccf70c 1942 struct ip6_pktopts *opt = *pktopt;
b0d623f7 1943 int error = 0, priv;
1c79356b 1944 struct proc *p = sopt->sopt_p;
1c79356b
A
1945
1946 /* turn off any old options. */
1947 if (opt) {
1948#if DIAGNOSTIC
9bccf70c
A
1949 if (opt->ip6po_pktinfo || opt->ip6po_nexthop ||
1950 opt->ip6po_hbh || opt->ip6po_dest1 || opt->ip6po_dest2 ||
1951 opt->ip6po_rhinfo.ip6po_rhi_rthdr)
1952 printf("ip6_pcbopts: all specified options are cleared.\n");
1c79356b
A
1953#endif
1954 ip6_clearpktopts(opt, 1, -1);
b0d623f7 1955 } else {
1c79356b 1956 opt = _MALLOC(sizeof(*opt), M_IP6OPT, M_WAITOK);
b0d623f7
A
1957 if (opt == NULL)
1958 return ENOBUFS;
1959 }
1c79356b
A
1960 *pktopt = NULL;
1961
1962 if (!m || m->m_len == 0) {
1963 /*
55e303ae
A
1964 * Only turning off any previous options, regardless of
1965 * whether the opt is just created or given.
1c79356b
A
1966 */
1967 if (opt)
9bccf70c 1968 FREE(opt, M_IP6OPT);
1c79356b
A
1969 return(0);
1970 }
1971
b0d623f7
A
1972 priv = (proc_suser(p) == 0);
1973
1c79356b 1974 /* set options specified by user. */
1c79356b
A
1975 if ((error = ip6_setpktoptions(m, opt, priv, 1)) != 0) {
1976 ip6_clearpktopts(opt, 1, -1); /* XXX: discard all options */
55e303ae 1977 FREE(opt, M_IP6OPT);
1c79356b
A
1978 return(error);
1979 }
1980 *pktopt = opt;
1981 return(0);
1982}
1983
b0d623f7
A
1984static int
1985ip6_pcbopt(int optname, u_char *buf, int len, struct ip6_pktopts **pktopt)
1986{
1987 struct ip6_pktopts *opt;
1988
1989 opt = *pktopt;
1990 if (opt == NULL) {
1991 opt = _MALLOC(sizeof(*opt), M_IP6OPT, M_WAITOK);
1992 ip6_initpktopts(opt);
1993 *pktopt = opt;
1994 }
1995
1996 return (ip6_setpktopt(optname, buf, len, opt));
1997}
1998
1999static int
2000ip6_getpcbopt(struct ip6_pktopts *pktopt, int optname, struct sockopt *sopt)
2001{
2002 void *optdata = NULL;
2003 int optdatalen = 0;
2004 int deftclass = 0;
2005 int error = 0;
2006
2007 switch (optname) {
2008 case IPV6_TCLASS:
2009 if (pktopt && pktopt->ip6po_tclass >= 0)
2010 optdata = &pktopt->ip6po_tclass;
2011 else
2012 optdata = &deftclass;
2013 optdatalen = sizeof(int);
2014 break;
2015 default: /* should not happen */
2016#ifdef DIAGNOSTIC
2017 panic("ip6_getpcbopt: unexpected option\n");
2018#endif
2019 return (ENOPROTOOPT);
2020 }
2021
2022 error = sooptcopyout(sopt, optdata, optdatalen);
2023 return (error);
2024}
2025
2026static int
2027ip6_setpktopt(int optname, u_char *buf, int len, struct ip6_pktopts *opt)
2028{
2029 switch (optname) {
2030 case IPV6_TCLASS:
2031 {
2032 int tclass;
2033
2034 if (len != sizeof(int))
2035 return (EINVAL);
2036 tclass = *(int *)buf;
2037 if (tclass < -1 || tclass > 255)
2038 return (EINVAL);
2039
2040 opt->ip6po_tclass = tclass;
2041 break;
2042 }
2043
2044 default:
2045 return (ENOPROTOOPT);
2046 } /* end of switch */
2047
2048 return (0);
2049}
2050
1c79356b 2051/*
9bccf70c
A
2052 * initialize ip6_pktopts. beware that there are non-zero default values in
2053 * the struct.
1c79356b 2054 */
9bccf70c 2055void
b0d623f7 2056ip6_initpktopts(opt)
1c79356b 2057 struct ip6_pktopts *opt;
1c79356b 2058{
9bccf70c
A
2059 bzero(opt, sizeof(*opt));
2060 opt->ip6po_hlim = -1; /* -1 means default hop limit */
b0d623f7 2061 opt->ip6po_tclass = -1; /* -1 means default traffic class */
1c79356b
A
2062}
2063
2064void
2065ip6_clearpktopts(pktopt, needfree, optname)
2066 struct ip6_pktopts *pktopt;
2067 int needfree, optname;
2068{
2069 if (pktopt == NULL)
2070 return;
2071
9bccf70c 2072 if (optname == -1) {
1c79356b 2073 if (needfree && pktopt->ip6po_pktinfo)
9bccf70c 2074 FREE(pktopt->ip6po_pktinfo, M_IP6OPT);
1c79356b
A
2075 pktopt->ip6po_pktinfo = NULL;
2076 }
9bccf70c 2077 if (optname == -1)
1c79356b 2078 pktopt->ip6po_hlim = -1;
b0d623f7
A
2079 if (optname == -1)
2080 pktopt->ip6po_tclass = -1;
9bccf70c 2081 if (optname == -1) {
1c79356b 2082 if (needfree && pktopt->ip6po_nexthop)
9bccf70c 2083 FREE(pktopt->ip6po_nexthop, M_IP6OPT);
1c79356b
A
2084 pktopt->ip6po_nexthop = NULL;
2085 }
9bccf70c 2086 if (optname == -1) {
1c79356b 2087 if (needfree && pktopt->ip6po_hbh)
9bccf70c 2088 FREE(pktopt->ip6po_hbh, M_IP6OPT);
1c79356b
A
2089 pktopt->ip6po_hbh = NULL;
2090 }
9bccf70c 2091 if (optname == -1) {
1c79356b 2092 if (needfree && pktopt->ip6po_dest1)
9bccf70c 2093 FREE(pktopt->ip6po_dest1, M_IP6OPT);
1c79356b
A
2094 pktopt->ip6po_dest1 = NULL;
2095 }
9bccf70c 2096 if (optname == -1) {
1c79356b 2097 if (needfree && pktopt->ip6po_rhinfo.ip6po_rhi_rthdr)
9bccf70c 2098 FREE(pktopt->ip6po_rhinfo.ip6po_rhi_rthdr, M_IP6OPT);
1c79356b
A
2099 pktopt->ip6po_rhinfo.ip6po_rhi_rthdr = NULL;
2100 if (pktopt->ip6po_route.ro_rt) {
9bccf70c 2101 rtfree(pktopt->ip6po_route.ro_rt);
1c79356b
A
2102 pktopt->ip6po_route.ro_rt = NULL;
2103 }
2104 }
9bccf70c 2105 if (optname == -1) {
1c79356b 2106 if (needfree && pktopt->ip6po_dest2)
9bccf70c 2107 FREE(pktopt->ip6po_dest2, M_IP6OPT);
1c79356b
A
2108 pktopt->ip6po_dest2 = NULL;
2109 }
2110}
2111
9bccf70c
A
2112#define PKTOPT_EXTHDRCPY(type) \
2113do {\
2114 if (src->type) {\
1c79356b
A
2115 int hlen =\
2116 (((struct ip6_ext *)src->type)->ip6e_len + 1) << 3;\
2117 dst->type = _MALLOC(hlen, M_IP6OPT, canwait);\
2118 if (dst->type == NULL && canwait == M_NOWAIT)\
2119 goto bad;\
2120 bcopy(src->type, dst->type, hlen);\
9bccf70c
A
2121 }\
2122} while (0)
1c79356b
A
2123
2124struct ip6_pktopts *
2125ip6_copypktopts(src, canwait)
2126 struct ip6_pktopts *src;
2127 int canwait;
2128{
2129 struct ip6_pktopts *dst;
2130
2131 if (src == NULL) {
2132 printf("ip6_clearpktopts: invalid argument\n");
2133 return(NULL);
2134 }
2135
2136 dst = _MALLOC(sizeof(*dst), M_IP6OPT, canwait);
2137 if (dst == NULL && canwait == M_NOWAIT)
55e303ae 2138 return (NULL);
1c79356b
A
2139 bzero(dst, sizeof(*dst));
2140
2141 dst->ip6po_hlim = src->ip6po_hlim;
b0d623f7 2142 dst->ip6po_tclass = src->ip6po_tclass;
1c79356b
A
2143 if (src->ip6po_pktinfo) {
2144 dst->ip6po_pktinfo = _MALLOC(sizeof(*dst->ip6po_pktinfo),
2145 M_IP6OPT, canwait);
2146 if (dst->ip6po_pktinfo == NULL && canwait == M_NOWAIT)
2147 goto bad;
2148 *dst->ip6po_pktinfo = *src->ip6po_pktinfo;
2149 }
2150 if (src->ip6po_nexthop) {
2151 dst->ip6po_nexthop = _MALLOC(src->ip6po_nexthop->sa_len,
2152 M_IP6OPT, canwait);
2153 if (dst->ip6po_nexthop == NULL && canwait == M_NOWAIT)
2154 goto bad;
2155 bcopy(src->ip6po_nexthop, dst->ip6po_nexthop,
2156 src->ip6po_nexthop->sa_len);
2157 }
2158 PKTOPT_EXTHDRCPY(ip6po_hbh);
2159 PKTOPT_EXTHDRCPY(ip6po_dest1);
2160 PKTOPT_EXTHDRCPY(ip6po_dest2);
2161 PKTOPT_EXTHDRCPY(ip6po_rthdr); /* not copy the cached route */
2162 return(dst);
2163
2164 bad:
9bccf70c
A
2165 if (dst->ip6po_pktinfo) FREE(dst->ip6po_pktinfo, M_IP6OPT);
2166 if (dst->ip6po_nexthop) FREE(dst->ip6po_nexthop, M_IP6OPT);
2167 if (dst->ip6po_hbh) FREE(dst->ip6po_hbh, M_IP6OPT);
2168 if (dst->ip6po_dest1) FREE(dst->ip6po_dest1, M_IP6OPT);
2169 if (dst->ip6po_dest2) FREE(dst->ip6po_dest2, M_IP6OPT);
2170 if (dst->ip6po_rthdr) FREE(dst->ip6po_rthdr, M_IP6OPT);
55e303ae 2171 FREE(dst, M_IP6OPT);
1c79356b
A
2172 return(NULL);
2173}
2174#undef PKTOPT_EXTHDRCPY
2175
2176void
2177ip6_freepcbopts(pktopt)
2178 struct ip6_pktopts *pktopt;
2179{
2180 if (pktopt == NULL)
2181 return;
2182
2183 ip6_clearpktopts(pktopt, 1, -1);
2184
9bccf70c 2185 FREE(pktopt, M_IP6OPT);
1c79356b
A
2186}
2187
2188/*
2189 * Set the IP6 multicast options in response to user setsockopt().
2190 */
2191static int
91447636
A
2192ip6_setmoptions(
2193 int optname,
2194 struct inpcb* in6p,
2195 struct mbuf *m)
1c79356b
A
2196{
2197 int error = 0;
2198 u_int loop, ifindex;
2199 struct ipv6_mreq *mreq;
2200 struct ifnet *ifp;
55e303ae 2201 struct ip6_moptions **im6op = &in6p->in6p_moptions;
1c79356b 2202 struct ip6_moptions *im6o = *im6op;
55e303ae 2203 struct ip_moptions *imo;
1c79356b
A
2204 struct route_in6 ro;
2205 struct sockaddr_in6 *dst;
2206 struct in6_multi_mship *imm;
1c79356b
A
2207
2208 if (im6o == NULL) {
2209 /*
2210 * No multicast option buffer attached to the pcb;
2211 * allocate one and initialize to default values.
2212 */
2213 im6o = (struct ip6_moptions *)
2214 _MALLOC(sizeof(*im6o), M_IPMOPTS, M_WAITOK);
2215
2216 if (im6o == NULL)
2217 return(ENOBUFS);
2218 *im6op = im6o;
2219 im6o->im6o_multicast_ifp = NULL;
2220 im6o->im6o_multicast_hlim = ip6_defmcasthlim;
2221 im6o->im6o_multicast_loop = IPV6_DEFAULT_MULTICAST_LOOP;
2222 LIST_INIT(&im6o->im6o_memberships);
2223 }
55e303ae
A
2224
2225 if (in6p->inp_moptions == NULL) {
2226 /*
2227 * No IPv4 multicast option buffer attached to the pcb;
2228 * call ip_createmoptions to allocate one and initialize
2229 * to default values.
2230 */
2231 error = ip_createmoptions(&in6p->inp_moptions);
2232 if (error != 0)
2233 return error;
2234 }
2235 imo = in6p->inp_moptions;
1c79356b
A
2236
2237 switch (optname) {
2238
2239 case IPV6_MULTICAST_IF:
2240 /*
2241 * Select the interface for outgoing multicast packets.
2242 */
2243 if (m == NULL || m->m_len != sizeof(u_int)) {
2244 error = EINVAL;
2245 break;
2246 }
9bccf70c 2247 bcopy(mtod(m, u_int *), &ifindex, sizeof(ifindex));
b0d623f7
A
2248
2249 ifnet_head_lock_shared();
2250 /* Don't need to check is ifindex is < 0 since it's unsigned */
2251 if (if_index < ifindex) {
1c79356b 2252 error = ENXIO; /* XXX EINVAL? */
b0d623f7 2253 ifnet_head_done();
1c79356b
A
2254 break;
2255 }
2256 ifp = ifindex2ifnet[ifindex];
b0d623f7 2257 ifnet_head_done();
1c79356b
A
2258 if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
2259 error = EADDRNOTAVAIL;
2260 break;
2261 }
2262 im6o->im6o_multicast_ifp = ifp;
55e303ae 2263 imo->imo_multicast_ifp = ifp;
1c79356b
A
2264 break;
2265
2266 case IPV6_MULTICAST_HOPS:
2267 {
2268 /*
2269 * Set the IP6 hoplimit for outgoing multicast packets.
2270 */
2271 int optval;
2272 if (m == NULL || m->m_len != sizeof(int)) {
2273 error = EINVAL;
2274 break;
2275 }
9bccf70c 2276 bcopy(mtod(m, u_int *), &optval, sizeof(optval));
1c79356b
A
2277 if (optval < -1 || optval >= 256)
2278 error = EINVAL;
55e303ae 2279 else if (optval == -1) {
1c79356b 2280 im6o->im6o_multicast_hlim = ip6_defmcasthlim;
55e303ae
A
2281 imo->imo_multicast_ttl = IP_DEFAULT_MULTICAST_TTL;
2282 } else {
1c79356b 2283 im6o->im6o_multicast_hlim = optval;
55e303ae
A
2284 imo->imo_multicast_ttl = optval;
2285 }
1c79356b
A
2286 break;
2287 }
2288
2289 case IPV6_MULTICAST_LOOP:
2290 /*
2291 * Set the loopback flag for outgoing multicast packets.
2292 * Must be zero or one.
2293 */
9bccf70c
A
2294 if (m == NULL || m->m_len != sizeof(u_int)) {
2295 error = EINVAL;
2296 break;
2297 }
2298 bcopy(mtod(m, u_int *), &loop, sizeof(loop));
2299 if (loop > 1) {
1c79356b
A
2300 error = EINVAL;
2301 break;
2302 }
2303 im6o->im6o_multicast_loop = loop;
55e303ae 2304 imo->imo_multicast_loop = loop;
1c79356b
A
2305 break;
2306
2307 case IPV6_JOIN_GROUP:
2308 /*
2309 * Add a multicast group membership.
2310 * Group must be a valid IP6 multicast address.
2311 */
2312 if (m == NULL || m->m_len != sizeof(struct ipv6_mreq)) {
2313 error = EINVAL;
2314 break;
2315 }
2316 mreq = mtod(m, struct ipv6_mreq *);
55e303ae
A
2317 /*
2318 * If the interface is specified, validate it.
b0d623f7
A
2319 *
2320 * Don't need to check if it's < 0, since it's unsigned
55e303ae 2321 */
b0d623f7
A
2322 ifnet_head_lock_shared();
2323 if (if_index < mreq->ipv6mr_interface) {
2324 ifnet_head_done();
55e303ae
A
2325 error = ENXIO; /* XXX EINVAL? */
2326 break;
2327 }
b0d623f7
A
2328 ifp = ifindex2ifnet[mreq->ipv6mr_interface];
2329 ifnet_head_done();
2330
1c79356b
A
2331 if (IN6_IS_ADDR_UNSPECIFIED(&mreq->ipv6mr_multiaddr)) {
2332 /*
2333 * We use the unspecified address to specify to accept
2334 * all multicast addresses. Only super user is allowed
2335 * to do this.
2336 */
91447636 2337 if (suser(kauth_cred_get(), 0))
9bccf70c 2338 {
1c79356b
A
2339 error = EACCES;
2340 break;
2341 }
55e303ae
A
2342 } else if (IN6_IS_ADDR_V4MAPPED(&mreq->ipv6mr_multiaddr)) {
2343 struct ip_mreq v4req;
2344
2345 v4req.imr_multiaddr.s_addr = mreq->ipv6mr_multiaddr.s6_addr32[3];
2346 v4req.imr_interface.s_addr = INADDR_ANY;
2347
2348 /* Find an IPv4 address on the specified interface. */
2349 if (mreq->ipv6mr_interface != 0) {
2350 struct in_ifaddr *ifa;
2351
b0d623f7 2352 lck_rw_lock_shared(in_ifaddr_rwlock);
55e303ae
A
2353 TAILQ_FOREACH(ifa, &in_ifaddrhead, ia_link) {
2354 if (ifa->ia_ifp == ifp) {
2355 v4req.imr_interface = IA_SIN(ifa)->sin_addr;
2356 break;
2357 }
2358 }
b0d623f7 2359 lck_rw_done(in_ifaddr_rwlock);
55e303ae
A
2360
2361 if (v4req.imr_multiaddr.s_addr == 0) {
2362 /* Interface has no IPv4 address. */
2363 error = EINVAL;
2364 break;
2365 }
2366 }
2367
2368 error = ip_addmembership(imo, &v4req);
2369 break;
1c79356b
A
2370 } else if (!IN6_IS_ADDR_MULTICAST(&mreq->ipv6mr_multiaddr)) {
2371 error = EINVAL;
2372 break;
2373 }
1c79356b
A
2374 /*
2375 * If no interface was explicitly specified, choose an
2376 * appropriate one according to the given multicast address.
2377 */
2378 if (mreq->ipv6mr_interface == 0) {
2379 /*
2380 * If the multicast address is in node-local scope,
2381 * the interface should be a loopback interface.
2382 * Otherwise, look up the routing table for the
2383 * address, and choose the outgoing interface.
2384 * XXX: is it a good approach?
2385 */
2386 if (IN6_IS_ADDR_MC_NODELOCAL(&mreq->ipv6mr_multiaddr)) {
2d21ac55 2387 ifp = lo_ifp;
1c79356b
A
2388 } else {
2389 ro.ro_rt = NULL;
2390 dst = (struct sockaddr_in6 *)&ro.ro_dst;
2391 bzero(dst, sizeof(*dst));
2392 dst->sin6_len = sizeof(struct sockaddr_in6);
2393 dst->sin6_family = AF_INET6;
2394 dst->sin6_addr = mreq->ipv6mr_multiaddr;
2395 rtalloc((struct route *)&ro);
2396 if (ro.ro_rt == NULL) {
2397 error = EADDRNOTAVAIL;
2398 break;
2399 }
2400 ifp = ro.ro_rt->rt_ifp;
2401 rtfree(ro.ro_rt);
c910b4d9 2402 ro.ro_rt = NULL;
1c79356b 2403 }
b0d623f7 2404 }
1c79356b
A
2405
2406 /*
2407 * See if we found an interface, and confirm that it
2408 * supports multicast
2409 */
2410 if (ifp == NULL || (ifp->if_flags & IFF_MULTICAST) == 0) {
2411 error = EADDRNOTAVAIL;
2412 break;
2413 }
2414 /*
2415 * Put interface index into the multicast address,
2416 * if the address has link-local scope.
2417 */
2418 if (IN6_IS_ADDR_MC_LINKLOCAL(&mreq->ipv6mr_multiaddr)) {
2419 mreq->ipv6mr_multiaddr.s6_addr16[1]
2420 = htons(mreq->ipv6mr_interface);
2421 }
2422 /*
2423 * See if the membership already exists.
2424 */
91447636 2425 lck_mtx_lock(nd6_mutex);
1c79356b
A
2426 for (imm = im6o->im6o_memberships.lh_first;
2427 imm != NULL; imm = imm->i6mm_chain.le_next)
2428 if (imm->i6mm_maddr->in6m_ifp == ifp &&
2429 IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr,
2430 &mreq->ipv6mr_multiaddr))
2431 break;
2432 if (imm != NULL) {
2433 error = EADDRINUSE;
91447636 2434 lck_mtx_unlock(nd6_mutex);
1c79356b
A
2435 break;
2436 }
2437 /*
2438 * Everything looks good; add a new record to the multicast
2439 * address list for the given interface.
2440 */
2441 imm = _MALLOC(sizeof(*imm), M_IPMADDR, M_WAITOK);
2442 if (imm == NULL) {
2443 error = ENOBUFS;
91447636 2444 lck_mtx_unlock(nd6_mutex);
1c79356b
A
2445 break;
2446 }
2447 if ((imm->i6mm_maddr =
91447636 2448 in6_addmulti(&mreq->ipv6mr_multiaddr, ifp, &error, 1)) == NULL) {
9bccf70c 2449 FREE(imm, M_IPMADDR);
91447636 2450 lck_mtx_unlock(nd6_mutex);
1c79356b
A
2451 break;
2452 }
2453 LIST_INSERT_HEAD(&im6o->im6o_memberships, imm, i6mm_chain);
91447636 2454 lck_mtx_unlock(nd6_mutex);
1c79356b
A
2455 break;
2456
2457 case IPV6_LEAVE_GROUP:
2458 /*
2459 * Drop a multicast group membership.
2460 * Group must be a valid IP6 multicast address.
2461 */
2462 if (m == NULL || m->m_len != sizeof(struct ipv6_mreq)) {
2463 error = EINVAL;
2464 break;
2465 }
2466 mreq = mtod(m, struct ipv6_mreq *);
1c79356b
A
2467 /*
2468 * If an interface address was specified, get a pointer
2469 * to its ifnet structure.
b0d623f7
A
2470 *
2471 * Don't need to check if it's < 0, since it's unsigned.
1c79356b 2472 */
b0d623f7
A
2473 ifnet_head_lock_shared();
2474 if (if_index < mreq->ipv6mr_interface) {
2475 ifnet_head_done();
1c79356b
A
2476 error = ENXIO; /* XXX EINVAL? */
2477 break;
2478 }
2479 ifp = ifindex2ifnet[mreq->ipv6mr_interface];
b0d623f7 2480 ifnet_head_done();
55e303ae
A
2481
2482 if (IN6_IS_ADDR_UNSPECIFIED(&mreq->ipv6mr_multiaddr)) {
91447636 2483 if (suser(kauth_cred_get(), 0)) {
55e303ae
A
2484 error = EACCES;
2485 break;
2486 }
2487 } else if (IN6_IS_ADDR_V4MAPPED(&mreq->ipv6mr_multiaddr)) {
2488 struct ip_mreq v4req;
2489
2490 v4req.imr_multiaddr.s_addr = mreq->ipv6mr_multiaddr.s6_addr32[3];
2491 v4req.imr_interface.s_addr = INADDR_ANY;
2492
2493 if (ifp != NULL) {
2494 struct in_ifaddr *ifa;
2495
b0d623f7 2496 lck_rw_lock_shared(in_ifaddr_rwlock);
55e303ae
A
2497 TAILQ_FOREACH(ifa, &in_ifaddrhead, ia_link) {
2498 if (ifa->ia_ifp == ifp) {
2499 v4req.imr_interface = IA_SIN(ifa)->sin_addr;
2500 break;
2501 }
2502 }
b0d623f7 2503 lck_rw_done(in_ifaddr_rwlock);
55e303ae
A
2504 }
2505
2506 error = ip_dropmembership(imo, &v4req);
2507 break;
2508 } else if (!IN6_IS_ADDR_MULTICAST(&mreq->ipv6mr_multiaddr)) {
2509 error = EINVAL;
2510 break;
2511 }
1c79356b
A
2512 /*
2513 * Put interface index into the multicast address,
2514 * if the address has link-local scope.
2515 */
2516 if (IN6_IS_ADDR_MC_LINKLOCAL(&mreq->ipv6mr_multiaddr)) {
2517 mreq->ipv6mr_multiaddr.s6_addr16[1]
2518 = htons(mreq->ipv6mr_interface);
2519 }
2520 /*
2521 * Find the membership in the membership list.
2522 */
91447636 2523 lck_mtx_lock(nd6_mutex);
1c79356b
A
2524 for (imm = im6o->im6o_memberships.lh_first;
2525 imm != NULL; imm = imm->i6mm_chain.le_next) {
2526 if ((ifp == NULL ||
2527 imm->i6mm_maddr->in6m_ifp == ifp) &&
2528 IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr,
2529 &mreq->ipv6mr_multiaddr))
2530 break;
2531 }
2532 if (imm == NULL) {
2533 /* Unable to resolve interface */
2534 error = EADDRNOTAVAIL;
91447636 2535 lck_mtx_unlock(nd6_mutex);
1c79356b
A
2536 break;
2537 }
2538 /*
2539 * Give up the multicast address record to which the
2540 * membership points.
2541 */
2542 LIST_REMOVE(imm, i6mm_chain);
91447636
A
2543 in6_delmulti(imm->i6mm_maddr, 1);
2544 lck_mtx_unlock(nd6_mutex);
9bccf70c 2545 FREE(imm, M_IPMADDR);
1c79356b
A
2546 break;
2547
2548 default:
2549 error = EOPNOTSUPP;
2550 break;
2551 }
2552
2553 /*
2554 * If all options have default values, no need to keep the mbuf.
2555 */
91447636 2556 lck_mtx_lock(nd6_mutex);
1c79356b
A
2557 if (im6o->im6o_multicast_ifp == NULL &&
2558 im6o->im6o_multicast_hlim == ip6_defmcasthlim &&
2559 im6o->im6o_multicast_loop == IPV6_DEFAULT_MULTICAST_LOOP &&
2560 im6o->im6o_memberships.lh_first == NULL) {
9bccf70c 2561 FREE(*im6op, M_IPMOPTS);
1c79356b
A
2562 *im6op = NULL;
2563 }
55e303ae
A
2564 if (imo->imo_multicast_ifp == NULL &&
2565 imo->imo_multicast_vif == -1 &&
2566 imo->imo_multicast_ttl == IP_DEFAULT_MULTICAST_TTL &&
2567 imo->imo_multicast_loop == IP_DEFAULT_MULTICAST_LOOP &&
2568 imo->imo_num_memberships == 0) {
2569 ip_freemoptions(imo);
2570 in6p->inp_moptions = 0;
2571 }
91447636 2572 lck_mtx_unlock(nd6_mutex);
1c79356b
A
2573
2574 return(error);
2575}
2576
2577/*
2578 * Return the IP6 multicast options in response to user getsockopt().
2579 */
2580static int
2581ip6_getmoptions(optname, im6o, mp)
2582 int optname;
9bccf70c
A
2583 struct ip6_moptions *im6o;
2584 struct mbuf **mp;
1c79356b
A
2585{
2586 u_int *hlim, *loop, *ifindex;
2587
1c79356b 2588 *mp = m_get(M_WAIT, MT_HEADER); /*XXX*/
b0d623f7
A
2589 if (*mp == NULL)
2590 return ENOBUFS;
1c79356b
A
2591
2592 switch (optname) {
2593
2594 case IPV6_MULTICAST_IF:
2595 ifindex = mtod(*mp, u_int *);
2596 (*mp)->m_len = sizeof(u_int);
2597 if (im6o == NULL || im6o->im6o_multicast_ifp == NULL)
2598 *ifindex = 0;
2599 else
2600 *ifindex = im6o->im6o_multicast_ifp->if_index;
2601 return(0);
2602
2603 case IPV6_MULTICAST_HOPS:
2604 hlim = mtod(*mp, u_int *);
2605 (*mp)->m_len = sizeof(u_int);
2606 if (im6o == NULL)
2607 *hlim = ip6_defmcasthlim;
2608 else
2609 *hlim = im6o->im6o_multicast_hlim;
2610 return(0);
2611
2612 case IPV6_MULTICAST_LOOP:
2613 loop = mtod(*mp, u_int *);
2614 (*mp)->m_len = sizeof(u_int);
2615 if (im6o == NULL)
2616 *loop = ip6_defmcasthlim;
2617 else
2618 *loop = im6o->im6o_multicast_loop;
2619 return(0);
2620
2621 default:
2622 return(EOPNOTSUPP);
2623 }
2624}
2625
2626/*
2627 * Discard the IP6 multicast options.
2628 */
2629void
2630ip6_freemoptions(im6o)
9bccf70c 2631 struct ip6_moptions *im6o;
1c79356b
A
2632{
2633 struct in6_multi_mship *imm;
2634
2635 if (im6o == NULL)
2636 return;
91447636
A
2637
2638 lck_mtx_lock(nd6_mutex);
1c79356b
A
2639 while ((imm = im6o->im6o_memberships.lh_first) != NULL) {
2640 LIST_REMOVE(imm, i6mm_chain);
2641 if (imm->i6mm_maddr)
91447636 2642 in6_delmulti(imm->i6mm_maddr, 1);
9bccf70c 2643 FREE(imm, M_IPMADDR);
1c79356b 2644 }
91447636 2645 lck_mtx_unlock(nd6_mutex);
9bccf70c 2646 FREE(im6o, M_IPMOPTS);
1c79356b
A
2647}
2648
2649/*
2650 * Set IPv6 outgoing packet options based on advanced API.
2651 */
2652int
2653ip6_setpktoptions(control, opt, priv, needcopy)
2654 struct mbuf *control;
2655 struct ip6_pktopts *opt;
2656 int priv, needcopy;
2657{
9bccf70c 2658 struct cmsghdr *cm = 0;
1c79356b
A
2659
2660 if (control == 0 || opt == 0)
2661 return(EINVAL);
2662
b0d623f7 2663 ip6_initpktopts(opt);
1c79356b
A
2664
2665 /*
2666 * XXX: Currently, we assume all the optional information is stored
2667 * in a single mbuf.
2668 */
2669 if (control->m_next)
2670 return(EINVAL);
2671
2672 for (; control->m_len; control->m_data += CMSG_ALIGN(cm->cmsg_len),
2673 control->m_len -= CMSG_ALIGN(cm->cmsg_len)) {
2674 cm = mtod(control, struct cmsghdr *);
2675 if (cm->cmsg_len == 0 || cm->cmsg_len > control->m_len)
2676 return(EINVAL);
2677 if (cm->cmsg_level != IPPROTO_IPV6)
2678 continue;
2679
9bccf70c
A
2680 /*
2681 * XXX should check if RFC2292 API is mixed with 2292bis API
2682 */
2683 switch (cm->cmsg_type) {
1c79356b
A
2684 case IPV6_PKTINFO:
2685 if (cm->cmsg_len != CMSG_LEN(sizeof(struct in6_pktinfo)))
2686 return(EINVAL);
2687 if (needcopy) {
2688 /* XXX: Is it really WAITOK? */
2689 opt->ip6po_pktinfo =
2690 _MALLOC(sizeof(struct in6_pktinfo),
2691 M_IP6OPT, M_WAITOK);
b0d623f7
A
2692 if (opt->ip6po_pktinfo == NULL)
2693 return ENOBUFS;
9bccf70c
A
2694 bcopy(CMSG_DATA(cm), opt->ip6po_pktinfo,
2695 sizeof(struct in6_pktinfo));
1c79356b
A
2696 } else
2697 opt->ip6po_pktinfo =
2698 (struct in6_pktinfo *)CMSG_DATA(cm);
2699 if (opt->ip6po_pktinfo->ipi6_ifindex &&
2700 IN6_IS_ADDR_LINKLOCAL(&opt->ip6po_pktinfo->ipi6_addr))
2701 opt->ip6po_pktinfo->ipi6_addr.s6_addr16[1] =
2702 htons(opt->ip6po_pktinfo->ipi6_ifindex);
2703
b0d623f7 2704 if (opt->ip6po_pktinfo->ipi6_ifindex > if_index) {
1c79356b
A
2705 return(ENXIO);
2706 }
2707
2708 /*
2709 * Check if the requested source address is indeed a
9bccf70c
A
2710 * unicast address assigned to the node, and can be
2711 * used as the packet's source address.
1c79356b
A
2712 */
2713 if (!IN6_IS_ADDR_UNSPECIFIED(&opt->ip6po_pktinfo->ipi6_addr)) {
9bccf70c 2714 struct in6_ifaddr *ia6;
1c79356b
A
2715 struct sockaddr_in6 sin6;
2716
2717 bzero(&sin6, sizeof(sin6));
2718 sin6.sin6_len = sizeof(sin6);
2719 sin6.sin6_family = AF_INET6;
2720 sin6.sin6_addr =
2721 opt->ip6po_pktinfo->ipi6_addr;
9bccf70c
A
2722 ia6 = (struct in6_ifaddr *)ifa_ifwithaddr(sin6tosa(&sin6));
2723 if (ia6 == NULL ||
2724 (ia6->ia6_flags & (IN6_IFF_ANYCAST |
91447636
A
2725 IN6_IFF_NOTREADY)) != 0) {
2726 if (ia6) ifafree(&ia6->ia_ifa);
1c79356b 2727 return(EADDRNOTAVAIL);
91447636
A
2728 }
2729 ifafree(&ia6->ia_ifa);
2730 ia6 = NULL;
1c79356b
A
2731 }
2732 break;
2733
2734 case IPV6_HOPLIMIT:
2735 if (cm->cmsg_len != CMSG_LEN(sizeof(int)))
2736 return(EINVAL);
2737
2738 opt->ip6po_hlim = *(int *)CMSG_DATA(cm);
2739 if (opt->ip6po_hlim < -1 || opt->ip6po_hlim > 255)
2740 return(EINVAL);
2741 break;
2742
b0d623f7
A
2743 case IPV6_TCLASS:
2744 if (cm->cmsg_len != CMSG_LEN(sizeof(int)))
2745 return(EINVAL);
2746
2747 opt->ip6po_tclass = *(int *)CMSG_DATA(cm);
2748 if (opt->ip6po_tclass < -1 || opt->ip6po_tclass > 255)
2749 return (EINVAL);
2750 break;
2751
1c79356b
A
2752 case IPV6_NEXTHOP:
2753 if (!priv)
2754 return(EPERM);
9bccf70c 2755
1c79356b
A
2756 if (cm->cmsg_len < sizeof(u_char) ||
2757 /* check if cmsg_len is large enough for sa_len */
2758 cm->cmsg_len < CMSG_LEN(*CMSG_DATA(cm)))
2759 return(EINVAL);
2760
2761 if (needcopy) {
2762 opt->ip6po_nexthop =
2763 _MALLOC(*CMSG_DATA(cm),
2764 M_IP6OPT, M_WAITOK);
b0d623f7
A
2765 if (opt->ip6po_nexthop == NULL)
2766 return ENOBUFS;
1c79356b
A
2767 bcopy(CMSG_DATA(cm),
2768 opt->ip6po_nexthop,
2769 *CMSG_DATA(cm));
2770 } else
2771 opt->ip6po_nexthop =
2772 (struct sockaddr *)CMSG_DATA(cm);
2773 break;
2774
2775 case IPV6_HOPOPTS:
2776 {
2777 struct ip6_hbh *hbh;
2778 int hbhlen;
2779
2780 if (cm->cmsg_len < CMSG_LEN(sizeof(struct ip6_hbh)))
2781 return(EINVAL);
2782 hbh = (struct ip6_hbh *)CMSG_DATA(cm);
2783 hbhlen = (hbh->ip6h_len + 1) << 3;
2784 if (cm->cmsg_len != CMSG_LEN(hbhlen))
2785 return(EINVAL);
2786
2787 if (needcopy) {
2788 opt->ip6po_hbh =
2789 _MALLOC(hbhlen, M_IP6OPT, M_WAITOK);
b0d623f7
A
2790 if (opt->ip6po_hbh == NULL)
2791 return ENOBUFS;
1c79356b
A
2792 bcopy(hbh, opt->ip6po_hbh, hbhlen);
2793 } else
2794 opt->ip6po_hbh = hbh;
2795 break;
2796 }
2797
2798 case IPV6_DSTOPTS:
2799 {
9bccf70c 2800 struct ip6_dest *dest, **newdest;
1c79356b
A
2801 int destlen;
2802
2803 if (cm->cmsg_len < CMSG_LEN(sizeof(struct ip6_dest)))
2804 return(EINVAL);
2805 dest = (struct ip6_dest *)CMSG_DATA(cm);
2806 destlen = (dest->ip6d_len + 1) << 3;
2807 if (cm->cmsg_len != CMSG_LEN(destlen))
2808 return(EINVAL);
2809
9bccf70c
A
2810 /*
2811 * The old advacned API is ambiguous on this
2812 * point. Our approach is to determine the
2813 * position based according to the existence
2814 * of a routing header. Note, however, that
2815 * this depends on the order of the extension
2816 * headers in the ancillary data; the 1st part
2817 * of the destination options header must
2818 * appear before the routing header in the
2819 * ancillary data, too.
2820 * RFC2292bis solved the ambiguity by
2821 * introducing separate cmsg types.
1c79356b 2822 */
9bccf70c
A
2823 if (opt->ip6po_rthdr == NULL)
2824 newdest = &opt->ip6po_dest1;
2825 else
2826 newdest = &opt->ip6po_dest2;
2827
2828 if (needcopy) {
2829 *newdest = _MALLOC(destlen, M_IP6OPT, M_WAITOK);
b0d623f7
A
2830 if (*newdest == NULL)
2831 return ENOBUFS;
9bccf70c
A
2832 bcopy(dest, *newdest, destlen);
2833 } else
2834 *newdest = dest;
2835
1c79356b
A
2836 break;
2837 }
2838
2839 case IPV6_RTHDR:
2840 {
2841 struct ip6_rthdr *rth;
2842 int rthlen;
2843
2844 if (cm->cmsg_len < CMSG_LEN(sizeof(struct ip6_rthdr)))
2845 return(EINVAL);
2846 rth = (struct ip6_rthdr *)CMSG_DATA(cm);
2847 rthlen = (rth->ip6r_len + 1) << 3;
2848 if (cm->cmsg_len != CMSG_LEN(rthlen))
2849 return(EINVAL);
2850
9bccf70c 2851 switch (rth->ip6r_type) {
1c79356b
A
2852 case IPV6_RTHDR_TYPE_0:
2853 /* must contain one addr */
2854 if (rth->ip6r_len == 0)
2855 return(EINVAL);
2856 /* length must be even */
2857 if (rth->ip6r_len % 2)
2858 return(EINVAL);
2859 if (rth->ip6r_len / 2 != rth->ip6r_segleft)
2860 return(EINVAL);
2861 break;
2862 default:
2863 return(EINVAL); /* not supported */
2864 }
2865
2866 if (needcopy) {
2867 opt->ip6po_rthdr = _MALLOC(rthlen, M_IP6OPT,
2868 M_WAITOK);
b0d623f7
A
2869 if (opt->ip6po_rthdr == NULL)
2870 return ENOBUFS;
1c79356b
A
2871 bcopy(rth, opt->ip6po_rthdr, rthlen);
2872 } else
2873 opt->ip6po_rthdr = rth;
2874
2875 break;
2876 }
2877
1c79356b
A
2878 default:
2879 return(ENOPROTOOPT);
2880 }
2881 }
2882
2883 return(0);
2884}
2885
2886/*
2887 * Routine called from ip6_output() to loop back a copy of an IP6 multicast
2888 * packet to the input queue of a specified interface. Note that this
2889 * calls the output routine of the loopback "driver", but with an interface
2890 * pointer that might NOT be &loif -- easier than replicating that code here.
2891 */
2892void
91447636
A
2893ip6_mloopback(
2894 struct ifnet *ifp,
2895 struct mbuf *m,
2896 struct sockaddr_in6 *dst)
1c79356b 2897{
9bccf70c
A
2898 struct mbuf *copym;
2899 struct ip6_hdr *ip6;
1c79356b
A
2900
2901 copym = m_copy(m, 0, M_COPYALL);
9bccf70c
A
2902 if (copym == NULL)
2903 return;
2904
2905 /*
2906 * Make sure to deep-copy IPv6 header portion in case the data
2907 * is in an mbuf cluster, so that we can safely override the IPv6
2908 * header portion later.
2909 */
2910 if ((copym->m_flags & M_EXT) != 0 ||
2911 copym->m_len < sizeof(struct ip6_hdr)) {
2912 copym = m_pullup(copym, sizeof(struct ip6_hdr));
2913 if (copym == NULL)
2914 return;
2915 }
2916
2917#if DIAGNOSTIC
2918 if (copym->m_len < sizeof(*ip6)) {
2919 m_freem(copym);
2920 return;
2921 }
2922#endif
2923
2924 ip6 = mtod(copym, struct ip6_hdr *);
2925#ifndef SCOPEDROUTING
2926 /*
2927 * clear embedded scope identifiers if necessary.
2928 * in6_clearscope will touch the addresses only when necessary.
2929 */
2930 in6_clearscope(&ip6->ip6_src);
2931 in6_clearscope(&ip6->ip6_dst);
2932#endif
2933
1c79356b 2934#ifdef __APPLE__
9bccf70c
A
2935
2936 /* Makes sure the HW checksum flags are cleaned before sending the packet */
2937
91447636 2938 copym->m_pkthdr.rcvif = 0;
9bccf70c
A
2939 copym->m_pkthdr.csum_data = 0;
2940 copym->m_pkthdr.csum_flags = 0;
2941
91447636 2942 if (lo_ifp) {
55e303ae 2943 copym->m_pkthdr.rcvif = ifp;
91447636
A
2944 lck_mtx_unlock(ip6_mutex);
2945 dlil_output(lo_ifp, PF_INET6, copym, 0, (struct sockaddr *)dst, 0);
2946 lck_mtx_lock(ip6_mutex);
55e303ae 2947 } else
9bccf70c 2948 m_free(copym);
1c79356b 2949#else
55e303ae 2950 (void)if_simloop(ifp, copym, dst->sin6_family, NULL);
1c79356b 2951#endif
1c79356b
A
2952}
2953
2954/*
2955 * Chop IPv6 header off from the payload.
2956 */
2957static int
2958ip6_splithdr(m, exthdrs)
2959 struct mbuf *m;
2960 struct ip6_exthdrs *exthdrs;
2961{
2962 struct mbuf *mh;
2963 struct ip6_hdr *ip6;
2964
2965 ip6 = mtod(m, struct ip6_hdr *);
2966 if (m->m_len > sizeof(*ip6)) {
2d21ac55 2967 MGETHDR(mh, M_DONTWAIT, MT_HEADER); /* MAC-OK */
1c79356b
A
2968 if (mh == 0) {
2969 m_freem(m);
2970 return ENOBUFS;
2971 }
2972 M_COPY_PKTHDR(mh, m);
2973 MH_ALIGN(mh, sizeof(*ip6));
2974 m->m_flags &= ~M_PKTHDR;
2975 m->m_len -= sizeof(*ip6);
2976 m->m_data += sizeof(*ip6);
2977 mh->m_next = m;
2978 m = mh;
2979 m->m_len = sizeof(*ip6);
2980 bcopy((caddr_t)ip6, mtod(m, caddr_t), sizeof(*ip6));
2981 }
2982 exthdrs->ip6e_ip6 = m;
2983 return 0;
2984}
2985
2986/*
2987 * Compute IPv6 extension header length.
2988 */
1c79356b
A
2989int
2990ip6_optlen(in6p)
2991 struct in6pcb *in6p;
2992{
2993 int len;
2994
2995 if (!in6p->in6p_outputopts)
2996 return 0;
2997
2998 len = 0;
2999#define elen(x) \
3000 (((struct ip6_ext *)(x)) ? (((struct ip6_ext *)(x))->ip6e_len + 1) << 3 : 0)
3001
3002 len += elen(in6p->in6p_outputopts->ip6po_hbh);
3003 if (in6p->in6p_outputopts->ip6po_rthdr)
3004 /* dest1 is valid with rthdr only */
3005 len += elen(in6p->in6p_outputopts->ip6po_dest1);
3006 len += elen(in6p->in6p_outputopts->ip6po_rthdr);
3007 len += elen(in6p->in6p_outputopts->ip6po_dest2);
3008 return len;
3009#undef elen
3010}
2d21ac55 3011