Deleted Added
full compact
ip6_output.c (60889) ip6_output.c (62587)
1/* $FreeBSD: head/sys/netinet6/ip6_output.c 62587 2000-07-04 16:35:15Z itojun $ */
2/* $KAME: ip6_output.c,v 1.115 2000/07/03 13:23:28 itojun Exp $ */
3
1/*
2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
4/*
5 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright

--- 11 unchanged lines hidden (view full) ---

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.
28 *
29 * $FreeBSD: head/sys/netinet6/ip6_output.c 60889 2000-05-24 21:16:56Z archie $
30 */
31
32/*
33 * Copyright (c) 1982, 1986, 1988, 1990, 1993
34 * The Regents of the University of California. All rights reserved.
35 *
36 * Redistribution and use in source and binary forms, with or without
37 * modification, are permitted provided that the following conditions

--- 21 unchanged lines hidden (view full) ---

59 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62 * SUCH DAMAGE.
63 *
64 * @(#)ip_output.c 8.3 (Berkeley) 1/21/94
65 */
66
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

--- 21 unchanged lines hidden (view full) ---

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
67#include "opt_ipsec.h"
68#include "opt_ip6fw.h"
68#include "opt_ip6fw.h"
69#include "opt_inet.h"
70#include "opt_inet6.h"
71#include "opt_ipsec.h"
69
70#include <sys/param.h>
71#include <sys/malloc.h>
72#include <sys/mbuf.h>
73#include <sys/errno.h>
74#include <sys/protosw.h>
75#include <sys/socket.h>
76#include <sys/socketvar.h>
77#include <sys/systm.h>
78#include <sys/kernel.h>
79#include <sys/proc.h>
80
81#include <net/if.h>
82#include <net/route.h>
83
84#include <netinet/in.h>
85#include <netinet/in_var.h>
72
73#include <sys/param.h>
74#include <sys/malloc.h>
75#include <sys/mbuf.h>
76#include <sys/errno.h>
77#include <sys/protosw.h>
78#include <sys/socket.h>
79#include <sys/socketvar.h>
80#include <sys/systm.h>
81#include <sys/kernel.h>
82#include <sys/proc.h>
83
84#include <net/if.h>
85#include <net/route.h>
86
87#include <netinet/in.h>
88#include <netinet/in_var.h>
86#include <netinet6/ip6.h>
87#include <netinet6/icmp6.h>
88#include <netinet/in_pcb.h>
89#include
90#include
89#include <netinet6/ip6_var.h>
91#include <netinet6/ip6_var.h>
92#include <netinet/in_pcb.h>
90#include <netinet6/nd6.h>
91
92#ifdef IPSEC
93#include <netinet6/ipsec.h>
93#include <netinet6/nd6.h>
94
95#ifdef IPSEC
96#include <netinet6/ipsec.h>
97#ifdef INET6
94#include <netinet6/ipsec6.h>
98#include <netinet6/ipsec6.h>
95#include <netkey/key.h>
96#ifdef IPSEC_DEBUG
97#include <netkey/key_debug.h>
98#else
99#define KEYDEBUG(lev,arg)
100#endif
99#endif
100#include <netkey/key.h>
101#endif /* IPSEC */
102
101#endif /* IPSEC */
102
103#include "loop.h"
104
105#include <net/net_osdep.h>
106
107#ifdef IPV6FIREWALL
108#include <netinet6/ip6_fw.h>
109#endif
110
111static MALLOC_DEFINE(M_IPMOPTS, "ip6_moptions", "internet multicast options");
112
113struct ip6_exthdrs {
103#include <net/net_osdep.h>
104
105#ifdef IPV6FIREWALL
106#include <netinet6/ip6_fw.h>
107#endif
108
109static MALLOC_DEFINE(M_IPMOPTS, "ip6_moptions", "internet multicast options");
110
111struct ip6_exthdrs {
114 struct mbuf *ip6e_ip6;
115 struct mbuf *ip6e_hbh;
116 struct mbuf *ip6e_dest1;
117 struct mbuf *ip6e_rthdr;
118 struct mbuf *ip6e_dest2;
112 struct mbuf *ip6e_ip6;
113 struct mbuf *ip6e_hbh;
114 struct mbuf *ip6e_dest1;
115 struct mbuf *ip6e_rthdr;
116 struct mbuf *ip6e_dest2;
119};
120
117};
118
121static int ip6_pcbopts __P((struct ip6_pktopts **, struct mbuf *,
119static int ip6_pcbopts __P((struct ip6_pktopts **, struct mbuf *,
122 struct socket *, struct sockopt *sopt));
120 struct socket *, struct sockopt *sopt));
123static int ip6_setmoptions __P((int, struct ip6_moptions **, struct mbuf *));
124static int ip6_getmoptions __P((int, struct ip6_moptions *, struct mbuf **));
125static int ip6_copyexthdr __P((struct mbuf **, caddr_t, int));
126static int ip6_insertfraghdr __P((struct mbuf *, struct mbuf *, int,
121static int ip6_setmoptions __P((int, struct ip6_moptions **, struct mbuf *));
122static int ip6_getmoptions __P((int, struct ip6_moptions *, struct mbuf **));
123static int ip6_copyexthdr __P((struct mbuf **, caddr_t, int));
124static int ip6_insertfraghdr __P((struct mbuf *, struct mbuf *, int,
127 struct ip6_frag **));
125 struct ip6_frag **));
128static int ip6_insert_jumboopt __P((struct ip6_exthdrs *, u_int32_t));
129static int ip6_splithdr __P((struct mbuf *, struct ip6_exthdrs *));
126static int ip6_insert_jumboopt __P((struct ip6_exthdrs *, u_int32_t));
127static int ip6_splithdr __P((struct mbuf *, struct ip6_exthdrs *));
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.
137 */
138int
139ip6_output(m0, opt, ro, flags, im6o, ifpp)
140 struct mbuf *m0;
141 struct ip6_pktopts *opt;
142 struct route_in6 *ro;
143 int flags;
144 struct ip6_moptions *im6o;
145 struct ifnet **ifpp; /* XXX: just for statistics */
146{
147 struct ip6_hdr *ip6, *mhip6;
128
129/*
130 * IP6 output. The packet in mbuf chain m contains a skeletal IP6
131 * header (with pri, len, nxt, hlim, src, dst).
132 * This function may modify ver and hlim only.
133 * The mbuf chain containing the packet will be freed.
134 * The mbuf opt, if present, will not be freed.
135 */
136int
137ip6_output(m0, opt, ro, flags, im6o, ifpp)
138 struct mbuf *m0;
139 struct ip6_pktopts *opt;
140 struct route_in6 *ro;
141 int flags;
142 struct ip6_moptions *im6o;
143 struct ifnet **ifpp; /* XXX: just for statistics */
144{
145 struct ip6_hdr *ip6, *mhip6;
148 struct ifnet *ifp;
146 struct ifnet *ifp, *origifp;
149 struct mbuf *m = m0;
150 int hlen, tlen, len, off;
151 struct route_in6 ip6route;
152 struct sockaddr_in6 *dst;
153 int error = 0;
154 struct in6_ifaddr *ia;
155 u_long mtu;
156 u_int32_t optlen = 0, plen = 0, unfragpartlen = 0;
157 struct ip6_exthdrs exthdrs;
158 struct in6_addr finaldst;
159 struct route_in6 *ro_pmtu = NULL;
160 int hdrsplit = 0;
161 int needipsec = 0;
162#ifdef IPSEC
163 int needipsectun = 0;
164 struct socket *so;
165 struct secpolicy *sp = NULL;
166
167 /* for AH processing. stupid to have "socket" variable in IP layer... */
147 struct mbuf *m = m0;
148 int hlen, tlen, len, off;
149 struct route_in6 ip6route;
150 struct sockaddr_in6 *dst;
151 int error = 0;
152 struct in6_ifaddr *ia;
153 u_long mtu;
154 u_int32_t optlen = 0, plen = 0, unfragpartlen = 0;
155 struct ip6_exthdrs exthdrs;
156 struct in6_addr finaldst;
157 struct route_in6 *ro_pmtu = NULL;
158 int hdrsplit = 0;
159 int needipsec = 0;
160#ifdef IPSEC
161 int needipsectun = 0;
162 struct socket *so;
163 struct secpolicy *sp = NULL;
164
165 /* for AH processing. stupid to have "socket" variable in IP layer... */
168 if ((flags & IPV6_SOCKINMRCVIF) != 0) {
169 so = (struct socket *)m->m_pkthdr.rcvif;
170 m->m_pkthdr.rcvif = NULL;
171 } else
172 so = NULL;
166 so = ipsec_getsocket(m);
167 ipsec_setsocket(m, NULL);
173 ip6 = mtod(m, struct ip6_hdr *);
174#endif /* IPSEC */
175
168 ip6 = mtod(m, struct ip6_hdr *);
169#endif /* IPSEC */
170
176#define MAKE_EXTHDR(hp,mp) \
177 { \
171#define MAKE_EXTHDR(hp, mp) \
172 do { \
178 if (hp) { \
179 struct ip6_ext *eh = (struct ip6_ext *)(hp); \
180 error = ip6_copyexthdr((mp), (caddr_t)(hp), \
181 ((eh)->ip6e_len + 1) << 3); \
182 if (error) \
183 goto freehdrs; \
184 } \
173 if (hp) { \
174 struct ip6_ext *eh = (struct ip6_ext *)(hp); \
175 error = ip6_copyexthdr((mp), (caddr_t)(hp), \
176 ((eh)->ip6e_len + 1) << 3); \
177 if (error) \
178 goto freehdrs; \
179 } \
185 }
186
180 } while (0)
181
187 bzero(&exthdrs, sizeof(exthdrs));
182 bzero(&exthdrs, sizeof(exthdrs));
183
188 if (opt) {
189 /* Hop-by-Hop options header */
190 MAKE_EXTHDR(opt->ip6po_hbh, &exthdrs.ip6e_hbh);
191 /* Destination options header(1st part) */
192 MAKE_EXTHDR(opt->ip6po_dest1, &exthdrs.ip6e_dest1);
193 /* Routing header */
194 MAKE_EXTHDR(opt->ip6po_rthdr, &exthdrs.ip6e_rthdr);
195 /* Destination options header(2nd part) */

--- 4 unchanged lines hidden (view full) ---

200 /* get a security policy for this packet */
201 if (so == NULL)
202 sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, 0, &error);
203 else
204 sp = ipsec6_getpolicybysock(m, IPSEC_DIR_OUTBOUND, so, &error);
205
206 if (sp == NULL) {
207 ipsec6stat.out_inval++;
184 if (opt) {
185 /* Hop-by-Hop options header */
186 MAKE_EXTHDR(opt->ip6po_hbh, &exthdrs.ip6e_hbh);
187 /* Destination options header(1st part) */
188 MAKE_EXTHDR(opt->ip6po_dest1, &exthdrs.ip6e_dest1);
189 /* Routing header */
190 MAKE_EXTHDR(opt->ip6po_rthdr, &exthdrs.ip6e_rthdr);
191 /* Destination options header(2nd part) */

--- 4 unchanged lines hidden (view full) ---

196 /* get a security policy for this packet */
197 if (so == NULL)
198 sp = ipsec6_getpolicybyaddr(m, IPSEC_DIR_OUTBOUND, 0, &error);
199 else
200 sp = ipsec6_getpolicybysock(m, IPSEC_DIR_OUTBOUND, so, &error);
201
202 if (sp == NULL) {
203 ipsec6stat.out_inval++;
208 goto bad;
204 goto freehdrs;
209 }
210
211 error = 0;
212
213 /* check policy */
214 switch (sp->policy) {
215 case IPSEC_POLICY_DISCARD:
216 /*
217 * This packet is just discarded.
218 */
219 ipsec6stat.out_polvio++;
205 }
206
207 error = 0;
208
209 /* check policy */
210 switch (sp->policy) {
211 case IPSEC_POLICY_DISCARD:
212 /*
213 * This packet is just discarded.
214 */
215 ipsec6stat.out_polvio++;
220 goto bad;
216 goto freehdrs;
221
222 case IPSEC_POLICY_BYPASS:
223 case IPSEC_POLICY_NONE:
224 /* no need to do IPsec. */
225 needipsec = 0;
226 break;
227
228 case IPSEC_POLICY_IPSEC:
229 if (sp->req == NULL) {
217
218 case IPSEC_POLICY_BYPASS:
219 case IPSEC_POLICY_NONE:
220 /* no need to do IPsec. */
221 needipsec = 0;
222 break;
223
224 case IPSEC_POLICY_IPSEC:
225 if (sp->req == NULL) {
230 /* XXX should be panic ? */
231 printf("ip6_output: No IPsec request specified.\n");
232 error = EINVAL;
233 goto bad;
226 /* acquire a policy */
227 error = key_spdacquire(sp);
228 goto freehdrs;
234 }
235 needipsec = 1;
236 break;
237
238 case IPSEC_POLICY_ENTRUST:
239 default:
240 printf("ip6_output: Invalid policy found. %d\n", sp->policy);
241 }

--- 74 unchanged lines hidden (view full) ---

316 if (!hdrsplit)
317 panic("assumption failed: hdr not split");
318 exthdrs.ip6e_dest2->m_next = m->m_next;
319 m->m_next = exthdrs.ip6e_dest2;
320 *mtod(exthdrs.ip6e_dest2, u_char *) = ip6->ip6_nxt;
321 ip6->ip6_nxt = IPPROTO_DSTOPTS;
322 }
323
229 }
230 needipsec = 1;
231 break;
232
233 case IPSEC_POLICY_ENTRUST:
234 default:
235 printf("ip6_output: Invalid policy found. %d\n", sp->policy);
236 }

--- 74 unchanged lines hidden (view full) ---

311 if (!hdrsplit)
312 panic("assumption failed: hdr not split");
313 exthdrs.ip6e_dest2->m_next = m->m_next;
314 m->m_next = exthdrs.ip6e_dest2;
315 *mtod(exthdrs.ip6e_dest2, u_char *) = ip6->ip6_nxt;
316 ip6->ip6_nxt = IPPROTO_DSTOPTS;
317 }
318
324#define MAKE_CHAIN(m,mp,p,i)\
325 {\
319#define MAKE_CHAIN(m, mp, p, i)\
320 do {\
326 if (m) {\
327 if (!hdrsplit) \
328 panic("assumption failed: hdr not split"); \
329 *mtod((m), u_char *) = *(p);\
330 *(p) = (i);\
331 p = mtod((m), u_char *);\
332 (m)->m_next = (mp)->m_next;\
333 (mp)->m_next = (m);\
334 (mp) = (m);\
335 }\
321 if (m) {\
322 if (!hdrsplit) \
323 panic("assumption failed: hdr not split"); \
324 *mtod((m), u_char *) = *(p);\
325 *(p) = (i);\
326 p = mtod((m), u_char *);\
327 (m)->m_next = (mp)->m_next;\
328 (mp)->m_next = (m);\
329 (mp) = (m);\
330 }\
336 }
331 } while (0)
337 /*
338 * result: IPv6 hbh dest1 rthdr dest2 payload
339 * m will point to IPv6 header. mprev will point to the
340 * extension header prior to dest2 (rthdr in the above case).
341 */
342 MAKE_CHAIN(exthdrs.ip6e_hbh, mprev,
343 nexthdrp, IPPROTO_HOPOPTS);
344 MAKE_CHAIN(exthdrs.ip6e_dest1, mprev,

--- 120 unchanged lines hidden (view full) ---

465 RTFREE(ro->ro_rt);
466 ro->ro_rt = (struct rtentry *)0;
467 }
468 if (ro->ro_rt == 0) {
469 bzero(dst, sizeof(*dst));
470 dst->sin6_family = AF_INET6;
471 dst->sin6_len = sizeof(struct sockaddr_in6);
472 dst->sin6_addr = ip6->ip6_dst;
332 /*
333 * result: IPv6 hbh dest1 rthdr dest2 payload
334 * m will point to IPv6 header. mprev will point to the
335 * extension header prior to dest2 (rthdr in the above case).
336 */
337 MAKE_CHAIN(exthdrs.ip6e_hbh, mprev,
338 nexthdrp, IPPROTO_HOPOPTS);
339 MAKE_CHAIN(exthdrs.ip6e_dest1, mprev,

--- 120 unchanged lines hidden (view full) ---

460 RTFREE(ro->ro_rt);
461 ro->ro_rt = (struct rtentry *)0;
462 }
463 if (ro->ro_rt == 0) {
464 bzero(dst, sizeof(*dst));
465 dst->sin6_family = AF_INET6;
466 dst->sin6_len = sizeof(struct sockaddr_in6);
467 dst->sin6_addr = ip6->ip6_dst;
468#ifdef SCOPEDROUTING
469 /* XXX: sin6_scope_id should already be fixed at this point */
470 if (IN6_IS_SCOPE_LINKLOCAL(&dst->sin6_addr))
471 dst->sin6_scope_id = ntohs(dst->sin6_addr.s6_addr16[1]);
472#endif
473 }
474#ifdef IPSEC
475 if (needipsec && needipsectun) {
476 struct ipsec_output_state state;
477
478 /*
479 * All the extension headers will become inaccessible
480 * (since they can be encrypted).

--- 34 unchanged lines hidden (view full) ---

515 error = 0;
516 break;
517 }
518 goto bad;
519 }
520
521 exthdrs.ip6e_ip6 = m;
522 }
473 }
474#ifdef IPSEC
475 if (needipsec && needipsectun) {
476 struct ipsec_output_state state;
477
478 /*
479 * All the extension headers will become inaccessible
480 * (since they can be encrypted).

--- 34 unchanged lines hidden (view full) ---

515 error = 0;
516 break;
517 }
518 goto bad;
519 }
520
521 exthdrs.ip6e_ip6 = m;
522 }
523#endif /*IPESC*/
523#endif /*IPSEC*/
524
525 if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
526 /* Unicast */
527
528#define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa))
529#define sin6tosa(sin6) ((struct sockaddr *)(sin6))
530 /* xxx
531 * interface selection comes here
532 * if an interface is specified from an upper layer,
533 * ifp must point it.
534 */
524
525 if (!IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) {
526 /* Unicast */
527
528#define ifatoia6(ifa) ((struct in6_ifaddr *)(ifa))
529#define sin6tosa(sin6) ((struct sockaddr *)(sin6))
530 /* xxx
531 * interface selection comes here
532 * if an interface is specified from an upper layer,
533 * ifp must point it.
534 */
535 if (ro->ro_rt == 0)
535 if (ro->ro_rt == 0) {
536 /*
537 * non-bsdi always clone routes, if parent is
538 * PRF_CLONING.
539 */
536 rtalloc((struct route *)ro);
540 rtalloc((struct route *)ro);
541 }
537 if (ro->ro_rt == 0) {
538 ip6stat.ip6s_noroute++;
539 error = EHOSTUNREACH;
540 /* XXX in6_ifstat_inc(ifp, ifs6_out_discard); */
541 goto bad;
542 }
543 ia = ifatoia6(ro->ro_rt->rt_ifa);
544 ifp = ro->ro_rt->rt_ifp;
545 ro->ro_rt->rt_use++;
546 if (ro->ro_rt->rt_flags & RTF_GATEWAY)
547 dst = (struct sockaddr_in6 *)ro->ro_rt->rt_gateway;
548 m->m_flags &= ~(M_BCAST | M_MCAST); /* just in case */
549
550 in6_ifstat_inc(ifp, ifs6_out_request);
551
552 /*
542 if (ro->ro_rt == 0) {
543 ip6stat.ip6s_noroute++;
544 error = EHOSTUNREACH;
545 /* XXX in6_ifstat_inc(ifp, ifs6_out_discard); */
546 goto bad;
547 }
548 ia = ifatoia6(ro->ro_rt->rt_ifa);
549 ifp = ro->ro_rt->rt_ifp;
550 ro->ro_rt->rt_use++;
551 if (ro->ro_rt->rt_flags & RTF_GATEWAY)
552 dst = (struct sockaddr_in6 *)ro->ro_rt->rt_gateway;
553 m->m_flags &= ~(M_BCAST | M_MCAST); /* just in case */
554
555 in6_ifstat_inc(ifp, ifs6_out_request);
556
557 /*
553 * Check if there is the outgoing interface conflicts with
554 * the interface specified by ifi6_ifindex(if specified).
558 * Check if the outgoing interface conflicts with
559 * the interface specified by ifi6_ifindex (if specified).
555 * Note that loopback interface is always okay.
560 * Note that loopback interface is always okay.
556 * (this happens when we are sending packet toward my
557 * interface)
561 * (this may happen when we are sending a packet to one of
562 * our own addresses.)
558 */
559 if (opt && opt->ip6po_pktinfo
560 && opt->ip6po_pktinfo->ipi6_ifindex) {
561 if (!(ifp->if_flags & IFF_LOOPBACK)
562 && ifp->if_index != opt->ip6po_pktinfo->ipi6_ifindex) {
563 ip6stat.ip6s_noroute++;
564 in6_ifstat_inc(ifp, ifs6_out_discard);
565 error = EHOSTUNREACH;

--- 105 unchanged lines hidden (view full) ---

671 * recursively calls this function, using the
672 * IPV6_FORWARDING flag to prevent infinite recursion.
673 *
674 * Multicasts that are looped back by ip6_mloopback(),
675 * above, will be forwarded by the ip6_input() routine,
676 * if necessary.
677 */
678 if (ip6_mrouter && (flags & IPV6_FORWARDING) == 0) {
563 */
564 if (opt && opt->ip6po_pktinfo
565 && opt->ip6po_pktinfo->ipi6_ifindex) {
566 if (!(ifp->if_flags & IFF_LOOPBACK)
567 && ifp->if_index != opt->ip6po_pktinfo->ipi6_ifindex) {
568 ip6stat.ip6s_noroute++;
569 in6_ifstat_inc(ifp, ifs6_out_discard);
570 error = EHOSTUNREACH;

--- 105 unchanged lines hidden (view full) ---

676 * recursively calls this function, using the
677 * IPV6_FORWARDING flag to prevent infinite recursion.
678 *
679 * Multicasts that are looped back by ip6_mloopback(),
680 * above, will be forwarded by the ip6_input() routine,
681 * if necessary.
682 */
683 if (ip6_mrouter && (flags & IPV6_FORWARDING) == 0) {
679 if (ip6_mforward(ip6, ifp, m) != NULL) {
684 if (ip6_mforward(ip6, ifp, m) != 0) {
680 m_freem(m);
681 goto done;
682 }
683 }
684 }
685 /*
686 * Multicasts with a hoplimit of zero may be looped back,
687 * above, but must not be transmitted on a network.

--- 53 unchanged lines hidden (view full) ---

741 mtu = ifmtu;
742 if ((ro_pmtu->ro_rt->rt_rmx.rmx_locks & RTV_MTU) == 0)
743 ro_pmtu->ro_rt->rt_rmx.rmx_mtu = mtu; /* XXX */
744 }
745 } else {
746 mtu = nd_ifinfo[ifp->if_index].linkmtu;
747 }
748
685 m_freem(m);
686 goto done;
687 }
688 }
689 }
690 /*
691 * Multicasts with a hoplimit of zero may be looped back,
692 * above, but must not be transmitted on a network.

--- 53 unchanged lines hidden (view full) ---

746 mtu = ifmtu;
747 if ((ro_pmtu->ro_rt->rt_rmx.rmx_locks & RTV_MTU) == 0)
748 ro_pmtu->ro_rt->rt_rmx.rmx_mtu = mtu; /* XXX */
749 }
750 } else {
751 mtu = nd_ifinfo[ifp->if_index].linkmtu;
752 }
753
749 /*
750 * Fake link-local scope-class addresses
751 */
752 if ((ifp->if_flags & IFF_LOOPBACK) == 0) {
754 /* Fake scoped addresses */
755 if ((ifp->if_flags & IFF_LOOPBACK) != 0) {
756 /*
757 * If source or destination address is a scoped address, and
758 * the packet is going to be sent to a loopback interface,
759 * we should keep the original interface.
760 */
761
762 /*
763 * XXX: this is a very experimental and temporary solution.
764 * We eventually have sockaddr_in6 and use the sin6_scope_id
765 * field of the structure here.
766 * We rely on the consistency between two scope zone ids
767 * of source add destination, which should already be assured
768 * Larger scopes than link will be supported in the near
769 * future.
770 */
753 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
771 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
772 origifp = ifindex2ifnet[ntohs(ip6->ip6_src.s6_addr16[1])];
773 else if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
774 origifp = ifindex2ifnet[ntohs(ip6->ip6_dst.s6_addr16[1])];
775 else
776 origifp = ifp;
777 }
778 else
779 origifp = ifp;
780#ifndef FAKE_LOOPBACK_IF
781 if ((ifp->if_flags & IFF_LOOPBACK) == 0)
782#else
783 if (1)
784#endif
785 {
786 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
754 ip6->ip6_src.s6_addr16[1] = 0;
755 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
756 ip6->ip6_dst.s6_addr16[1] = 0;
757 }
758
759#ifdef IPV6FIREWALL
760 /*
761 * Check with the firewall...
762 */
763 if (ip6_fw_chk_ptr) {
764 u_short port = 0;
787 ip6->ip6_src.s6_addr16[1] = 0;
788 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
789 ip6->ip6_dst.s6_addr16[1] = 0;
790 }
791
792#ifdef IPV6FIREWALL
793 /*
794 * Check with the firewall...
795 */
796 if (ip6_fw_chk_ptr) {
797 u_short port = 0;
798 m->m_pkthdr.rcvif = NULL; /*XXX*/
765 /* If ipfw says divert, we have to just drop packet */
766 if ((*ip6_fw_chk_ptr)(&ip6, ifp, &port, &m)) {
767 m_freem(m);
768 goto done;
769 }
770 if (!m) {
771 error = EACCES;
772 goto done;

--- 49 unchanged lines hidden (view full) ---

822 * larger than the link's MTU.
823 * XXX: IFF_FRAGMENTABLE (or such) flag has not been defined yet...
824 */
825
826 || ifp->if_flags & IFF_FRAGMENTABLE
827#endif
828 )
829 {
799 /* If ipfw says divert, we have to just drop packet */
800 if ((*ip6_fw_chk_ptr)(&ip6, ifp, &port, &m)) {
801 m_freem(m);
802 goto done;
803 }
804 if (!m) {
805 error = EACCES;
806 goto done;

--- 49 unchanged lines hidden (view full) ---

856 * larger than the link's MTU.
857 * XXX: IFF_FRAGMENTABLE (or such) flag has not been defined yet...
858 */
859
860 || ifp->if_flags & IFF_FRAGMENTABLE
861#endif
862 )
863 {
830#if defined(__NetBSD__) && defined(IFA_STATS)
831 if (IFA_STATS) {
832 struct in6_ifaddr *ia6;
833 ip6 = mtod(m, struct ip6_hdr *);
834 ia6 = in6_ifawithifp(ifp, &ip6->ip6_src);
835 if (ia6) {
836 ia->ia_ifa.ifa_data.ifad_outbytes +=
837 m->m_pkthdr.len;
838 }
839 }
840#endif
841 error = nd6_output(ifp, m, dst, ro->ro_rt);
864 error = nd6_output(ifp, origifp, m, dst, ro->ro_rt);
842 goto done;
843 } else if (mtu < IPV6_MMTU) {
844 /*
845 * note that path MTU is never less than IPV6_MMTU
846 * (see icmp6_input).
847 */
848 error = EMSGSIZE;
849 in6_ifstat_inc(ifp, ifs6_out_fragfail);

--- 99 unchanged lines hidden (view full) ---

949sendorfree:
950 m = m0->m_nextpkt;
951 m0->m_nextpkt = 0;
952 m_freem(m0);
953 for (m0 = m; m; m = m0) {
954 m0 = m->m_nextpkt;
955 m->m_nextpkt = 0;
956 if (error == 0) {
865 goto done;
866 } else if (mtu < IPV6_MMTU) {
867 /*
868 * note that path MTU is never less than IPV6_MMTU
869 * (see icmp6_input).
870 */
871 error = EMSGSIZE;
872 in6_ifstat_inc(ifp, ifs6_out_fragfail);

--- 99 unchanged lines hidden (view full) ---

972sendorfree:
973 m = m0->m_nextpkt;
974 m0->m_nextpkt = 0;
975 m_freem(m0);
976 for (m0 = m; m; m = m0) {
977 m0 = m->m_nextpkt;
978 m->m_nextpkt = 0;
979 if (error == 0) {
957#if defined(__NetBSD__) && defined(IFA_STATS)
958 if (IFA_STATS) {
959 struct in6_ifaddr *ia6;
960 ip6 = mtod(m, struct ip6_hdr *);
961 ia6 = in6_ifawithifp(ifp, &ip6->ip6_src);
962 if (ia6) {
963 ia->ia_ifa.ifa_data.ifad_outbytes +=
964 m->m_pkthdr.len;
965 }
966 }
967#endif
968 error = nd6_output(ifp, m, dst, ro->ro_rt);
980 error = nd6_output(ifp, origifp, m, dst, ro->ro_rt);
969 } else
970 m_freem(m);
971 }
972
973 if (error == 0)
974 ip6stat.ip6s_fragmented++;
975
976done:

--- 142 unchanged lines hidden (view full) ---

1119 } else
1120 n = m;
1121
1122 /* Search for the last mbuf of unfragmentable part. */
1123 for (mlast = n; mlast->m_next; mlast = mlast->m_next)
1124 ;
1125
1126 if ((mlast->m_flags & M_EXT) == 0 &&
981 } else
982 m_freem(m);
983 }
984
985 if (error == 0)
986 ip6stat.ip6s_fragmented++;
987
988done:

--- 142 unchanged lines hidden (view full) ---

1131 } else
1132 n = m;
1133
1134 /* Search for the last mbuf of unfragmentable part. */
1135 for (mlast = n; mlast->m_next; mlast = mlast->m_next)
1136 ;
1137
1138 if ((mlast->m_flags & M_EXT) == 0 &&
1127 M_TRAILINGSPACE(mlast) < sizeof(struct ip6_frag)) {
1139 M_TRAILINGSPACE(mlast) >= sizeof(struct ip6_frag)) {
1128 /* use the trailing space of the last mbuf for the fragment hdr */
1129 *frghdrp =
1130 (struct ip6_frag *)(mtod(mlast, caddr_t) + mlast->m_len);
1131 mlast->m_len += sizeof(struct ip6_frag);
1132 m->m_pkthdr.len += sizeof(struct ip6_frag);
1133 } else {
1134 /* allocate a new mbuf for the fragment header */
1135 struct mbuf *mfrg;

--- 57 unchanged lines hidden (view full) ---

1193 case IPV6_HOPOPTS:
1194 case IPV6_DSTOPTS:
1195 if (!privileged) {
1196 error = EPERM;
1197 break;
1198 }
1199 /* fall through */
1200 case IPV6_UNICAST_HOPS:
1140 /* use the trailing space of the last mbuf for the fragment hdr */
1141 *frghdrp =
1142 (struct ip6_frag *)(mtod(mlast, caddr_t) + mlast->m_len);
1143 mlast->m_len += sizeof(struct ip6_frag);
1144 m->m_pkthdr.len += sizeof(struct ip6_frag);
1145 } else {
1146 /* allocate a new mbuf for the fragment header */
1147 struct mbuf *mfrg;

--- 57 unchanged lines hidden (view full) ---

1205 case IPV6_HOPOPTS:
1206 case IPV6_DSTOPTS:
1207 if (!privileged) {
1208 error = EPERM;
1209 break;
1210 }
1211 /* fall through */
1212 case IPV6_UNICAST_HOPS:
1201 case IPV6_RECVOPTS:
1202 case IPV6_RECVRETOPTS:
1203 case IPV6_RECVDSTADDR:
1204 case IPV6_PKTINFO:
1205 case IPV6_HOPLIMIT:
1206 case IPV6_RTHDR:
1207 case IPV6_CHECKSUM:
1208 case IPV6_FAITH:
1209 case IPV6_BINDV6ONLY:
1210 if (optlen != sizeof(int))
1211 error = EINVAL;

--- 16 unchanged lines hidden (view full) ---

1228 }
1229 break;
1230#define OPTSET(bit) \
1231 if (optval) \
1232 in6p->in6p_flags |= bit; \
1233 else \
1234 in6p->in6p_flags &= ~bit;
1235
1213 case IPV6_PKTINFO:
1214 case IPV6_HOPLIMIT:
1215 case IPV6_RTHDR:
1216 case IPV6_CHECKSUM:
1217 case IPV6_FAITH:
1218 case IPV6_BINDV6ONLY:
1219 if (optlen != sizeof(int))
1220 error = EINVAL;

--- 16 unchanged lines hidden (view full) ---

1237 }
1238 break;
1239#define OPTSET(bit) \
1240 if (optval) \
1241 in6p->in6p_flags |= bit; \
1242 else \
1243 in6p->in6p_flags &= ~bit;
1244
1236 case IPV6_RECVOPTS:
1237 OPTSET(IN6P_RECVOPTS);
1238 break;
1239
1240 case IPV6_RECVRETOPTS:
1241 OPTSET(IN6P_RECVRETOPTS);
1242 break;
1243
1244 case IPV6_RECVDSTADDR:
1245 OPTSET(IN6P_RECVDSTADDR);
1246 break;
1247
1248 case IPV6_PKTINFO:
1249 OPTSET(IN6P_PKTINFO);
1250 break;
1251
1252 case IPV6_HOPLIMIT:
1253 OPTSET(IN6P_HOPLIMIT);
1254 break;
1255

--- 47 unchanged lines hidden (view full) ---

1303 m->m_len, m->m_len);
1304 error = ip6_setmoptions(sopt->sopt_name,
1305 &in6p->in6p_moptions,
1306 m);
1307 (void)m_free(m);
1308 }
1309 break;
1310
1245 case IPV6_PKTINFO:
1246 OPTSET(IN6P_PKTINFO);
1247 break;
1248
1249 case IPV6_HOPLIMIT:
1250 OPTSET(IN6P_HOPLIMIT);
1251 break;
1252

--- 47 unchanged lines hidden (view full) ---

1300 m->m_len, m->m_len);
1301 error = ip6_setmoptions(sopt->sopt_name,
1302 &in6p->in6p_moptions,
1303 m);
1304 (void)m_free(m);
1305 }
1306 break;
1307
1311 case IPV6_PORTRANGE:
1312 error = sooptcopyin(sopt, &optval, sizeof optval,
1313 sizeof optval);
1314 if (error)
1315 break;
1308 case IPV6_PORTRANGE:
1309 error = sooptcopyin(sopt, &optval,
1310 sizeof optval, sizeof optval);
1311 if (error)
1312 break;
1316
1313
1317 switch (optval) {
1318 case IPV6_PORTRANGE_DEFAULT:
1319 in6p->in6p_flags &= ~(IN6P_LOWPORT);
1320 in6p->in6p_flags &= ~(IN6P_HIGHPORT);
1321 break;
1314 switch (optval) {
1315 case IPV6_PORTRANGE_DEFAULT:
1316 in6p->in6p_flags &= ~(IN6P_LOWPORT);
1317 in6p->in6p_flags &= ~(IN6P_HIGHPORT);
1318 break;
1322
1319
1323 case IPV6_PORTRANGE_HIGH:
1324 in6p->in6p_flags &= ~(IN6P_LOWPORT);
1325 in6p->in6p_flags |= IN6P_HIGHPORT;
1326 break;
1320 case IPV6_PORTRANGE_HIGH:
1321 in6p->in6p_flags &= ~(IN6P_LOWPORT);
1322 in6p->in6p_flags |= IN6P_HIGHPORT;
1323 break;
1327
1324
1328 case IPV6_PORTRANGE_LOW:
1329 in6p->in6p_flags &= ~(IN6P_HIGHPORT);
1330 in6p->in6p_flags |= IN6P_LOWPORT;
1331 break;
1325 case IPV6_PORTRANGE_LOW:
1326 in6p->in6p_flags &= ~(IN6P_HIGHPORT);
1327 in6p->in6p_flags |= IN6P_LOWPORT;
1328 break;
1332
1329
1333 default:
1334 error = EINVAL;
1330 default:
1331 error = EINVAL;
1332 break;
1333 }
1335 break;
1334 break;
1336 }
1337 break;
1338
1339#ifdef IPSEC
1340 case IPV6_IPSEC_POLICY:
1341 {
1342 caddr_t req = NULL;
1335
1336#ifdef IPSEC
1337 case IPV6_IPSEC_POLICY:
1338 {
1339 caddr_t req = NULL;
1340 size_t len = 0;
1343 struct mbuf *m;
1344
1341 struct mbuf *m;
1342
1345 if ((error = soopt_getm(sopt, &m))
1346 != 0) /* XXX */
1343 if ((error = soopt_getm(sopt, &m)) != 0) /* XXX */
1347 break;
1344 break;
1348 if ((error = soopt_mcopyin(sopt, m))
1349 != 0) /* XXX */
1345 if ((error = soopt_mcopyin(sopt, m)) != 0) /* XXX */
1350 break;
1346 break;
1351 if (m != 0)
1347 if (m) {
1352 req = mtod(m, caddr_t);
1348 req = mtod(m, caddr_t);
1349 len = m->m_len;
1350 }
1353 error = ipsec6_set_policy(in6p, optname, req,
1351 error = ipsec6_set_policy(in6p, optname, req,
1354 privileged);
1352 len, privileged);
1355 m_freem(m);
1356 }
1357 break;
1358#endif /* IPSEC */
1359
1360#ifdef IPV6FIREWALL
1361 case IPV6_FW_ADD:
1362 case IPV6_FW_DEL:

--- 21 unchanged lines hidden (view full) ---

1384 error = ENOPROTOOPT;
1385 break;
1386 }
1387 break;
1388
1389 case SOPT_GET:
1390 switch (optname) {
1391
1353 m_freem(m);
1354 }
1355 break;
1356#endif /* IPSEC */
1357
1358#ifdef IPV6FIREWALL
1359 case IPV6_FW_ADD:
1360 case IPV6_FW_DEL:

