summaryrefslogtreecommitdiff
path: root/sys/netinet6/raw_ipv6.c
diff options
context:
space:
mode:
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);