summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/netinet/in.h3
-rw-r--r--sys/netinet/in_pcb.h9
-rw-r--r--sys/netinet/ip_input.c64
-rw-r--r--sys/netinet/ip_output.c10
-rw-r--r--sys/netinet/ip_var.h5
-rw-r--r--sys/netinet/raw_ip.c51
-rw-r--r--sys/netinet/udp_usrreq.c57
7 files changed, 115 insertions, 84 deletions
diff --git a/sys/netinet/in.h b/sys/netinet/in.h
index e9cf72408b8..33a9fb60315 100644
--- a/sys/netinet/in.h
+++ b/sys/netinet/in.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: in.h,v 1.69 2006/05/26 20:50:41 deraadt Exp $ */
+/* $OpenBSD: in.h,v 1.70 2006/05/29 20:42:27 claudio Exp $ */
/* $NetBSD: in.h,v 1.20 1996/02/13 23:41:47 christos Exp $ */
/*
@@ -264,6 +264,7 @@ struct ip_opts {
#define IP_IPSEC_LOCAL_AUTH 27 /* buf; IPsec local auth material */
#define IP_IPSEC_REMOTE_AUTH 28 /* buf; IPsec remote auth material */
#define IP_IPCOMP_LEVEL 29 /* int; compression used */
+#define IP_RECVIF 30 /* bool; receive reception if w/dgram */
/*
* Security levels - IPsec, not IPSO
diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h
index e6a12d0c55e..a2f70a5cd4e 100644
--- a/sys/netinet/in_pcb.h
+++ b/sys/netinet/in_pcb.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: in_pcb.h,v 1.52 2005/12/10 01:30:14 deraadt Exp $ */
+/* $OpenBSD: in_pcb.h,v 1.53 2006/05/29 20:42:27 claudio Exp $ */
/* $NetBSD: in_pcb.h,v 1.14 1996/02/13 23:42:00 christos Exp $ */
/*
@@ -164,12 +164,13 @@ struct inpcbtable {
#define INP_RXSRCRT 0x010
#define INP_HOPLIMIT 0x020
-#define INP_CONTROLOPTS (INP_RECVOPTS|INP_RECVRETOPTS|INP_RECVDSTADDR| \
- INP_RXSRCRT|INP_HOPLIMIT)
-
#define INP_HDRINCL 0x008 /* user supplies entire IP header */
#define INP_HIGHPORT 0x010 /* user wants "high" port binding */
#define INP_LOWPORT 0x020 /* user wants "low" port binding */
+#define INP_RECVIF 0x080 /* receive incoming interface */
+
+#define INP_CONTROLOPTS (INP_RECVOPTS|INP_RECVRETOPTS|INP_RECVDSTADDR| \
+ INP_RXSRCRT|INP_HOPLIMIT|INP_RECVIF)
/*
* These flags' values should be determined by either the transport
diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c
index 83d63334ad9..160fac4048d 100644
--- a/sys/netinet/ip_input.c
+++ b/sys/netinet/ip_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_input.c,v 1.138 2006/03/05 21:48:56 miod Exp $ */
+/* $OpenBSD: ip_input.c,v 1.139 2006/05/29 20:42:27 claudio Exp $ */
/* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */
/*
@@ -40,6 +40,7 @@
#include <sys/domain.h>
#include <sys/protosw.h>
#include <sys/socket.h>
+#include <sys/socketvar.h>
#include <sys/syslog.h>
#include <sys/sysctl.h>
@@ -1627,3 +1628,64 @@ ip_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
}
/* NOTREACHED */
}
+
+void
+ip_savecontrol(struct inpcb *inp, struct mbuf **mp, struct ip *ip,
+ struct mbuf *m)
+{
+#ifdef SO_TIMESTAMP
+ if (inp->inp_socket->so_options & SO_TIMESTAMP) {
+ struct timeval tv;
+
+ microtime(&tv);
+ *mp = sbcreatecontrol((caddr_t) &tv, sizeof(tv),
+ SCM_TIMESTAMP, SOL_SOCKET);
+ if (*mp)
+ mp = &(*mp)->m_next;
+ }
+#endif
+ if (inp->inp_flags & INP_RECVDSTADDR) {
+ *mp = sbcreatecontrol((caddr_t) &ip->ip_dst,
+ sizeof(struct in_addr), IP_RECVDSTADDR, IPPROTO_IP);
+ if (*mp)
+ mp = &(*mp)->m_next;
+ }
+#ifdef notyet
+ /* this code is broken and will probably never be fixed. */
+ /* options were tossed already */
+ if (inp->inp_flags & INP_RECVOPTS) {
+ *mp = sbcreatecontrol((caddr_t) opts_deleted_above,
+ sizeof(struct in_addr), IP_RECVOPTS, IPPROTO_IP);
+ if (*mp)
+ mp = &(*mp)->m_next;
+ }
+ /* ip_srcroute doesn't do what we want here, need to fix */
+ if (inp->inp_flags & INP_RECVRETOPTS) {
+ *mp = sbcreatecontrol((caddr_t) ip_srcroute(),
+ sizeof(struct in_addr), IP_RECVRETOPTS, IPPROTO_IP);
+ if (*mp)
+ mp = &(*mp)->m_next;
+ }
+#endif
+ if (inp->inp_flags & INP_RECVIF) {
+ struct sockaddr_dl sdl;
+ struct ifnet *ifp;
+
+ if ((ifp = m->m_pkthdr.rcvif) == NULL ||
+ ifp->if_sadl == NULL) {
+ bzero(&sdl, sizeof(sdl));
+ sdl.sdl_len = offsetof(struct sockaddr_dl, sdl_data[0]);
+ sdl.sdl_family = AF_LINK;
+ sdl.sdl_index = ifp != NULL ? ifp->if_index : 0;
+ sdl.sdl_nlen = sdl.sdl_alen = sdl.sdl_slen = 0;
+ *mp = sbcreatecontrol((caddr_t) &sdl, sdl.sdl_len,
+ IP_RECVIF, IPPROTO_IP);
+ } else {
+ *mp = sbcreatecontrol((caddr_t) ifp->if_sadl,
+ ifp->if_sadl->sdl_len, IP_RECVIF, IPPROTO_IP);
+ }
+ if (*mp)
+ mp = &(*mp)->m_next;
+ }
+}
+
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index ee15bd2cd43..697cc0231f0 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_output.c,v 1.177 2006/05/26 20:50:41 deraadt Exp $ */
+/* $OpenBSD: ip_output.c,v 1.178 2006/05/29 20:42:27 claudio Exp $ */
/* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */
/*
@@ -1044,6 +1044,7 @@ ip_ctloutput(op, so, level, optname, mp)
case IP_RECVOPTS:
case IP_RECVRETOPTS:
case IP_RECVDSTADDR:
+ case IP_RECVIF:
if (m == NULL || m->m_len != sizeof(int))
error = EINVAL;
else {
@@ -1074,6 +1075,9 @@ ip_ctloutput(op, so, level, optname, mp)
case IP_RECVDSTADDR:
OPTSET(INP_RECVDSTADDR);
break;
+ case IP_RECVIF:
+ OPTSET(INP_RECVIF);
+ break;
}
}
break;
@@ -1375,6 +1379,7 @@ ip_ctloutput(op, so, level, optname, mp)
case IP_RECVOPTS:
case IP_RECVRETOPTS:
case IP_RECVDSTADDR:
+ case IP_RECVIF:
*mp = m = m_get(M_WAIT, MT_SOOPTS);
m->m_len = sizeof(int);
switch (optname) {
@@ -1400,6 +1405,9 @@ ip_ctloutput(op, so, level, optname, mp)
case IP_RECVDSTADDR:
optval = OPTBIT(INP_RECVDSTADDR);
break;
+ case IP_RECVIF:
+ optval = OPTBIT(INP_RECVIF);
+ break;
}
*mtod(m, int *) = optval;
break;
diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h
index 725798c077f..dbe2c64a593 100644
--- a/sys/netinet/ip_var.h
+++ b/sys/netinet/ip_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_var.h,v 1.35 2005/08/11 12:55:31 mpf Exp $ */
+/* $OpenBSD: ip_var.h,v 1.36 2006/05/29 20:42:27 claudio Exp $ */
/* $NetBSD: ip_var.h,v 1.16 1996/02/13 23:43:20 christos Exp $ */
/*
@@ -152,6 +152,7 @@ extern int ip_mtudisc; /* mtu discovery */
extern u_int ip_mtudisc_timeout; /* seconds to timeout mtu discovery */
extern struct rttimer_queue *ip_mtudisc_timeout_q;
extern struct pool ipqent_pool;
+struct inpcb;
int ip_ctloutput(int, struct socket *, int, int, struct mbuf **);
int ip_dooptions(struct mbuf *);
@@ -181,6 +182,8 @@ struct mbuf *
ip_srcroute(void);
void ip_stripoptions(struct mbuf *, struct mbuf *);
int ip_sysctl(int *, u_int, void *, size_t *, void *, size_t);
+void ip_savecontrol(struct inpcb *, struct mbuf **, struct ip *,
+ struct mbuf *);
void ipintr(void);
void ipv4_input(struct mbuf *);
int rip_ctloutput(int, struct socket *, int, int, struct mbuf **);
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
index a14519aa345..83279f8cb0c 100644
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: raw_ip.c,v 1.38 2006/03/05 21:48:57 miod Exp $ */
+/* $OpenBSD: raw_ip.c,v 1.39 2006/05/29 20:42:27 claudio Exp $ */
/* $NetBSD: raw_ip.c,v 1.25 1996/02/18 18:58:33 christos Exp $ */
/*
@@ -120,8 +120,8 @@ void
rip_input(struct mbuf *m, ...)
{
struct ip *ip = mtod(m, struct ip *);
- struct inpcb *inp;
- struct socket *last = 0;
+ struct inpcb *inp, *last = NULL;
+ struct mbuf *opts = NULL;
ripsrc.sin_addr = ip->ip_src;
CIRCLEQ_FOREACH(inp, &rawcbtable.inpt_queue, inp_queue) {
@@ -139,24 +139,34 @@ rip_input(struct mbuf *m, ...)
continue;
if (last) {
struct mbuf *n;
+
if ((n = m_copy(m, 0, (int)M_COPYALL)) != NULL) {
- if (sbappendaddr(&last->so_rcv,
- sintosa(&ripsrc), n,
- (struct mbuf *)0) == 0)
+ if (last->inp_flags & INP_CONTROLOPTS)
+ ip_savecontrol(last, &opts, ip, n);
+ if (sbappendaddr(&last->inp_socket->so_rcv,
+ sintosa(&ripsrc), n, opts) == 0) {
/* should notify about lost packet */
m_freem(n);
- else
- sorwakeup(last);
+ if (opts)
+ m_freem(opts);
+ } else
+ sorwakeup(last->inp_socket);
+ if (opts)
+ opts = NULL;
}
}
- last = inp->inp_socket;
+ last = inp;
}
if (last) {
- if (sbappendaddr(&last->so_rcv, sintosa(&ripsrc), m,
- (struct mbuf *)0) == 0)
+ if (last->inp_flags & INP_CONTROLOPTS)
+ ip_savecontrol(last, &opts, ip, m);
+ if (sbappendaddr(&last->inp_socket->so_rcv, sintosa(&ripsrc), m,
+ opts) == 0) {
m_freem(m);
- else
- sorwakeup(last);
+ if (opts)
+ m_freem(opts);
+ } else
+ sorwakeup(last->inp_socket);
} else {
if (ip->ip_p != IPPROTO_ICMP)
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_PROTOCOL, 0, 0);
@@ -251,11 +261,8 @@ rip_output(struct mbuf *m, ...)
* Raw IP socket option processing.
*/
int
-rip_ctloutput(op, so, level, optname, m)
- int op;
- struct socket *so;
- int level, optname;
- struct mbuf **m;
+rip_ctloutput(int op, struct socket *so, int level, int optname,
+ struct mbuf **m)
{
struct inpcb *inp = sotoinpcb(so);
int error;
@@ -325,10 +332,8 @@ u_long rip_recvspace = RIPRCVQ;
/*ARGSUSED*/
int
-rip_usrreq(so, req, m, nam, control)
- struct socket *so;
- int req;
- struct mbuf *m, *nam, *control;
+rip_usrreq(struct socket *so, int req, struct mbuf *m, struct mbuf *nam,
+ struct mbuf *control)
{
int error = 0;
struct inpcb *inp = sotoinpcb(so);
@@ -337,7 +342,7 @@ rip_usrreq(so, req, m, nam, control)
#endif
if (req == PRU_CONTROL)
return (in_control(so, (u_long)m, (caddr_t)nam,
- (struct ifnet *)control));
+ (struct ifnet *)control));
if (inp == NULL && req != PRU_ATTACH) {
error = EINVAL;
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index 2e1cdb35394..d29e3674852 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: udp_usrreq.c,v 1.107 2006/05/16 12:39:21 markus Exp $ */
+/* $OpenBSD: udp_usrreq.c,v 1.108 2006/05/29 20:42:27 claudio Exp $ */
/* $NetBSD: udp_usrreq.c,v 1.28 1996/03/16 23:54:03 christos Exp $ */
/*
@@ -120,7 +120,6 @@ struct udpstat udpstat;
static void udp_detach(struct inpcb *);
static void udp_notify(struct inpcb *, int);
-static struct mbuf *udp_saveopt(caddr_t, int, int);
#ifndef UDBHASHSIZE
#define UDBHASHSIZE 128
@@ -624,32 +623,9 @@ udp_input(struct mbuf *m, ...)
if (ip6 && (inp->inp_flags & IN6P_CONTROLOPTS))
ip6_savecontrol(inp, &opts, ip6, m);
#endif /* INET6 */
- if (ip && (inp->inp_flags & INP_CONTROLOPTS)) {
- struct mbuf **mp = &opts;
-
- if (inp->inp_flags & INP_RECVDSTADDR) {
- *mp = udp_saveopt((caddr_t) &ip->ip_dst,
- sizeof(struct in_addr), IP_RECVDSTADDR);
- if (*mp)
- mp = &(*mp)->m_next;
- }
-#ifdef notyet
- /* options were tossed above */
- if (inp->inp_flags & INP_RECVOPTS) {
- *mp = udp_saveopt((caddr_t) opts_deleted_above,
- sizeof(struct in_addr), IP_RECVOPTS);
- if (*mp)
- mp = &(*mp)->m_next;
- }
- /* ip_srcroute doesn't do what we want here, need to fix */
- if (inp->inp_flags & INP_RECVRETOPTS) {
- *mp = udp_saveopt((caddr_t) ip_srcroute(),
- sizeof(struct in_addr), IP_RECVRETOPTS);
- if (*mp)
- mp = &(*mp)->m_next;
- }
-#endif
- }
+ if (ip && (inp->inp_flags & INP_CONTROLOPTS))
+ ip_savecontrol(inp, &opts, ip, m);
+
iphlen += sizeof(struct udphdr);
m_adj(m, iphlen);
if (sbappendaddr(&inp->inp_socket->so_rcv, &srcsa.sa, m, opts) == 0) {
@@ -665,31 +641,6 @@ bad:
}
/*
- * Create a "control" mbuf containing the specified data
- * with the specified type for presentation with a datagram.
- */
-struct mbuf *
-udp_saveopt(p, size, type)
- caddr_t p;
- int size;
- int type;
-{
- struct cmsghdr *cp;
- struct mbuf *m;
-
- if ((m = m_get(M_DONTWAIT, MT_CONTROL)) == NULL)
- return ((struct mbuf *) NULL);
- cp = (struct cmsghdr *) mtod(m, struct cmsghdr *);
- bcopy(p, CMSG_DATA(cp), size);
- size = CMSG_LEN(size);
- m->m_len = size;
- cp->cmsg_len = size;
- cp->cmsg_level = IPPROTO_IP;
- cp->cmsg_type = type;
- return (m);
-}
-
-/*
* Notify a udp user of an asynchronous error;
* just wake up so that he can collect error status.
*/