--- 21 unchanged lines hidden (view full) ---

1382 error = ENOPROTOOPT;
1383 break;
1384 }
1385 break;
1386
1387 case SOPT_GET:
1388 switch (optname) {
1389
1392 case IPV6_OPTIONS:
1393 case IPV6_RETOPTS:
1394 error = ENOPROTOOPT;
1395 break;
1396
1397 case IPV6_PKTOPTIONS:
1398 if (in6p->in6p_options) {
1399 error = soopt_mcopyout(sopt,
1400 in6p->in6p_options);
1401 } else
1402 sopt->sopt_valsize = 0;
1403 break;
1404
1405 case IPV6_HOPOPTS:
1406 case IPV6_DSTOPTS:
1407 if (!privileged) {
1408 error = EPERM;
1409 break;
1410 }
1411 /* fall through */
1412 case IPV6_UNICAST_HOPS:
1390 case IPV6_PKTOPTIONS:
1391 if (in6p->in6p_options) {
1392 error = soopt_mcopyout(sopt,
1393 in6p->in6p_options);
1394 } else
1395 sopt->sopt_valsize = 0;
1396 break;
1397
1398 case IPV6_HOPOPTS:
1399 case IPV6_DSTOPTS:
1400 if (!privileged) {
1401 error = EPERM;
1402 break;
1403 }
1404 /* fall through */
1405 case IPV6_UNICAST_HOPS:
1413 case IPV6_RECVOPTS:
1414 case IPV6_RECVRETOPTS:
1415 case IPV6_RECVDSTADDR:
1416 case IPV6_PKTINFO:
1417 case IPV6_HOPLIMIT:
1418 case IPV6_RTHDR:
1419 case IPV6_CHECKSUM:
1420 case IPV6_FAITH:
1421 case IPV6_BINDV6ONLY:
1422 case IPV6_PORTRANGE:
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
1406 case IPV6_PKTINFO:
1407 case IPV6_HOPLIMIT:
1408 case IPV6_RTHDR:
1409 case IPV6_CHECKSUM:
1410 case IPV6_FAITH:
1411 case IPV6_BINDV6ONLY:
1412 case IPV6_PORTRANGE:
1413 switch (optname) {
1414
1415 case IPV6_UNICAST_HOPS:
1416 optval = in6p->in6p_hops;
1417 break;
1418
1419#define OPTBIT(bit) (in6p->in6p_flags & bit ? 1 : 0)
1420
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;
1442
1443 case IPV6_PKTINFO:
1444 optval = OPTBIT(IN6P_PKTINFO);
1445 break;
1446
1447 case IPV6_HOPLIMIT:
1448 optval = OPTBIT(IN6P_HOPLIMIT);
1449 break;
1450

--- 53 unchanged lines hidden (view full) ---

1504 mtod(m, char *), m->m_len);
1505 m_freem(m);
1506 }
1507 break;
1508
1509#ifdef IPSEC
1510 case IPV6_IPSEC_POLICY:
1511 {
1421 case IPV6_PKTINFO:
1422 optval = OPTBIT(IN6P_PKTINFO);
1423 break;
1424
1425 case IPV6_HOPLIMIT:
1426 optval = OPTBIT(IN6P_HOPLIMIT);
1427 break;
1428

--- 53 unchanged lines hidden (view full) ---

1482 mtod(m, char *), m->m_len);
1483 m_freem(m);
1484 }
1485 break;
1486
1487#ifdef IPSEC
1488 case IPV6_IPSEC_POLICY:
1489 {
1512
1513 struct mbuf *m = NULL;
1514 caddr_t req = NULL;
1490 caddr_t req = NULL;
1491 size_t len = 0;
1492 struct mbuf *m = NULL;
1493 struct mbuf **mp = &m;
1515
1494
1516 if (m != 0)
1495 error = soopt_getm(sopt, &m); /* XXX */
1496 if (error != NULL)
1497 break;
1498 error = soopt_mcopyin(sopt, m); /* XXX */
1499 if (error != NULL)
1500 break;
1501 if (m) {
1517 req = mtod(m, caddr_t);
1502 req = mtod(m, caddr_t);
1518 error = ipsec6_get_policy(in6p, req, &m);
1503 len = m->m_len;
1504 }
1505 error = ipsec6_get_policy(in6p, req, len, mp);
1519 if (error == 0)
1520 error = soopt_mcopyout(sopt, m); /*XXX*/
1506 if (error == 0)
1507 error = soopt_mcopyout(sopt, m); /*XXX*/
1521 if (error == 0)
1522 m_freem(m);
1508 m_freem(m);
1523 break;
1524 }
1525#endif /* IPSEC */
1526
1527#ifdef IPV6FIREWALL
1528 case IPV6_FW_GET:
1529 {
1530 struct mbuf *m;

--- 174 unchanged lines hidden (view full) ---

1705 }
1706 mreq = mtod(m, struct ipv6_mreq *);
1707 if (IN6_IS_ADDR_UNSPECIFIED(&mreq->ipv6mr_multiaddr)) {
1708 /*
1709 * We use the unspecified address to specify to accept
1710 * all multicast addresses. Only super user is allowed
1711 * to do this.
1712 */
1509 break;
1510 }
1511#endif /* IPSEC */
1512
1513#ifdef IPV6FIREWALL
1514 case IPV6_FW_GET:
1515 {
1516 struct mbuf *m;

--- 174 unchanged lines hidden (view full) ---

1691 }
1692 mreq = mtod(m, struct ipv6_mreq *);
1693 if (IN6_IS_ADDR_UNSPECIFIED(&mreq->ipv6mr_multiaddr)) {
1694 /*
1695 * We use the unspecified address to specify to accept
1696 * all multicast addresses. Only super user is allowed
1697 * to do this.
1698 */
1713 if (suser(p)) {
1699 if (suser(p))
1700 {
1714 error = EACCES;
1715 break;
1716 }
1717 } else if (!IN6_IS_ADDR_MULTICAST(&mreq->ipv6mr_multiaddr)) {
1718 error = EINVAL;
1719 break;
1720 }
1721

--- 51 unchanged lines hidden (view full) ---

1773 */
1774 if (IN6_IS_ADDR_MC_LINKLOCAL(&mreq->ipv6mr_multiaddr)) {
1775 mreq->ipv6mr_multiaddr.s6_addr16[1]
1776 = htons(mreq->ipv6mr_interface);
1777 }
1778 /*
1779 * See if the membership already exists.
1780 */
1701 error = EACCES;
1702 break;
1703 }
1704 } else if (!IN6_IS_ADDR_MULTICAST(&mreq->ipv6mr_multiaddr)) {
1705 error = EINVAL;
1706 break;
1707 }
1708

