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