diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/netinet/in.h | 3 | ||||
-rw-r--r-- | sys/netinet/in_pcb.h | 9 | ||||
-rw-r--r-- | sys/netinet/ip_input.c | 64 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 10 | ||||
-rw-r--r-- | sys/netinet/ip_var.h | 5 | ||||
-rw-r--r-- | sys/netinet/raw_ip.c | 51 | ||||
-rw-r--r-- | sys/netinet/udp_usrreq.c | 57 |
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. */ |