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