summaryrefslogtreecommitdiff
path: root/sys/netinet6/raw_ipv6.c
diff options
context:
space:
mode:
authorJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>1999-12-08 06:50:25 +0000
committerJun-ichiro itojun Hagino <itojun@cvs.openbsd.org>1999-12-08 06:50:25 +0000
commitd9c080e0265d3557ac6fe2d2723cf4823eaa909f (patch)
tree422a747ed77f091d33ae234312450cc5cb2aa789 /sys/netinet6/raw_ipv6.c
parentbfa115c3a1f89cedeb913741469312347a52f8ee (diff)
bring in KAME IPv6 code, dated 19991208.
replaces NRL IPv6 layer. reuses NRL pcb layer. no IPsec-on-v6 support. see sys/netinet6/{TODO,IMPLEMENTATION} for more details. GENERIC configuration should work fine as before. GENERIC.v6 works fine as well, but you'll need KAME userland tools to play with IPv6 (will be bringed into soon).
Diffstat (limited to 'sys/netinet6/raw_ipv6.c')
-rw-r--r--sys/netinet6/raw_ipv6.c445
1 files changed, 266 insertions, 179 deletions
diff --git a/sys/netinet6/raw_ipv6.c b/sys/netinet6/raw_ipv6.c
index 72f995404a4..a32e501f699 100644
--- a/sys/netinet6/raw_ipv6.c
+++ b/sys/netinet6/raw_ipv6.c
@@ -42,7 +42,7 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
* SUCH DAMAGE.
*
* @(#)raw_ip.c 8.7 (Berkeley) 5/15/95
- * $Id: raw_ipv6.c,v 1.4 1999/04/28 09:28:16 art Exp $
+ * $Id: raw_ipv6.c,v 1.5 1999/12/08 06:50:23 itojun Exp $
*/
#include <sys/param.h>
@@ -72,11 +72,10 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
#include <netinet/ip.h>
#include <netinet/in_pcb.h>
-#include <netinet6/in6.h>
#include <netinet6/in6_var.h>
-#include <netinet6/ipv6.h>
-#include <netinet6/ipv6_var.h>
-#include <netinet6/icmpv6.h>
+#include <netinet6/ip6.h>
+#include <netinet6/ip6_var.h>
+#include <netinet6/icmp6.h>
#if __OpenBSD__
#undef IPSEC
@@ -110,7 +109,7 @@ struct inpcbtable rawin6pcbtable;
#else /* __NetBSD__ || __OpenBSD__ */
struct inpcb rawin6pcb;
#endif /* __NetBSD__ || __OpenBSD__ */
-struct sockaddr_in6 ripv6src = { sizeof(struct sockaddr_in6), AF_INET6 };
+struct sockaddr_in6 rip6src = { sizeof(struct sockaddr_in6), AF_INET6 };
/*
* Nominal space allocated to a raw ip socket.
@@ -118,8 +117,13 @@ struct sockaddr_in6 ripv6src = { sizeof(struct sockaddr_in6), AF_INET6 };
#define RIPV6SNDQ 8192
#define RIPV6RCVQ 8192
-u_long ripv6_sendspace = RIPV6SNDQ;
-u_long ripv6_recvspace = RIPV6RCVQ;
+#if 0
+u_long rip6_sendspace = RIPV6SNDQ;
+u_long rip6_recvspace = RIPV6RCVQ;
+#else
+extern u_long rip6_sendspace;
+extern u_long rip6_recvspace;
+#endif
/*
* External globals
@@ -129,7 +133,9 @@ static struct inpcbhead ri6pcb;
static struct inpcbinfo ri6pcbinfo;
#endif /* __FreeBSD__ */
-extern struct ipv6stat ipv6stat;
+#if 0
+extern struct ip6_hdrstat ipv6stat;
+#endif
#define RETURN_ERROR(x) { \
DPRINTF(EVENT, ("%s: returning %s\n", DEBUG_STATUS, #x)); \
@@ -145,7 +151,7 @@ extern struct ipv6stat ipv6stat;
----------------------------------------------------------------------*/
void
-ripv6_init()
+rip6_init()
{
#if __FreeBSD__
LIST_INIT(&ri6pcb);
@@ -194,50 +200,50 @@ static int ipv6_findnexthdr(struct mbuf *m, size_t extra)
do {
switch(nexthdr) {
case IPPROTO_IPV6:
- hl = sizeof(struct ipv6);
+ hl = sizeof(struct ip6_hdr);
if ((extra -= hl) < 0)
return -1;
- nexthdr = ((struct ipv6 *)p)->ipv6_nexthdr;
+ nexthdr = ((struct ip6_hdr *)p)->ip6_nxt;
break;
case IPPROTO_HOPOPTS:
case IPPROTO_DSTOPTS:
- if (extra < sizeof(struct ipv6_opthdr))
+ if (extra < sizeof(struct ip6_ext))
return -1;
- hl = sizeof(struct ipv6_opthdr) +
- (((struct ipv6_opthdr *)p)->oh_extlen << 3);
+ hl = sizeof(struct ip6_ext) +
+ (((struct ip6_ext *)p)->ip6e_len << 3);
if ((extra -= hl) < 0)
return -1;
- nexthdr = ((struct ipv6_opthdr *)p)->oh_nexthdr;
+ nexthdr = ((struct ip6_ext *)p)->ip6e_nxt;
break;
case IPPROTO_ROUTING:
- if (extra < sizeof(struct ipv6_srcroute0))
+ if (extra < sizeof(struct ip6_rthdr0))
return -1;
- hl = sizeof(struct ipv6_srcroute0) +
- (((struct ipv6_srcroute0 *)p)->i6sr_len << 3);
+ hl = sizeof(struct ip6_rthdr0) +
+ (((struct ip6_rthdr0 *)p)->ip6r0_len << 3);
if ((extra -= hl) < 0)
return -1;
- nexthdr = ((struct ipv6_srcroute0 *)p)->i6sr_nexthdr;
+ nexthdr = ((struct ip6_rthdr0 *)p)->ip6r0_nxt;
break;
#ifdef IPSEC
case IPPROTO_AH:
- if (extra < sizeof(struct ipv6_srcroute0))
+ if (extra < sizeof(struct ip6_hdr_srcroute0))
return -1;
- hl = sizeof(struct ipv6_srcroute0) +
- ((struct ipv6_srcroute0 *)p)->i6sr_len << 3;
+ hl = sizeof(struct ip6_hdr_srcroute0) +
+ ((struct ip6_hdr_srcroute0 *)p)->i6sr_len << 3;
if ((extra -= hl) < 0)
return -1;
- nexthdr = ((struct ipv6_srcroute0 *)p)->i6sr_nexthdr;
+ nexthdr = ((struct ip6_hdr_srcroute0 *)p)->i6sr_nexthdr;
break;
#endif /* IPSEC */
default:
@@ -252,52 +258,54 @@ static int ipv6_findnexthdr(struct mbuf *m, size_t extra)
/*----------------------------------------------------------------------
* If no HLP's are found for an IPv6 datagram, this routine is called.
----------------------------------------------------------------------*/
-void
-#if __OpenBSD__
-ripv6_input(struct mbuf *m, ...)
-#else /* __OpenBSD__ */
-ripv6_input(m,extra)
- struct mbuf *m;
- int extra;
-#endif /* __OpenBSD__ */
+int
+rip6_input(mp, offp, proto)
+ struct mbuf **mp;
+ int *offp, proto;
{
- register struct ipv6 *ipv6 = mtod(m, struct ipv6 *); /* Will have been
+ struct mbuf *m = *mp;
+ register struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); /* Will have been
pulled up by
ipv6_input(). */
register struct inpcb *inp;
- int nexthdr, icmpv6type;
+ int nexthdr, icmp6type;
int foundone = 0;
struct mbuf *m2 = NULL, *opts = NULL;
struct sockaddr_in6 srcsa;
#ifdef IPSEC
struct sockaddr_in6 dstsa;
#endif /* IPSEC */
-#if __OpenBSD__
- int extra;
- va_list ap;
+ int extra = *offp;
- va_start(ap, m);
- extra = va_arg(ap, int);
- va_end(ap);
-#endif /* __OpenBSD__ */
-
- DPRINTF(FINISHED, ("ripv6_input(m=%08x, extra=%d)\n", OSDEP_PCAST(m), extra));
+ DPRINTF(FINISHED, ("rip6_input(m=%08x, extra=%d)\n", OSDEP_PCAST(m), extra));
DP(FINISHED, m->m_pkthdr.len, d);
- DDO(FINISHED,printf("In ripv6_input(), header is:\n");dump_mchain(m));
- DPRINTF(EVENT, ("In ripv6_input()\n"));
+ DDO(FINISHED,printf("In rip6_input(), header is:\n");dump_mchain(m));
+ DPRINTF(EVENT, ("In rip6_input()\n"));
DPRINTF(EVENT, ("Header is: "));
+#if 0
DDO(GROSSEVENT, dump_ipv6(ipv6));
+#endif
bzero(&srcsa, sizeof(struct sockaddr_in6));
srcsa.sin6_family = AF_INET6;
srcsa.sin6_len = sizeof(struct sockaddr_in6);
- srcsa.sin6_addr = ipv6->ipv6_src;
+ srcsa.sin6_addr = ip6->ip6_src;
+
+ if (IN6_IS_SCOPE_LINKLOCAL(&srcsa.sin6_addr))
+ srcsa.sin6_addr.s6_addr16[1] = 0;
+ if (m->m_pkthdr.rcvif) {
+ if (IN6_IS_SCOPE_LINKLOCAL(&srcsa.sin6_addr))
+ srcsa.sin6_scope_id = m->m_pkthdr.rcvif->if_index;
+ else
+ srcsa.sin6_scope_id = 0;
+ } else
+ srcsa.sin6_scope_id = 0;
#if IPSEC
bzero(&dstsa, sizeof(struct sockaddr_in6));
dstsa.sin6_family = AF_INET6;
dstsa.sin6_len = sizeof(struct sockaddr_in6);
- dstsa.sin6_addr = ipv6->ipv6_dst;
+ dstsa.sin6_addr = ip6->ip6_dst;
#endif /* IPSEC */
#if 0
@@ -305,28 +313,28 @@ ripv6_input(m,extra)
if (m->m_len < extra)) {
if (!(m = m_pullup2(m, extra)))
return;
- ipv6 = mtod(m, struct ipv6 *);
+ ip6 = mtod(m, struct ip6_hdr *);
}
#endif /* 0 */
if ((nexthdr = ipv6_findnexthdr(m, extra)) < 0) {
- DPRINTF(ERROR, ("ripv6_input: ipv6_findnexthdr failed\n"));
+ DPRINTF(ERROR, ("rip6_input: ipv6_findnexthdr failed\n"));
goto ret;
}
DP(FINISHED, nexthdr, d);
if (nexthdr == IPPROTO_ICMPV6) {
- if (m->m_len < extra + sizeof(struct icmpv6hdr)) {
- if (!(m = m_pullup2(m, extra + sizeof(struct icmpv6hdr)))) {
- DPRINTF(ERROR, ("ripv6_input: m_pullup2 failed\n"));
+ if (m->m_len < extra + sizeof(struct icmp6_hdr)) {
+ if (!(m = m_pullup2(m, extra + sizeof(struct icmp6_hdr)))) {
+ DPRINTF(ERROR, ("rip6_input: m_pullup2 failed\n"));
goto ret;
}
- ipv6 = mtod(m, struct ipv6 *);
+ ip6 = mtod(m, struct ip6_hdr *);
}
- icmpv6type = ((struct icmpv6hdr *)(mtod(m, caddr_t) + extra))->icmpv6_type;
+ icmp6type = ((struct icmp6_hdr *)(mtod(m, caddr_t) + extra))->icmp6_type;
} else
- icmpv6type = -1;
+ icmp6type = -1;
/*
* Locate raw PCB for incoming datagram.
@@ -337,21 +345,22 @@ ripv6_input(m,extra)
#if __NetBSD__ || __OpenBSD__
for (inp = rawin6pcbtable.inpt_queue.cqh_first;
inp != (struct inpcb *)&rawin6pcbtable.inpt_queue;
- inp = inp->inp_queue.cqe_next) {
+ inp = inp->inp_queue.cqe_next)
#else /* __NetBSD__ || __OpenBSD__ */
- for (inp = rawin6pcb.inp_next; inp != &rawin6pcb; inp = inp->inp_next) {
+ for (inp = rawin6pcb.inp_next; inp != &rawin6pcb; inp = inp->inp_next)
#endif /* __NetBSD__ || __OpenBSD__ */
#endif /* __FreeBSD__ */
- if (inp->inp_ipv6.ipv6_nexthdr && inp->inp_ipv6.ipv6_nexthdr != nexthdr)
+ {
+ if (inp->inp_ipv6.ip6_nxt && inp->inp_ipv6.ip6_nxt != nexthdr)
continue;
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6) &&
- !IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, &ipv6->ipv6_dst))
+ !IN6_ARE_ADDR_EQUAL(&inp->inp_laddr6, &ip6->ip6_dst))
continue;
if (!IN6_IS_ADDR_UNSPECIFIED(&inp->inp_faddr6) &&
- !IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6, &ipv6->ipv6_src))
+ !IN6_ARE_ADDR_EQUAL(&inp->inp_faddr6, &ip6->ip6_src))
continue;
- if ((icmpv6type >= 0) &&
- ICMPV6_FILTER_WILLBLOCK(icmpv6type, &inp->inp_filter))
+ if (inp->inp_icmp6filt &&
+ ICMP6_FILTER_WILLBLOCK(icmp6type, inp->inp_icmp6filt))
continue;
DPRINTF(IDL_EVENT, ("Found a raw pcb (>1)\n"));
@@ -375,8 +384,8 @@ ripv6_input(m,extra)
if ((m2 = m_copym(m, 0, (int)M_COPYALL, M_DONTWAIT))) {
m_adj(m2, extra);
DP(FINISHED, m2->m_pkthdr.len, d);
- if (inp->inp_flags & INP_CONTROLOPTS)
- opts = ipv6_headertocontrol(m, extra, inp->inp_flags);
+ if (inp->inp_flags & IN6P_CONTROLOPTS)
+ ip6_savecontrol(inp, &opts, ip6, m);
else
opts = NULL;
if (sbappendaddr(&inp->inp_socket->so_rcv, (struct sockaddr *)&srcsa, m2,
@@ -393,46 +402,54 @@ ripv6_input(m,extra)
* We should send an ICMPv6 protocol unreachable here,
* though original UCB 4.4-lite BSD's IPv4 does not do so.
*/
+#if 0
ipv6stat.ips_noproto++;
ipv6stat.ips_delivered--;
+#endif
}
ret:
if (m)
m_freem(m);
- DPRINTF(FINISHED, ("ripv6_input\n"));
+ DPRINTF(FINISHED, ("rip6_input\n"));
+ return IPPROTO_DONE;
}
/*----------------------------------------------------------------------
- * Output function for raw IPv6. Called from ripv6_usrreq(), and
+ * Output function for raw IPv6. Called from rip6_usrreq(), and
* ipv6_icmp_usrreq().
----------------------------------------------------------------------*/
#if __OpenBSD__
-int ripv6_output(struct mbuf *m, ...)
+int rip6_output(struct mbuf *m, ...)
#else /* __OpenBSD__ */
int
-ripv6_output(m, so, dst, control)
+rip6_output(m, so, dst, control)
struct mbuf *m;
struct socket *so;
struct in6_addr *dst;
struct mbuf *control;
#endif /* __OpenBSD__ */
{
- register struct ipv6 *ipv6;
+ register struct ip6_hdr *ip6;
register struct inpcb *inp;
int flags;
+ int error = 0;
+#if 0
struct ifnet *forceif = NULL;
+#endif
+ struct ip6_pktopts opt, *optp = NULL;
+ struct ifnet *oifp = NULL;
#if __OpenBSD__
va_list ap;
struct socket *so;
- struct in6_addr *dst;
+ struct sockaddr_in6 *dst;
struct mbuf *control;
va_start(ap, m);
so = va_arg(ap, struct socket *);
- dst = va_arg(ap, struct in6_addr *);
+ dst = va_arg(ap, struct sockaddr_in6 *);
control = va_arg(ap, struct mbuf *);
va_end(ap);
#endif /* __OpenBSD__ */
@@ -440,6 +457,15 @@ ripv6_output(m, so, dst, control)
inp = sotoinpcb(so);
flags = (so->so_options & SO_DONTROUTE);
+ if (control) {
+ error = ip6_setpktoptions(control, &opt, so->so_state & SS_PRIV);
+ if (error != 0)
+ goto bad;
+ optp = &opt;
+ } else
+ optp = NULL;
+
+#if 0
if (inp->inp_flags & INP_HDRINCL)
{
flags |= IPV6_RAWOUTPUT;
@@ -448,14 +474,25 @@ ripv6_output(m, so, dst, control)
expects it to be contiguous. */
}
else
+#endif
{
- M_PREPEND(m, sizeof(struct ipv6), M_WAIT);
- ipv6 = mtod(m, struct ipv6 *);
- ipv6->ipv6_nexthdr = inp->inp_ipv6.ipv6_nexthdr;
- ipv6->ipv6_hoplimit = MAXHOPLIMIT;
- ipv6->ipv6_src = inp->inp_laddr6;
- ipv6->ipv6_dst = *dst;
- ipv6->ipv6_versfl = 0; /* Or possibly user flow label, in host order. */
+ struct in6_addr *in6a;
+
+ in6a = in6_selectsrc(dst, optp, inp->inp_moptions6,
+ &inp->inp_route6, &inp->inp_laddr6, &error);
+ if (in6a == NULL) {
+ if (error == 0)
+ error = EADDRNOTAVAIL;
+ goto bad;
+ }
+
+ M_PREPEND(m, sizeof(struct ip6_hdr), M_WAIT);
+ ip6 = mtod(m, struct ip6_hdr *);
+ ip6->ip6_flow = 0; /* Or possibly user flow label, in host order. */
+ ip6->ip6_vfc = IPV6_VERSION;
+ ip6->ip6_nxt = inp->inp_ipv6.ip6_nxt;
+ bcopy(in6a, &ip6->ip6_src, sizeof(*in6a));
+ ip6->ip6_dst = dst->sin6_addr;
/*
* Question: How do I handle options?
*
@@ -463,22 +500,55 @@ ripv6_output(m, so, dst, control)
*/
}
+ /*
+ * If the scope of the destination is link-local, embed the interface
+ * index in the address.
+ *
+ * XXX advanced-api value overrides sin6_scope_id
+ */
+ if (IN6_IS_ADDR_LINKLOCAL(&ip6->ip6_dst) ||
+ IN6_IS_ADDR_MC_LINKLOCAL(&ip6->ip6_dst)) {
+ struct in6_pktinfo *pi;
+
+ /*
+ * XXX Boundary check is assumed to be already done in
+ * ip6_setpktoptions().
+ */
+ if (optp && (pi = optp->ip6po_pktinfo) && pi->ipi6_ifindex) {
+ ip6->ip6_dst.s6_addr16[1] = htons(pi->ipi6_ifindex);
+ oifp = ifindex2ifnet[pi->ipi6_ifindex];
+ }
+ else if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst) &&
+ inp->inp_moptions6 &&
+ inp->inp_moptions6->im6o_multicast_ifp) {
+ oifp = inp->inp_moptions6->im6o_multicast_ifp;
+ ip6->ip6_dst.s6_addr16[1] = htons(oifp->if_index);
+ } else if (dst->sin6_scope_id) {
+ /* boundary check */
+ if (dst->sin6_scope_id < 0
+ || if_index < dst->sin6_scope_id) {
+ error = ENXIO; /* XXX EINVAL? */
+ goto bad;
+ }
+ ip6->ip6_dst.s6_addr16[1]
+ = htons(dst->sin6_scope_id & 0xffff);/*XXX*/
+ }
+ }
+
+ ip6->ip6_hlim = in6_selecthlim(inp, oifp);
+
{
- int payload = sizeof(struct ipv6);
- int nexthdr = mtod(m, struct ipv6 *)->ipv6_nexthdr;
+ int payload = sizeof(struct ip6_hdr);
+ int nexthdr = mtod(m, struct ip6_hdr *)->ip6_nxt;
+#if 0
int error;
-
- if (control)
- if ((error = ipv6_controltoheader(&m, control, &forceif, &payload))) {
- m_freem(m);
- return error;
- }
+#endif
if (inp->inp_csumoffset >= 0) {
uint16_t *csum;
if (!(m = m_pullup2(m, payload + inp->inp_csumoffset))) {
- DPRINTF(IDL_ERROR, ("ripv6_output: m_pullup2(m, %d) failed\n", payload + inp->inp_csumoffset));
+ DPRINTF(IDL_ERROR, ("rip6_output: m_pullup2(m, %d) failed\n", payload + inp->inp_csumoffset));
m_freem(m);
return ENOBUFS;
};
@@ -486,11 +556,16 @@ ripv6_output(m, so, dst, control)
csum = (uint16_t *)(mtod(m, uint8_t *) + payload + inp->inp_csumoffset);
*csum = 0;
- *csum = in6_cksum(m, nexthdr, m->m_pkthdr.len - payload, payload);
+ *csum = in6_cksum(m, nexthdr, payload, m->m_pkthdr.len - payload);
};
};
- return ipv6_output(m,&inp->inp_route6,flags,inp->inp_moptions6, forceif, so);
+ return ip6_output(m, optp, &inp->inp_route6, flags, inp->inp_moptions6, &oifp);
+
+bad:
+ if (m)
+ m_freem(m);
+ return error;
}
/*----------------------------------------------------------------------
@@ -498,7 +573,7 @@ ripv6_output(m, so, dst, control)
----------------------------------------------------------------------*/
#if __FreeBSD__
-int ripv6_ctloutput(struct socket *so, struct sockopt *sopt)
+int rip6_ctloutput(struct socket *so, struct sockopt *sopt)
{
register struct inpcb *inp = sotoinpcb(so);
int op;
@@ -506,7 +581,7 @@ int ripv6_ctloutput(struct socket *so, struct sockopt *sopt)
int optname;
int optval;
- DPRINTF(FINISHED, ("ripv6_ctloutput(so=%08x, sopt=%08x)\n",
+ DPRINTF(FINISHED, ("rip6_ctloutput(so=%08x, sopt=%08x)\n",
OSDEP_PCAST(so), OSDEP_PCAST(sopt)));
switch(sopt->sopt_dir) {
@@ -524,7 +599,7 @@ int ripv6_ctloutput(struct socket *so, struct sockopt *sopt)
optname = sopt->sopt_name;
#else /* __FreeBSD__ */
int
-ripv6_ctloutput (op, so, level, optname, m)
+rip6_ctloutput (op, so, level, optname, m)
int op;
struct socket *so;
int level, optname;
@@ -532,7 +607,7 @@ ripv6_ctloutput (op, so, level, optname, m)
{
register struct inpcb *inp = sotoinpcb(so);
- DPRINTF(FINISHED, ("ripv6_ctloutput(op=%x,so,level=%x,optname=%x,m)\n", op, level, optname));
+ DPRINTF(FINISHED, ("rip6_ctloutput(op=%x,so,level=%x,optname=%x,m)\n", op, level, optname));
#endif /* __FreeBSD__ */
if ((level != IPPROTO_IP) && (level != IPPROTO_IPV6) && (level != IPPROTO_ICMPV6)) {
@@ -572,34 +647,35 @@ ripv6_ctloutput (op, so, level, optname, m)
return 0;
};
break;
- case ICMPV6_FILTER:
+ case ICMP6_FILTER:
if (op == PRCO_SETOPT || op == PRCO_GETOPT) {
#if __FreeBSD__
if (!sopt->sopt_val || (sopt->sopt_valsize !=
- sizeof(struct icmpv6_filter)))
+ sizeof(struct icmp6_filter)))
RETURN_ERROR(EINVAL);
if (op == PRCO_SETOPT) {
- struct icmpv6_filter icmpv6_filter;
- int error = sooptcopyin(sopt, &icmpv6_filter,
- sizeof(struct icmpv6_filter), sizeof(struct icmpv6_filter));
+ struct icmp6_filter icmp6_filter;
+ int error = sooptcopyin(sopt, &icmp6_filter,
+ sizeof(struct icmp6_filter), sizeof(struct icmp6_filter));
if (error)
return error;
- inp->inp_filter = icmpv6_filter;
+ bcopy(&icmp6_filter, inp->inp_icmp6filt, sizeof(icmp6_filter));
return 0;
} else
- return sooptcopyout(sopt, &inp->inp_filter,
- sizeof(struct icmpv6_filter));
+ return sooptcopyout(sopt, inp->inp_icmp6filt,
+ sizeof(struct icmp6_filter));
#else /* __FreeBSD__ */
- if (!m || !*m || (*m)->m_len != sizeof(struct icmpv6_filter))
+ if (!m || !*m || (*m)->m_len != sizeof(struct icmp6_filter))
RETURN_ERROR(EINVAL);
if (op == PRCO_SETOPT) {
- inp->inp_filter = *mtod(*m, struct icmpv6_filter *);
+ bcopy(mtod(*m, struct icmp6_filter *), inp->inp_icmp6filt,
+ sizeof(struct icmp6_filter));
m_freem(*m);
} else {
- (*m)->m_len = sizeof(struct icmpv6_filter);
- *mtod(*m, struct icmpv6_filter *) = inp->inp_filter;
+ (*m)->m_len = sizeof(struct icmp6_filter);
+ *mtod(*m, struct icmp6_filter *) = *inp->inp_icmp6filt;
};
return 0;
#endif /* __FreeBSD__ */
@@ -683,9 +759,9 @@ ripv6_ctloutput (op, so, level, optname, m)
};
}
#if __FreeBSD__
- return ipv6_ctloutput(so, sopt);
+ return ip6_ctloutput(so, sopt);
#else /* __FreeBSD__ */
- return ipv6_ctloutput(op, so, level, optname, m);
+ return ip6_ctloutput(op, so, level, optname, m);
#endif /* __FreeBSD__ */
}
@@ -698,17 +774,17 @@ ripv6_ctloutput (op, so, level, optname, m)
#endif /* __GNUC__ && __GNUC__ >= 2 && __OPTIMIZE__ && !__FreeBSD__ */
#if __NetBSD__ || __FreeBSD__
-MAYBESTATIC MAYBEINLINE int ripv6_usrreq_attach(struct socket *so, int proto,
+MAYBESTATIC MAYBEINLINE int rip6_usrreq_attach(struct socket *so, int proto,
struct proc *p)
#else /* __NetBSD__ || __FreeBSD__ */
-MAYBESTATIC MAYBEINLINE int ripv6_usrreq_attach(struct socket *so, int proto)
+MAYBESTATIC MAYBEINLINE int rip6_usrreq_attach(struct socket *so, int proto)
#endif /* __NetBSD__ || __FreeBSD__ */
{
register struct inpcb *inp = sotoinpcb(so);
register int error = 0;
if (inp)
- panic("ripv6_attach - Already got PCB");
+ panic("rip6_attach - Already got PCB");
#if __NetBSD__ || __FreeBSD__
if (p == 0 || (error = suser(p->p_ucred, &p->p_acflag)))
@@ -719,7 +795,7 @@ MAYBESTATIC MAYBEINLINE int ripv6_usrreq_attach(struct socket *so, int proto)
error = EACCES;
return error;
}
- if ((error = soreserve(so, ripv6_sendspace, ripv6_recvspace)) ||
+ if ((error = soreserve(so, rip6_sendspace, rip6_recvspace)) ||
#if __FreeBSD__
(error = in_pcballoc(so, &ri6pcbinfo, p)))
@@ -735,48 +811,55 @@ MAYBESTATIC MAYBEINLINE int ripv6_usrreq_attach(struct socket *so, int proto)
inp = sotoinpcb(so);
#ifdef __alpha__
- inp->inp_ipv6.ipv6_nexthdr = (u_long)proto; /*nam; Nam contains protocol
+ inp->inp_ipv6.ip6_nxt = (u_long)proto; /*nam; Nam contains protocol
type, apparently. */
#else
- inp->inp_ipv6.ipv6_nexthdr = (int)proto; /*nam; Nam contains protocol
+ inp->inp_ipv6.ip6_nxt = (int)proto; /*nam; Nam contains protocol
type, apparently. */
#endif
- if (inp->inp_ipv6.ipv6_nexthdr == IPPROTO_ICMPV6)
+ if (inp->inp_ipv6.ip6_nxt == IPPROTO_ICMPV6)
inp->inp_csumoffset = 2;
+ inp->inp_icmp6filt = (struct icmp6_filter *)
+ malloc(sizeof(struct icmp6_filter), M_PCB, M_NOWAIT);
+ ICMP6_FILTER_SETPASSALL(inp->inp_icmp6filt);
return error;
}
-MAYBESTATIC MAYBEINLINE int ripv6_usrreq_detach(struct socket *so)
+MAYBESTATIC MAYBEINLINE int rip6_usrreq_detach(struct socket *so)
{
register struct inpcb *inp = sotoinpcb(so);
if (inp == 0)
- panic("ripv6_detach");
+ panic("rip6_detach");
#ifdef MROUTING
/* More MROUTING stuff. */
#endif
+ if (inp->inp_icmp6filt) {
+ free(inp->inp_icmp6filt, M_PCB);
+ inp->inp_icmp6filt = NULL;
+ }
in_pcbdetach(inp);
return 0;
}
-MAYBESTATIC MAYBEINLINE int ripv6_usrreq_abort(struct socket *so)
+MAYBESTATIC MAYBEINLINE int rip6_usrreq_abort(struct socket *so)
{
soisdisconnected(so);
- return ripv6_usrreq_detach(so);
+ return rip6_usrreq_detach(so);
}
-static MAYBEINLINE int ripv6_usrreq_disconnect(struct socket *so)
+static MAYBEINLINE int rip6_usrreq_disconnect(struct socket *so)
{
if ((so->so_state & SS_ISCONNECTED) == 0)
return ENOTCONN;
- return ripv6_usrreq_abort(so);
+ return rip6_usrreq_abort(so);
}
#if __NetBSD__ || __FreeBSD__
-MAYBESTATIC MAYBEINLINE int ripv6_usrreq_bind(struct socket *so,
+MAYBESTATIC MAYBEINLINE int rip6_usrreq_bind(struct socket *so,
struct sockaddr *nam, struct proc *p)
#else /* __NetBSD__ || __FreeBSD__ */
-MAYBESTATIC MAYBEINLINE int ripv6_usrreq_bind(struct socket *so,
+MAYBESTATIC MAYBEINLINE int rip6_usrreq_bind(struct socket *so,
struct sockaddr *nam)
#endif /* __NetBSD__ || __FreeBSD__ */
{
@@ -800,27 +883,30 @@ MAYBESTATIC MAYBEINLINE int ripv6_usrreq_bind(struct socket *so,
}
#if __NetBSD__ || __FreeBSD__
-MAYBESTATIC MAYBEINLINE int ripv6_usrreq_connect(struct socket *so,
+MAYBESTATIC MAYBEINLINE int rip6_usrreq_connect(struct socket *so,
struct sockaddr *nam, struct proc *p)
#else /* __NetBSD__ || __FreeBSD__ */
-MAYBESTATIC MAYBEINLINE int ripv6_usrreq_connect(struct socket *so,
+MAYBESTATIC MAYBEINLINE int rip6_usrreq_connect(struct socket *so,
struct sockaddr *nam)
#endif /* __NetBSD__ || __FreeBSD__ */
{
register struct inpcb *inp = sotoinpcb(so);
register struct sockaddr_in6 *addr = (struct sockaddr_in6 *) nam;
+ int error;
+ struct in6_addr *in6a;
if (addr->sin6_family != AF_INET6)
return EAFNOSUPPORT;
-#if __NetBSD__ || __FreeBSD__ || __OpenBSD__
- if (ifnet.tqh_first == 0) {
-#else /* __NetBSD__ || __FreeBSD__ || __OpenBSD__ */
- if (ifnet == 0) {
-#endif /* __NetBSD__ || __FreeBSD__ || __OpenBSD__ */
- return EADDRNOTAVAIL; /* This is a weird way to say there
- are no interfaces, no? */
- }
+ in6a = in6_selectsrc(addr, inp->inp_outputopts6,
+ inp->inp_moptions6, &inp->inp_route6, &inp->inp_laddr6,
+ &error);
+ if (in6a == NULL) {
+ if (error == 0)
+ error = EADDRNOTAVAIL;
+ return error;
+ }
+ inp->inp_laddr6 = *in6a;
inp->inp_faddr6 = addr->sin6_addr; /* Will structure assignment
work with this compiler? */
@@ -828,28 +914,31 @@ MAYBESTATIC MAYBEINLINE int ripv6_usrreq_connect(struct socket *so,
return 0;
}
-MAYBESTATIC MAYBEINLINE int ripv6_usrreq_shutdown(struct socket *so)
+MAYBESTATIC MAYBEINLINE int rip6_usrreq_shutdown(struct socket *so)
{
socantsendmore(so);
return 0;
}
+static int rip6_usrreq_send __P((struct socket *so, int flags, struct mbuf *m,
+ struct sockaddr *addr, struct mbuf *control));
+
#if __NetBSD__ || __FreeBSD__
/*
* Note that flags and p are not used, but required by protosw in
* FreeBSD.
*/
-int ripv6_usrreq_send(struct socket *so, int flags, struct mbuf *m,
+static int rip6_usrreq_send(struct socket *so, int flags, struct mbuf *m,
struct sockaddr *addr, struct mbuf *control,
struct proc *p)
#else /* __NetBSD__ || __FreeBSD__ */
-int ripv6_usrreq_send(struct socket *so, int flags, struct mbuf *m,
+static int rip6_usrreq_send(struct socket *so, int flags, struct mbuf *m,
struct sockaddr *addr, struct mbuf *control)
#endif /* __NetBSD__ || __FreeBSD__ */
{
register struct inpcb *inp = sotoinpcb(so);
register int error = 0;
- struct in6_addr *dst;
+ struct sockaddr_in6 *dst, tmp;
if (inp == 0) {
m_freem(m);
@@ -865,26 +954,30 @@ int ripv6_usrreq_send(struct socket *so, int flags, struct mbuf *m,
if (addr)
return EISCONN;
- dst = &(inp->inp_faddr6);
+ bzero(&tmp, sizeof(tmp));
+ tmp.sin6_family = AF_INET6;
+ tmp.sin6_len = sizeof(tmp);
+ tmp.sin6_addr = inp->inp_faddr6;
+ dst = &tmp;
}
else
{
if (addr == NULL)
return ENOTCONN;
- dst = &((struct sockaddr_in6 *)addr)->sin6_addr;
+ dst = (struct sockaddr_in6 *)addr;
}
- error = ripv6_output(m,so,dst,control);
+ error = rip6_output(m,so,dst,control);
/* m = NULL; */
return error;
}
#if __NetBSD__ || __FreeBSD__
-MAYBESTATIC MAYBEINLINE int ripv6_usrreq_control(struct socket *so, u_long cmd,
+MAYBESTATIC MAYBEINLINE int rip6_usrreq_control(struct socket *so, u_long cmd,
caddr_t data, struct ifnet *ifp, struct proc *p)
#else /* __NetBSD__ || __FreeBSD__ */
-MAYBESTATIC MAYBEINLINE int ripv6_usrreq_control(struct socket *so, int cmd,
+MAYBESTATIC MAYBEINLINE int rip6_usrreq_control(struct socket *so, int cmd,
caddr_t data, struct ifnet *ifp)
#endif /* __NetBSD__ || __FreeBSD__ */
{
@@ -897,7 +990,7 @@ MAYBESTATIC MAYBEINLINE int ripv6_usrreq_control(struct socket *so, int cmd,
#endif /* __NetBSD__ || __FreeBSD__ */
}
-MAYBESTATIC MAYBEINLINE int ripv6_usrreq_sense(struct socket *so,
+MAYBESTATIC MAYBEINLINE int rip6_usrreq_sense(struct socket *so,
struct stat *sb)
{
/* services stat(2) call. */
@@ -905,10 +998,10 @@ MAYBESTATIC MAYBEINLINE int ripv6_usrreq_sense(struct socket *so,
}
#if __FreeBSD__
-MAYBESTATIC MAYBEINLINE int ripv6_usrreq_sockaddr(struct socket *so,
+MAYBESTATIC MAYBEINLINE int rip6_usrreq_sockaddr(struct socket *so,
struct sockaddr **nam)
#else /* __FreeBSD__ */
-MAYBESTATIC MAYBEINLINE int ripv6_usrreq_sockaddr(struct socket *so,
+MAYBESTATIC MAYBEINLINE int rip6_usrreq_sockaddr(struct socket *so,
struct mbuf *nam)
#endif /* __FreeBSD__ */
{
@@ -917,10 +1010,10 @@ MAYBESTATIC MAYBEINLINE int ripv6_usrreq_sockaddr(struct socket *so,
}
#if __FreeBSD__
-MAYBESTATIC MAYBEINLINE int ripv6_usrreq_peeraddr(struct socket *so,
+MAYBESTATIC MAYBEINLINE int rip6_usrreq_peeraddr(struct socket *so,
struct sockaddr **nam)
#else /* __FreeBSD__ */
-MAYBESTATIC MAYBEINLINE int ripv6_usrreq_peeraddr(struct socket *so,
+MAYBESTATIC MAYBEINLINE int rip6_usrreq_peeraddr(struct socket *so,
struct mbuf *nam)
#endif /* __FreeBSD__ */
{
@@ -929,13 +1022,13 @@ MAYBESTATIC MAYBEINLINE int ripv6_usrreq_peeraddr(struct socket *so,
}
#if __FreeBSD__
-struct pr_usrreqs ripv6_usrreqs = {
- ripv6_usrreq_abort, pru_accept_notsupp, ripv6_usrreq_attach,
- ripv6_usrreq_bind, ripv6_usrreq_connect, pru_connect2_notsupp,
- ripv6_usrreq_control, ripv6_usrreq_detach, ripv6_usrreq_detach,
- pru_listen_notsupp, ripv6_usrreq_peeraddr, pru_rcvd_notsupp,
- pru_rcvoob_notsupp, ripv6_usrreq_send, ripv6_usrreq_sense,
- ripv6_usrreq_shutdown, ripv6_usrreq_sockaddr, sosend, soreceive, sopoll
+struct pr_usrreqs rip6_usrreqs = {
+ rip6_usrreq_abort, pru_accept_notsupp, rip6_usrreq_attach,
+ rip6_usrreq_bind, rip6_usrreq_connect, pru_connect2_notsupp,
+ rip6_usrreq_control, rip6_usrreq_detach, rip6_usrreq_detach,
+ pru_listen_notsupp, rip6_usrreq_peeraddr, pru_rcvd_notsupp,
+ pru_rcvoob_notsupp, rip6_usrreq_send, rip6_usrreq_sense,
+ rip6_usrreq_shutdown, rip6_usrreq_sockaddr, sosend, soreceive, sopoll
};
#endif /* __FreeBSD__ */
@@ -944,21 +1037,15 @@ struct pr_usrreqs ripv6_usrreqs = {
----------------------------------------------------------------------*/
#if !__FreeBSD__
int
-#if __NetBSD__
-ripv6_usrreq(so, req, m, nam, control, p)
-#else /* __NetBSD__ */
-ripv6_usrreq(so, req, m, nam, control)
-#endif /* __NetBSD__ */
+rip6_usrreq(so, req, m, nam, control, p)
struct socket *so;
int req;
struct mbuf *m, *nam, *control;
-#if __NetBSD__
struct proc *p;
-#endif /* __NetBSD__ */
{
register int error = 0;
- DPRINTF(IDL_EVENT, ("ripv6_usrreq(so, req, m, nam, control)\n"));
+ DPRINTF(IDL_EVENT, ("rip6_usrreq(so, req, m, nam, control)\n"));
#ifdef MROUTING
/*
@@ -974,23 +1061,23 @@ ripv6_usrreq(so, req, m, nam, control)
{
case PRU_ATTACH:
#if __NetBSD__
- error = ripv6_usrreq_attach(so, 0, p); /* XXX */
+ error = rip6_usrreq_attach(so, (long)nam, p);
#else /* __NetBSD__ */
- error = ripv6_usrreq_attach(so, 0); /* XXX */
+ error = rip6_usrreq_attach(so, (long)nam);
#endif /* __NetBSD__ */
break;
case PRU_DISCONNECT:
- error = ripv6_usrreq_disconnect(so);
+ error = rip6_usrreq_disconnect(so);
break;
/* NOT */
/* FALLTHROUGH */
case PRU_ABORT:
- error = ripv6_usrreq_abort(so);
+ error = rip6_usrreq_abort(so);
break;
/* NOT */
/* FALLTHROUGH */
case PRU_DETACH:
- error = ripv6_usrreq_detach(so);
+ error = rip6_usrreq_detach(so);
break;
case PRU_BIND:
if (nam->m_len != sizeof(struct sockaddr_in6))
@@ -999,9 +1086,9 @@ ripv6_usrreq(so, req, m, nam, control)
* Be strict regarding sockaddr_in6 fields.
*/
#if __NetBSD__
- error = ripv6_usrreq_bind(so, mtod(nam, struct sockaddr *), p);
+ error = rip6_usrreq_bind(so, mtod(nam, struct sockaddr *), p);
#else /* __NetBSD__ */
- error = ripv6_usrreq_bind(so, mtod(nam, struct sockaddr *));
+ error = rip6_usrreq_bind(so, mtod(nam, struct sockaddr *));
#endif /* __NetBSD__ */
break;
case PRU_CONNECT:
@@ -1011,13 +1098,13 @@ ripv6_usrreq(so, req, m, nam, control)
if (nam->m_len != sizeof(struct sockaddr_in6))
return EINVAL;
#if __NetBSD__
- error = ripv6_usrreq_connect(so, mtod(nam, struct sockaddr *), p);
+ error = rip6_usrreq_connect(so, mtod(nam, struct sockaddr *), p);
#else /* __NetBSD__ */
- error = ripv6_usrreq_connect(so, mtod(nam, struct sockaddr *));
+ error = rip6_usrreq_connect(so, mtod(nam, struct sockaddr *));
#endif /* __NetBSD__ */
break;
case PRU_SHUTDOWN:
- error = ripv6_usrreq_shutdown(so);
+ error = rip6_usrreq_shutdown(so);
break;
case PRU_SEND:
/*
@@ -1026,22 +1113,22 @@ ripv6_usrreq(so, req, m, nam, control)
if (nam->m_len != sizeof(struct sockaddr_in6))
return EINVAL;
#if __NetBSD__
- error = ripv6_usrreq_send(so, 0, m, mtod(nam, struct sockaddr *), control, p);
+ error = rip6_usrreq_send(so, 0, m, mtod(nam, struct sockaddr *), control, p);
#else /* __NetBSD__ */
- error = ripv6_usrreq_send(so, 0, m, mtod(nam, struct sockaddr *), control);
+ error = rip6_usrreq_send(so, 0, m, mtod(nam, struct sockaddr *), control);
#endif /* __NetBSD__ */
m = NULL;
break;
case PRU_CONTROL:
#if __NetBSD__
- return ripv6_usrreq_control(so, (u_long)m, (caddr_t) nam,
+ return rip6_usrreq_control(so, (u_long)m, (caddr_t) nam,
(struct ifnet *) control, p);
#else /* __NetBSD__ */
- return ripv6_usrreq_control(so, (int)m, (caddr_t) nam,
+ return rip6_usrreq_control(so, (int)m, (caddr_t) nam,
(struct ifnet *) control);
#endif /* __NetBSD__ */
case PRU_SENSE:
- return ripv6_usrreq_sense(so, NULL); /* XXX */
+ return rip6_usrreq_sense(so, NULL); /* XXX */
case PRU_CONNECT2:
case PRU_RCVOOB:
case PRU_LISTEN:
@@ -1051,13 +1138,13 @@ ripv6_usrreq(so, req, m, nam, control)
error = EOPNOTSUPP;
break;
case PRU_SOCKADDR:
- error = ripv6_usrreq_sockaddr(so, nam);
+ error = rip6_usrreq_sockaddr(so, nam);
break;
case PRU_PEERADDR:
- error = ripv6_usrreq_peeraddr(so, nam);
+ error = rip6_usrreq_peeraddr(so, nam);
break;
default:
- panic ("ripv6_usrreq - unknown req\n");
+ panic ("rip6_usrreq - unknown req\n");
}
if (m != NULL)
m_freem(m);