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