--- 51 unchanged lines hidden (view full) ---

1760 */
1761 if (IN6_IS_ADDR_MC_LINKLOCAL(&mreq->ipv6mr_multiaddr)) {
1762 mreq->ipv6mr_multiaddr.s6_addr16[1]
1763 = htons(mreq->ipv6mr_interface);
1764 }
1765 /*
1766 * See if the membership already exists.
1767 */
1781 LIST_FOREACH(imm, &im6o->im6o_memberships, i6mm_chain)
1768 for (imm = im6o->im6o_memberships.lh_first;
1769 imm != NULL; imm = imm->i6mm_chain.le_next)
1782 if (imm->i6mm_maddr->in6m_ifp == ifp &&
1783 IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr,
1784 &mreq->ipv6mr_multiaddr))
1785 break;
1786 if (imm != NULL) {
1787 error = EADDRINUSE;
1788 break;
1789 }

--- 49 unchanged lines hidden (view full) ---

1839 */
1840 if (IN6_IS_ADDR_MC_LINKLOCAL(&mreq->ipv6mr_multiaddr)) {
1841 mreq->ipv6mr_multiaddr.s6_addr16[1]
1842 = htons(mreq->ipv6mr_interface);
1843 }
1844 /*
1845 * Find the membership in the membership list.
1846 */
1770 if (imm->i6mm_maddr->in6m_ifp == ifp &&
1771 IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr,
1772 &mreq->ipv6mr_multiaddr))
1773 break;
1774 if (imm != NULL) {
1775 error = EADDRINUSE;
1776 break;
1777 }

