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