Hi, The udp control option processing is implemented 3 times. Multicast lacks receive destination port. So better use a function and do it all in one place.
The pipex chunk does not use the options, so it can happen before. Adding the udp header length to the ip header length was done inconsistently. Better do that explicitly when it is needed. ok? bluhm Index: netinet/udp_usrreq.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/netinet/udp_usrreq.c,v retrieving revision 1.248 diff -u -p -r1.248 udp_usrreq.c --- netinet/udp_usrreq.c 14 May 2018 15:24:23 -0000 1.248 +++ netinet/udp_usrreq.c 6 Jun 2018 18:26:05 -0000 @@ -132,6 +132,9 @@ int *udpctl_vars[UDPCTL_MAXID] = UDPCTL_ struct inpcbtable udbtable; struct cpumem *udpcounters; +void udp_sbappend(struct inpcb *, struct mbuf *, struct ip *, + struct ip6_hdr *, int, struct udphdr *, struct sockaddr *, + u_int32_t); int udp_output(struct inpcb *, struct mbuf *, struct mbuf *, struct mbuf *); void udp_notify(struct inpcb *, int); int udp_sysctl_udpstat(void *, size_t *, void *); @@ -155,7 +158,6 @@ udp_input(struct mbuf **mp, int *offp, i struct ip *ip = NULL; struct udphdr *uh; struct inpcb *inp = NULL; - struct mbuf *opts = NULL; struct ip save_ip; int len; u_int16_t savesum; @@ -175,9 +177,7 @@ udp_input(struct mbuf **mp, int *offp, i struct tdb *tdb; int error, protoff; #endif /* IPSEC */ -#if defined(IPSEC) || defined(PIPEX) u_int32_t ipsecflowinfo = 0; -#endif /* define(IPSEC) || defined(PIPEX) */ udpstat_inc(udps_ipackets); @@ -376,8 +376,6 @@ udp_input(struct mbuf **mp, int *offp, i * fixing the interface. Maybe 4.5BSD will remedy this?) */ - iphlen += sizeof(struct udphdr); - /* * Locate pcb(s) for datagram. * (Algorithm copied from raw_intr().) @@ -442,30 +440,8 @@ udp_input(struct mbuf **mp, int *offp, i n = m_copym(m, 0, M_COPYALL, M_NOWAIT); if (n != NULL) { -#ifdef INET6 - if (ip6 && (last->inp_flags & - IN6P_CONTROLOPTS || - last->inp_socket->so_options & - SO_TIMESTAMP)) - ip6_savecontrol(last, n, &opts); -#endif /* INET6 */ - if (ip && (last->inp_flags & - INP_CONTROLOPTS || - last->inp_socket->so_options & - SO_TIMESTAMP)) - ip_savecontrol(last, &opts, - ip, n); - - m_adj(n, iphlen); - if (sbappendaddr(last->inp_socket, - &last->inp_socket->so_rcv, - &srcsa.sa, n, opts) == 0) { - m_freem(n); - m_freem(opts); - udpstat_inc(udps_fullsock); - } else - sorwakeup(last->inp_socket); - opts = NULL; + udp_sbappend(last, n, ip, ip6, iphlen, + uh, &srcsa.sa, 0); } } last = inp; @@ -492,22 +468,7 @@ udp_input(struct mbuf **mp, int *offp, i goto bad; } -#ifdef INET6 - if (ip6 && (last->inp_flags & IN6P_CONTROLOPTS || - last->inp_socket->so_options & SO_TIMESTAMP)) - ip6_savecontrol(last, m, &opts); -#endif /* INET6 */ - if (ip && (last->inp_flags & INP_CONTROLOPTS || - last->inp_socket->so_options & SO_TIMESTAMP)) - ip_savecontrol(last, &opts, ip, m); - - m_adj(m, iphlen); - if (sbappendaddr(last->inp_socket, &last->inp_socket->so_rcv, - &srcsa.sa, m, opts) == 0) { - udpstat_inc(udps_fullsock); - goto bad; - } - sorwakeup(last->inp_socket); + udp_sbappend(last, m, ip, ip6, iphlen, uh, &srcsa.sa, 0); return IPPROTO_DONE; } /* @@ -597,14 +558,42 @@ udp_input(struct mbuf **mp, int *offp, i ipsecflowinfo = tdb->tdb_ids->id_flow; #endif /*IPSEC */ - opts = NULL; +#ifdef PIPEX + if (pipex_enable && inp->inp_pipex) { + struct pipex_session *session; + int off = iphlen + sizeof(struct udphdr); + if ((session = pipex_l2tp_lookup_session(m, off)) != NULL) { + if ((m = *mp = pipex_l2tp_input(m, off, session, + ipsecflowinfo)) == NULL) { + /* the packet is handled by PIPEX */ + return IPPROTO_DONE; + } + } + } +#endif + + udp_sbappend(inp, m, ip, ip6, iphlen, uh, &srcsa.sa, ipsecflowinfo); + return IPPROTO_DONE; +bad: + m_freem(m); + return IPPROTO_DONE; +} + +void +udp_sbappend(struct inpcb *inp, struct mbuf *m, struct ip *ip, + struct ip6_hdr *ip6, int iphlen, struct udphdr *uh, + struct sockaddr *srcaddr, u_int32_t ipsecflowinfo) +{ + struct socket *so = inp->inp_socket; + struct mbuf *opts = NULL; + #ifdef INET6 if (ip6 && (inp->inp_flags & IN6P_CONTROLOPTS || - inp->inp_socket->so_options & SO_TIMESTAMP)) + so->so_options & SO_TIMESTAMP)) ip6_savecontrol(inp, m, &opts); #endif /* INET6 */ if (ip && (inp->inp_flags & INP_CONTROLOPTS || - inp->inp_socket->so_options & SO_TIMESTAMP)) + so->so_options & SO_TIMESTAMP)) ip_savecontrol(inp, &opts, ip, m); #ifdef INET6 if (ip6 && (inp->inp_flags & IN6P_RECVDSTPORT)) { @@ -634,34 +623,14 @@ udp_input(struct mbuf **mp, int *offp, i sizeof(u_int32_t), IP_IPSECFLOWINFO, IPPROTO_IP); } #endif -#ifdef PIPEX - if (pipex_enable && inp->inp_pipex) { - struct pipex_session *session; - int off = iphlen + sizeof(struct udphdr); - if ((session = pipex_l2tp_lookup_session(m, off)) != NULL) { - if ((m = *mp = pipex_l2tp_input(m, off, session, - ipsecflowinfo)) == NULL) { - m_freem(opts); - /* the packet is handled by PIPEX */ - return IPPROTO_DONE; - } - } - } -#endif - - iphlen += sizeof(struct udphdr); - m_adj(m, iphlen); - if (sbappendaddr(inp->inp_socket, &inp->inp_socket->so_rcv, &srcsa.sa, - m, opts) == 0) { + m_adj(m, iphlen + sizeof(struct udphdr)); + if (sbappendaddr(so, &so->so_rcv, srcaddr, m, opts) == 0) { udpstat_inc(udps_fullsock); - goto bad; + m_freem(m); + m_freem(opts); + return; } - sorwakeup(inp->inp_socket); - return IPPROTO_DONE; -bad: - m_freem(m); - m_freem(opts); - return IPPROTO_DONE; + sorwakeup(so); } /*