--- 49 unchanged lines hidden (view full) ---

1827 */
1828 if (IN6_IS_ADDR_MC_LINKLOCAL(&mreq->ipv6mr_multiaddr)) {
1829 mreq->ipv6mr_multiaddr.s6_addr16[1]
1830 = htons(mreq->ipv6mr_interface);
1831 }
1832 /*
1833 * Find the membership in the membership list.
1834 */
1847 LIST_FOREACH(imm, &im6o->im6o_memberships, i6mm_chain) {
1835 for (imm = im6o->im6o_memberships.lh_first;
1836 imm != NULL; imm = imm->i6mm_chain.le_next) {
1848 if ((ifp == NULL ||
1849 imm->i6mm_maddr->in6m_ifp == ifp) &&
1850 IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr,
1851 &mreq->ipv6mr_multiaddr))
1852 break;
1853 }
1854 if (imm == NULL) {
1855 /* Unable to resolve interface */

--- 15 unchanged lines hidden (view full) ---

1871 }
1872
1873 /*
1874 * If all options have default values, no need to keep the mbuf.
1875 */
1876 if (im6o->im6o_multicast_ifp == NULL &&
1877 im6o->im6o_multicast_hlim == ip6_defmcasthlim &&
1878 im6o->im6o_multicast_loop == IPV6_DEFAULT_MULTICAST_LOOP &&
1837 if ((ifp == NULL ||
1838 imm->i6mm_maddr->in6m_ifp == ifp) &&
1839 IN6_ARE_ADDR_EQUAL(&imm->i6mm_maddr->in6m_addr,
1840 &mreq->ipv6mr_multiaddr))
1841 break;
1842 }
1843 if (imm == NULL) {
1844 /* Unable to resolve interface */

--- 15 unchanged lines hidden (view full) ---

1860 }
1861
1862 /*
1863 * If all options have default values, no need to keep the mbuf.
1864 */
1865 if (im6o->im6o_multicast_ifp == NULL &&
1866 im6o->im6o_multicast_hlim == ip6_defmcasthlim &&
1867 im6o->im6o_multicast_loop == IPV6_DEFAULT_MULTICAST_LOOP &&
1879 LIST_EMPTY(&im6o->im6o_memberships)) {
1868 im6o->im6o_memberships.lh_first == NULL) {
1880 free(*im6op, M_IPMOPTS);
1881 *im6op = NULL;
1882 }
1883
1884 return(error);
1885}
1886
1887/*

--- 50 unchanged lines hidden (view full) ---

1938ip6_freemoptions(im6o)
1939 register struct ip6_moptions *im6o;
1940{
1941 struct in6_multi_mship *imm;
1942
1943 if (im6o == NULL)
1944 return;
1945
1869 free(*im6op, M_IPMOPTS);
1870 *im6op = NULL;
1871 }
1872
1873 return(error);
1874}
1875
1876/*

--- 50 unchanged lines hidden (view full) ---

1927ip6_freemoptions(im6o)
1928 register struct ip6_moptions *im6o;
1929{
1930 struct in6_multi_mship *imm;
1931
1932 if (im6o == NULL)
1933 return;
1934
1946 while ((imm = LIST_FIRST(&im6o->im6o_memberships)) != NULL) {
1935 while ((imm = im6o->im6o_memberships.lh_first) != NULL) {
1947 LIST_REMOVE(imm, i6mm_chain);
1948 if (imm->i6mm_maddr)
1949 in6_delmulti(imm->i6mm_maddr);
1950 free(imm, M_IPMADDR);
1951 }
1952 free(im6o, M_IPMOPTS);
1953}
1954

--- 16 unchanged lines hidden (view full) ---

1971
1972 /*
1973 * XXX: Currently, we assume all the optional information is stored
1974 * in a single mbuf.
1975 */
1976 if (control->m_next)
1977 return(EINVAL);
1978
1936 LIST_REMOVE(imm, i6mm_chain);
1937 if (imm->i6mm_maddr)
1938 in6_delmulti(imm->i6mm_maddr);
1939 free(imm, M_IPMADDR);
1940 }
1941 free(im6o, M_IPMOPTS);
1942}
1943

--- 16 unchanged lines hidden (view full) ---

1960
1961 /*
1962 * XXX: Currently, we assume all the optional information is stored
1963 * in a single mbuf.
1964 */
1965 if (control->m_next)
1966 return(EINVAL);
1967
1979 opt->ip6po_m = control;
1980
1981 for (; control->m_len; control->m_data += ALIGN(cm->cmsg_len),
1982 control->m_len -= ALIGN(cm->cmsg_len)) {
1983 cm = mtod(control, struct cmsghdr *);
1984 if (cm->cmsg_len == 0 || cm->cmsg_len > control->m_len)
1985 return(EINVAL);
1986 if (cm->cmsg_level != IPPROTO_IPV6)
1987 continue;
1988

--- 126 unchanged lines hidden (view full) ---

2115 * pointer that might NOT be &loif -- easier than replicating that code here.
2116 */
2117void
2118ip6_mloopback(ifp, m, dst)
2119 struct ifnet *ifp;
2120 register struct mbuf *m;
2121 register struct sockaddr_in6 *dst;
2122{
1968 for (; control->m_len; control->m_data += ALIGN(cm->cmsg_len),
1969 control->m_len -= ALIGN(cm->cmsg_len)) {
1970 cm = mtod(control, struct cmsghdr *);
1971 if (cm->cmsg_len == 0 || cm->cmsg_len > control->m_len)
1972 return(EINVAL);
1973 if (cm->cmsg_level != IPPROTO_IPV6)
1974 continue;
1975

--- 126 unchanged lines hidden (view full) ---

2102 * pointer that might NOT be &loif -- easier than replicating that code here.
2103 */
2104void
2105ip6_mloopback(ifp, m, dst)
2106 struct ifnet *ifp;
2107 register struct mbuf *m;
2108 register struct sockaddr_in6 *dst;
2109{
2123 struct mbuf *copym;
2110 struct mbuf *copym;
2111 struct ip6_hdr *ip6;
2124
2125 copym = m_copy(m, 0, M_COPYALL);
2112
2113 copym = m_copy(m, 0, M_COPYALL);
2126 if (copym != NULL) {
2127 (void)if_simloop(ifp, copym, dst->sin6_family, 0);
2114 if (copym == NULL)
2115 return;
2116
2117 /*
2118 * Make sure to deep-copy IPv6 header portion in case the data
2119 * is in an mbuf cluster, so that we can safely override the IPv6
2120 * header portion later.
2121 */
2122 if ((copym->m_flags & M_EXT) != 0 ||
2123 copym->m_len < sizeof(struct ip6_hdr)) {
2124 copym = m_pullup(copym, sizeof(struct ip6_hdr));
2125 if (copym == NULL)
2126 return;
2128 }
2127 }
2128
2129#ifdef DIAGNOSTIC
2130 if (copym->m_len < sizeof(*ip6)) {
2131 m_freem(copym);
2132 return;
2133 }
2134#endif
2135
2136#ifndef FAKE_LOOPBACK_IF
2137 if ((ifp->if_flags & IFF_LOOPBACK) == 0)
2138#else
2139 if (1)
2140#endif
2141 {
2142 ip6 = mtod(copym, struct ip6_hdr *);
2143 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_src))
2144 ip6->ip6_src.s6_addr16[1] = 0;
2145 if (IN6_IS_SCOPE_LINKLOCAL(&ip6->ip6_dst))
2146 ip6->ip6_dst.s6_addr16[1] = 0;
2147 }
2148
2149 (void)if_simloop(ifp, copym, dst->sin6_family, NULL);
2129}
2130
2131/*
2132 * Chop IPv6 header off from the payload.
2133 */
2134static int
2135ip6_splithdr(m, exthdrs)
2136 struct mbuf *m;

--- 50 unchanged lines hidden ---
2150}
2151
2152/*
2153 * Chop IPv6 header off from the payload.
2154 */
2155static int
2156ip6_splithdr(m, exthdrs)
2157 struct mbuf *m;

--- 50 unchanged lines hidden ---