diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c index bc09d6037..2b8692c 100644 --- a/sys/netinet/udp_usrreq.c +++ b/sys/netinet/udp_usrreq.c @@ -767,12 +767,16 @@ end: int -udp_output(struct mbuf *m, struct inpcb *inp) +udp_output(struct mbuf *m, struct inpcb *inp, struct mbuf *control, + struct lwp *l) { struct udpiphdr *ui; struct route *ro; + struct ip_moptions *imop, imo; + struct sockaddr_in laddr; int len = m->m_pkthdr.len; int error = 0; + int flags = 0; MCLAIM(m, &udp_tx_mowner); @@ -796,12 +800,72 @@ udp_output(struct mbuf *m, struct inpcb *inp) } /* + * Source address would be taken from inpcb, + * but IP_PKTINFO can override it. + */ + imop = inp->inp_moptions; + sockaddr_in_init(&laddr, &inp->inp_laddr, 0); + if (control != NULL) { + struct inpcb *xinp; + struct cmsghdr *cm; + struct in_pktinfo *pktinfo; + + /* + * XXX: Currently, we assume all the optional information is + * stored in a single mbuf. + */ + if (control->m_next) { + error = EINVAL; + goto release; + } + + for (; control->m_len > 0; + control->m_data += CMSG_ALIGN(cm->cmsg_len), + control->m_len -= CMSG_ALIGN(cm->cmsg_len)) { + cm = mtod(control, struct cmsghdr *); + if ((control->m_len < sizeof(*cm)) || + (cm->cmsg_len == 0) || + (cm->cmsg_len > control->m_len)) { + error = EINVAL; + goto release; + } + if (cm->cmsg_level != IPPROTO_IP) + continue; + + switch (cm->cmsg_type) { + case IP_PKTINFO: + if (cm->cmsg_len != + CMSG_LEN(sizeof(struct in_pktinfo))) { + error = EINVAL; + goto release; + } + pktinfo = (struct in_pktinfo *)CMSG_DATA(cm); + error = in_pktinfo_prepare(pktinfo, &imop, &imo, + &laddr, &flags, l); + if (error != 0) + goto release; + + /* Checking laddr:port already in use? */ + xinp = in_pcblookup_bind(&udbtable, + laddr.sin_addr, inp->inp_lport); + if ((xinp != NULL) && (xinp != inp)) { + error = EADDRINUSE; + goto release; + } + break; + } + } + m_freem(control); + control = NULL; + } + + /* * Fill in mbuf with extended UDP header * and addresses and length put into network format. */ ui = mtod(m, struct udpiphdr *); ui->ui_pr = IPPROTO_UDP; - ui->ui_src = inp->inp_laddr; + ui->ui_src = laddr.sin_addr; ui->ui_dst = inp->inp_faddr; ui->ui_sport = inp->inp_lport; ui->ui_dport = inp->inp_fport; @@ -829,11 +893,12 @@ udp_output(struct mbuf *m, struct inpcb *inp) ((struct ip *)ui)->ip_tos = inp->inp_ip.ip_tos; /* XXX */ UDP_STATINC(UDP_STAT_OPACKETS); - return (ip_output(m, inp->inp_options, ro, - inp->inp_socket->so_options & (SO_DONTROUTE | SO_BROADCAST), - inp->inp_moptions, inp)); + flags |= inp->inp_socket->so_options & (SO_DONTROUTE|SO_BROADCAST); + return ip_output(m, inp->inp_options, ro, flags, imop, inp); release: + if (control != NULL) + m_freem(control); m_freem(m); return (error); } @@ -1067,12 +1132,6 @@ udp_send(struct socket *so, struct mbuf *m, struct sockaddr *nam, KASSERT(inp != NULL); KASSERT(m != NULL); - if (control && control->m_len) { - m_freem(control); - m_freem(m); - return EINVAL; - } - memset(&laddr, 0, sizeof laddr); s = splsoftnet(); @@ -1091,16 +1150,19 @@ udp_send(struct socket *so, struct mbuf *m, struct sockaddr *nam, goto die; } } - error = udp_output(m, inp); + error = udp_output(m, inp, control, l); m = NULL; + control = NULL; if (nam) { in_pcbdisconnect(inp); inp->inp_laddr = laddr; /* XXX */ in_pcbstate(inp, INP_BOUND); /* XXX */ } die: - if (m) + if (m != NULL) m_freem(m); + if (control != NULL) + m_freem(control); splx(s); return error; diff --git a/sys/netinet/udp_var.h b/sys/netinet/udp_var.h index c446fdd..3763682 100644 --- a/sys/netinet/udp_var.h +++ b/sys/netinet/udp_var.h @@ -96,7 +96,7 @@ int udp_ctloutput(int, struct socket *, struct sockopt *); void udp_init(void); void udp_init_common(void); void udp_input(struct mbuf *, ...); -int udp_output(struct mbuf *, struct inpcb *); +int udp_output(struct mbuf *, struct inpcb *, struct mbuf *, struct lwp *); int udp_sysctl(int *, u_int, void *, size_t *, void *, size_t); int udp_input_checksum(int af, struct mbuf *, const struct udphdr *, int, diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c index 35919c0..faa29b1 100644 --- a/sys/netinet/raw_ip.c +++ b/sys/netinet/raw_ip.c @@ -303,41 +303,98 @@ rip_ctlinput(int cmd, const struct sockaddr *sa, void *v) * Tack on options user may have setup with control call. */ int -rip_output(struct mbuf *m, struct inpcb *inp) +rip_output(struct mbuf *m, struct inpcb *inp, struct mbuf *control, + struct lwp *l) { struct ip *ip; struct mbuf *opts; + struct ip_moptions *imop, imo; + struct sockaddr_in laddr; int flags; + int error = 0; flags = (inp->inp_socket->so_options & SO_DONTROUTE) | IP_ALLOWBROADCAST | IP_RETURNMTU; /* + * Source address would be taken from inpcb, + * but IP_PKTINFO can override it. + */ + imop = inp->inp_moptions; + sockaddr_in_init(&laddr, &inp->inp_laddr, 0); + if (control != NULL) { + struct cmsghdr *cm; + struct in_pktinfo *pktinfo; + + /* + * XXX: Currently, we assume all the optional information is + * stored in a single mbuf. + */ + if (control->m_next) { + error = EINVAL; + goto release; + } + + for (; control->m_len > 0; + control->m_data += CMSG_ALIGN(cm->cmsg_len), + control->m_len -= CMSG_ALIGN(cm->cmsg_len)) { + cm = mtod(control, struct cmsghdr *); + if ((control->m_len < sizeof(*cm)) || + (cm->cmsg_len == 0) || + (cm->cmsg_len > control->m_len)) { + error = EINVAL; + goto release; + } + if (cm->cmsg_level != IPPROTO_IP) + continue; + + switch (cm->cmsg_type) { + case IP_PKTINFO: + if (cm->cmsg_len != + CMSG_LEN(sizeof(struct in_pktinfo))) { + error = EINVAL; + goto release; + } + pktinfo = (struct in_pktinfo *)CMSG_DATA(cm); + error = in_pktinfo_prepare(pktinfo, &imop, &imo, + &laddr, &flags, l); + if (error != 0) + goto release; + break; + } + } + m_freem(control); + control = NULL; + } + + /* * If the user handed us a complete IP packet, use it. * Otherwise, allocate an mbuf for a header and fill it in. */ if ((inp->inp_flags & INP_HDRINCL) == 0) { if ((m->m_pkthdr.len + sizeof(struct ip)) > IP_MAXPACKET) { - m_freem(m); - return (EMSGSIZE); + error = EMSGSIZE; + goto release; } M_PREPEND(m, sizeof(struct ip), M_DONTWAIT); - if (!m) - return (ENOBUFS); + if (!m) { + error = ENOBUFS; + goto release; + } ip = mtod(m, struct ip *); ip->ip_tos = 0; ip->ip_off = htons(0); ip->ip_p = inp->inp_ip.ip_p; ip->ip_len = htons(m->m_pkthdr.len); - ip->ip_src = inp->inp_laddr; + ip->ip_src = laddr.sin_addr; ip->ip_dst = inp->inp_faddr; ip->ip_ttl = MAXTTL; opts = inp->inp_options; } else { if (m->m_pkthdr.len > IP_MAXPACKET) { - m_freem(m); - return (EMSGSIZE); + error = EMSGSIZE; + goto release; } ip = mtod(m, struct ip *); @@ -350,15 +407,17 @@ rip_output(struct mbuf *m, struct inpcb *inp) int hlen = ip->ip_hl << 2; m = m_copyup(m, hlen, (max_linkhdr + 3) & ~3); - if (m == NULL) - return (ENOMEM); /* XXX */ + if (m == NULL) { + error = ENOMEM; /* XXX */ + goto release; + } ip = mtod(m, struct ip *); } /* XXX userland passes ip_len and ip_off in host order */ if (m->m_pkthdr.len != ip->ip_len) { - m_freem(m); - return (EINVAL); + error = EINVAL; + goto release; } HTONS(ip->ip_len); HTONS(ip->ip_off); @@ -374,8 +433,14 @@ rip_output(struct mbuf *m, struct inpcb *inp) * IP output. Note: if IP_RETURNMTU flag is set, the MTU size * will be stored in inp_errormtu. */ - return ip_output(m, opts, &inp->inp_route, flags, inp->inp_moptions, - inp); + return ip_output(m, opts, &inp->inp_route, flags, imop, inp); + + release: + if (control != NULL) + m_freem(control); + if (m != NULL) + m_freem(m); + return error; } /* @@ -747,12 +812,6 @@ rip_send(struct socket *so, struct mbuf *m, struct sockaddr *nam, * Ship a packet out. The appropriate raw output * routine handles any massaging necessary. */ - if (control && control->m_len) { - m_freem(control); - m_freem(m); - return EINVAL; - } - s = splsoftnet(); if (nam) { if ((so->so_state & SS_ISCONNECTED) != 0) { @@ -760,21 +819,24 @@ rip_send(struct socket *so, struct mbuf *m, struct sockaddr *nam, goto die; } error = rip_connect_pcb(inp, (struct sockaddr_in *)nam); - if (error) { - die: - m_freem(m); - splx(s); - return error; - } + if (error) + goto die; } else { if ((so->so_state & SS_ISCONNECTED) == 0) { error = ENOTCONN; goto die; } } - error = rip_output(m, inp); + error = rip_output(m, inp, control, l); + m = NULL; + control = NULL; if (nam) rip_disconnect1(inp); + die: + if (m != NULL) + m_freem(m); + if (control != NULL) + m_freem(control); splx(s); return error; diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index db68efb..2b9107c 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -329,8 +329,9 @@ ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro, int flags, mtu = ifp->if_mtu; ip->ip_ttl = 1; isbroadcast = in_broadcast(dst->sin_addr, ifp); - } else if ((IN_MULTICAST(ip->ip_dst.s_addr) || - ip->ip_dst.s_addr == INADDR_BROADCAST) && + } else if (((IN_MULTICAST(ip->ip_dst.s_addr) || + ip->ip_dst.s_addr == INADDR_BROADCAST) || + (flags & IP_ROUTETOIFINDEX)) && imo != NULL && imo->imo_multicast_if_index != 0) { ifp = mifp = if_get_byindex(imo->imo_multicast_if_index, &psref); if (ifp == NULL) { @@ -344,7 +345,31 @@ ip_output(struct mbuf *m0, struct mbuf *opt, struct route *ro, int flags, error = EADDRNOTAVAIL; goto bad; } - isbroadcast = 0; + if (IN_MULTICAST(ip->ip_dst.s_addr) || + ip->ip_dst.s_addr == INADDR_BROADCAST) { + isbroadcast = 0; + } else { + /* IP_ROUTETOIFINDEX */ + isbroadcast = in_broadcast(dst->sin_addr, ifp); + if ((isbroadcast == 0) && ((ifp->if_flags & + (IFF_LOOPBACK | IFF_POINTOPOINT)) == 0) && + (in_direct(dst->sin_addr, ifp) == 0)) { + /* gateway address required */ + if (rt == NULL) + rt = rtcache_init(ro); + if (rt == NULL || rt->rt_ifp != ifp) { + IP_STATINC(IP_STAT_NOROUTE); + error = EHOSTUNREACH; + goto bad; + } + rt->rt_use++; + if (rt->rt_flags & RTF_GATEWAY) + dst = satosin(rt->rt_gateway); + if (rt->rt_flags & RTF_HOST) + isbroadcast = + rt->rt_flags & RTF_BROADCAST; + } + } } else { if (rt == NULL) rt = rtcache_init(ro); diff --git a/sys/netinet/ip_var.h b/sys/netinet/ip_var.h index 058c81d..7e7c838 100644 --- a/sys/netinet/ip_var.h +++ b/sys/netinet/ip_var.h @@ -182,6 +182,7 @@ __CTASSERT(SO_BROADCAST == 0x0020); #define IP_IGMP_MCAST 0x0040 /* IGMP for mcast join/leave */ #define IP_MTUDISC 0x0400 /* Path MTU Discovery; set DF */ +#define IP_ROUTETOIFINDEX 0x0800 /* force route imo_multicast_if_index */ extern struct domain inetdomain; extern const struct pr_usrreqs rip_usrreqs; @@ -233,7 +234,7 @@ void * rip_ctlinput(int, const struct sockaddr *, void *); int rip_ctloutput(int, struct socket *, struct sockopt *); void rip_init(void); void rip_input(struct mbuf *, ...); -int rip_output(struct mbuf *, struct inpcb *); +int rip_output(struct mbuf *, struct inpcb *, struct mbuf *, struct lwp *); int rip_usrreq(struct socket *, int, struct mbuf *, struct mbuf *, struct mbuf *, struct lwp *); diff --git a/sys/netinet/in.c b/sys/netinet/in.c index 9d27daf..5e13574 100644 --- a/sys/netinet/in.c +++ b/sys/netinet/in.c @@ -258,6 +258,43 @@ in_localaddr(struct in_addr in) } /* + * like in_localaddr() but can specify ifp. + */ +int +in_direct(struct in_addr in, struct ifnet *ifp) +{ + struct ifaddr *ifa; + int localaddr = 0; + int s; + + KASSERT(ifp != NULL); + +#define ia (ifatoia(ifa)) + s = pserialize_read_enter(); + if (subnetsarelocal) { + IFADDR_READER_FOREACH(ifa, ifp) { + if (ifa->ifa_addr->sa_family == AF_INET && + ((in.s_addr & ia->ia_netmask) == ia->ia_net)) { + localaddr = 1; + break; + } + } + } else { + IFADDR_READER_FOREACH(ifa, ifp) { + if (ifa->ifa_addr->sa_family == AF_INET && + (in.s_addr & ia->ia_subnetmask) == ia->ia_subnet) { + localaddr = 1; + break; + } + } + } + pserialize_read_exit(s); + + return localaddr; +#undef ia +} + +/* * Determine whether an IP address is in a reserved set of addresses * that may not be forwarded, or whether datagrams to that destination * may be forwarded. @@ -1713,6 +1750,50 @@ in_multi_lock_held(void) return rw_lock_held(&in_multilock); } +int +in_pktinfo_prepare(const struct in_pktinfo *pktinfo, struct ip_moptions **imop, + struct ip_moptions *imo, struct sockaddr_in *laddr, + int *flags, struct lwp *l) +{ + int error = 0; + + if (pktinfo->ipi_ifindex != 0) { + struct ifnet *ifp; + struct in_ifaddr *ia; + int s; + + s = pserialize_read_enter(); + ifp = if_byindex(pktinfo->ipi_ifindex); + if (ifp == NULL) { + pserialize_read_exit(s); + return EADDRNOTAVAIL; + } + ia = in_get_ia_from_ifp(ifp); + if (ia == NULL) { + pserialize_read_exit(s); + return EADDRNOTAVAIL; + } + laddr->sin_addr = IA_SIN(ia)->sin_addr; + pserialize_read_exit(s); + + if (*imop != NULL) { + memcpy(imo, *imop, sizeof(*imo)); + } else { + memset(imo, 0, sizeof(*imo)); + imo->imo_multicast_ttl = IP_DEFAULT_MULTICAST_TTL; + imo->imo_multicast_loop = IP_DEFAULT_MULTICAST_LOOP; + } + imo->imo_multicast_if_index = pktinfo->ipi_ifindex; + *imop = imo; + *flags |= IP_ROUTETOIFINDEX; + } else { + laddr->sin_addr = pktinfo->ipi_addr; + /* EADDRNOTAVAIL? */ + error = in_pcbbindableaddr(laddr, l->l_cred); + } + return error; +} + struct in_ifaddr * in_selectsrc(struct sockaddr_in *sin, struct route *ro, int soopts, struct ip_moptions *mopts, int *errorp, struct psref *psref) diff --git a/sys/netinet/in.h b/sys/netinet/in.h index c92f378..b922345 100644 --- a/sys/netinet/in.h +++ b/sys/netinet/in.h @@ -562,6 +562,7 @@ extern u_char ip_protox[]; extern const struct sockaddr_in in_any; int in_broadcast(struct in_addr, struct ifnet *); +int in_direct(struct in_addr, struct ifnet *); int in_canforward(struct in_addr); int cpu_in_cksum(struct mbuf *, int, int, uint32_t); int in_cksum(struct mbuf *, int); @@ -581,6 +582,8 @@ struct ip_moptions; struct in_ifaddr *in_selectsrc(struct sockaddr_in *, struct route *, int, struct ip_moptions *, int *, struct psref *); +int in_pktinfo_prepare(const struct in_pktinfo *, struct ip_moptions **, + struct ip_moptions *, struct sockaddr_in *, int *, struct lwp *); #define in_hosteq(s,t) ((s).s_addr == (t).s_addr) #define in_nullhost(x) ((x).s_addr == INADDR_ANY) diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c index a1c3a7f..bfb2426 100644 --- a/sys/netinet/in_pcb.c +++ b/sys/netinet/in_pcb.c @@ -270,8 +270,8 @@ in_pcbsetport(struct sockaddr_in *sin, struct inpcb *inp, kauth_cred_t cred) return (0); } -static int -in_pcbbind_addr(struct inpcb *inp, struct sockaddr_in *sin, kauth_cred_t cred) +int +in_pcbbindableaddr(struct sockaddr_in *sin, kauth_cred_t cred) { int error = EADDRNOTAVAIL; struct ifaddr *ifa = NULL; @@ -298,13 +298,20 @@ in_pcbbind_addr(struct inpcb *inp, struct sockaddr_in *sin, kauth_cred_t cred) if (ia->ia4_flags & IN_IFF_DUPLICATED) goto error; } + error = 0; + error: pserialize_read_exit(s); + return error; +} - inp->inp_laddr = sin->sin_addr; +static int +in_pcbbind_addr(struct inpcb *inp, struct sockaddr_in *sin, kauth_cred_t cred) +{ + int error; - return (0); -error: - pserialize_read_exit(s); + error = in_pcbbindableaddr(sin, cred); + if (error == 0) + inp->inp_laddr = sin->sin_addr; return error; } diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h index d565c52..2ff0b6a 100644 --- a/sys/netinet/in_pcb.h +++ b/sys/netinet/in_pcb.h @@ -135,6 +135,7 @@ struct inpcb { #ifdef _KERNEL void in_losing(struct inpcb *); int in_pcballoc(struct socket *, void *); +int in_pcbbindableaddr(struct sockaddr_in *, kauth_cred_t); int in_pcbbind(void *, struct sockaddr_in *, struct lwp *); int in_pcbconnect(void *, struct sockaddr_in *, struct lwp *); void in_pcbdetach(void *); diff --git a/tests/net/net/Makefile b/tests/net/net/Makefile index 8c2da67..524e01b 100644 --- a/tests/net/net/Makefile +++ b/tests/net/net/Makefile @@ -10,6 +10,7 @@ TESTS_C+= t_tcp TESTS_C+= t_udp TESTS_C+= t_pktinfo .if (${MKRUMP} != "no") && !defined(BSD_MK_COMPAT_FILE) +TESTS_C+= t_pktinfo_send TESTS_C+= t_raw .for name in forwarding ipaddress ipv6address ipv6_lifetime mtudisc mtudisc6 \ @@ -19,6 +20,8 @@ TESTS_SH_SRC_t_${name}= ../net_common.sh t_${name}.sh .endfor .endif +LDADD.t_pktinfo_send+= -lrumpnet_local -lrumpnet_netinet -lrumpnet_net -lrumpdev -lrumpnet_shmif +LDADD.t_pktinfo_send+= -lrumpnet -lrumpvfs -lrump -lrumpuser -lrump -lpthread LDADD.t_raw+= -lrumpnet_local -lrumpnet_netinet -lrumpnet_net -lrumpdev LDADD.t_raw+= -lrumpnet -lrumpvfs -lrump -lrumpuser -lrump -lpthread diff --git a/tests/net/net/t_pktinfo_send.c b/tests/net/net/t_pktinfo_send.c new file mode 100644 index 0000000..4b31047 --- /dev/null +++ b/tests/net/net/t_pktinfo_send.c @@ -0,0 +1,782 @@ +/* $NetBSD$ */ + +/*- + * Copyright (c) 2017 Internet Initiative Japan Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include +__RCSID("$NetBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "h_macros.h" +#include "../config/netconfig.c" + +#include + + +#define SERVERPORT 54321 +#define CLIENTPORT 12345 + + +char message[128] = "Hello IP_PKTINFO"; + +static void +setup_test_environment(void) +{ + RZ(rump_init()); + netcfg_rump_if("lo0", "127.0.0.2", "255.0.0.0"); + netcfg_rump_if("lo0", "127.0.0.3", "255.0.0.0"); + netcfg_rump_if("lo0", "127.0.0.4", "255.0.0.0"); + netcfg_rump_if("lo0", "127.0.0.5", "255.0.0.0"); +} + +static void +sock_in_init(struct sockaddr_in *sin, const char *addr, in_port_t port) +{ + memset(sin, 0, sizeof(struct sockaddr_in)); + + sin->sin_family = AF_INET; + sin->sin_port = htons(port); + inet_pton(AF_INET, addr, &sin->sin_addr); +} + +static int +sock_bind(int sock, const char *addr, in_port_t port) +{ + struct sockaddr_in bindaddr; + + sock_in_init(&bindaddr, addr, port); + return rump_sys_bind(sock, + (struct sockaddr *)&bindaddr, sizeof(bindaddr)); +} + +static int +udp_server(const char *addr, in_port_t port) +{ + int s, rv; + + RL(s = rump_sys_socket(AF_INET, SOCK_DGRAM, 0)); + RL(rv = sock_bind(s, addr, port)); + + return s; +} + +static int +addrcmp(struct sockaddr_in *sin, const char *addr) +{ + struct in_addr inaddr; + inet_pton(AF_INET, addr, &inaddr); + return memcmp(&inaddr, &sin->sin_addr, sizeof(inaddr)); +} + + +static ssize_t +sendto_pktinfo(int s, const void *buf, size_t len, int flags, + const char *src, const char *dst, in_port_t dstport) +{ + /* for sendmsg */ + struct sockaddr_in to; + struct msghdr msg; + char cmsgbuf[CMSG_SPACE(sizeof(struct in_pktinfo)) * 2]; + struct iovec vec; + + /* for store to cmsghdr */ + struct cmsghdr *cmsg; + + /* for pktinfo */ + struct in_pktinfo *pi; + struct in_addr addr; + + /* setup msghdr */ + sock_in_init(&to, dst, dstport); + + vec.iov_base = __UNCONST(buf); + vec.iov_len = len; + memset(&msg, 0, sizeof(msg)); + msg.msg_iov = &vec; + msg.msg_iovlen = 1; + msg.msg_name = (caddr_t)&to; + msg.msg_namelen = sizeof(to); + msg.msg_control = cmsgbuf; + msg.msg_controllen = 0; + cmsg = (struct cmsghdr *)cmsgbuf; + + /* setup ip_pktinfo */ + msg.msg_controllen += CMSG_SPACE(sizeof(struct in_pktinfo)); + cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); + cmsg->cmsg_level = IPPROTO_IP; + cmsg->cmsg_type = IP_PKTINFO; + + pi = (struct in_pktinfo *)CMSG_DATA(cmsg); + memset(pi, 0, sizeof(*pi)); + + /* treat 0.x.x.x/8 as interface index (like RFC1724 ss.3.3) */ + inet_pton(AF_INET, src, &addr); + if (ntohl(addr.s_addr) >> 24 == 0) + pi->ipi_ifindex = ntohl(addr.s_addr) & 0xffffff; + else { + pi->ipi_addr = addr; + } + + if (msg.msg_controllen == 0) + msg.msg_control = NULL; + + return rump_sys_sendmsg(s, &msg, flags); +} + +static void +try_sendmsg_pktinfo(int client, int server, const char *data, size_t datalen, + const char *src, const char *dst, in_port_t dstport) +{ + struct sockaddr_in from; + socklen_t fromlen; + int rv; + char buf[sizeof(message) * 2]; + + RL(rv = sendto_pktinfo(client, data, datalen, 0, + src, dst, dstport)); + + fromlen = sizeof(from); + RL(rv = rump_sys_recvfrom(server, buf, sizeof(buf), 0, + (struct sockaddr *)&from, &fromlen)); + + ATF_REQUIRE_MSG(addrcmp(&from, src) == 0, + "source address of received packet is %s, must be %s", + inet_ntoa(from.sin_addr), src); +} + +static void +do_send_pktinfo_tests(int client, int server, const char *data, size_t datalen) +{ + struct sockaddr_in sa_before, sa_after; + socklen_t sa_beforelen, sa_afterlen; + int rv; + char ipbuf1[sizeof("255.255.255.255")]; + char ipbuf2[sizeof("255.255.255.255")]; + + /* get sockaddr before sendmsg w/IP_PKTINFO */ + sa_beforelen = sizeof(sa_before); + RL(rv = rump_sys_getsockname(client, + (struct sockaddr *)&sa_before, &sa_beforelen)); + + /* + * sendmsg with IP_PKTINFO: 127.0.0.[2345] -> 127.0.0.1:54321, and + * check received packet is from 127.0.0.[2345] + */ + try_sendmsg_pktinfo(client, server, data, datalen, + "127.0.0.2", "127.0.0.1", SERVERPORT); + try_sendmsg_pktinfo(client, server, data, datalen, + "127.0.0.3", "127.0.0.1", SERVERPORT); + try_sendmsg_pktinfo(client, server, data, datalen, + "127.0.0.4", "127.0.0.1", SERVERPORT); + try_sendmsg_pktinfo(client, server, data, datalen, + "127.0.0.5", "127.0.0.1", SERVERPORT); + + /* get sockaddr after sendmsg w/IP_PKTINFO */ + sa_afterlen = sizeof(sa_after); + RL(rv = rump_sys_getsockname(client, + (struct sockaddr *)&sa_after, &sa_afterlen)); + + /* confirm sockaddr is not changed */ + inet_ntop(AF_INET, &sa_before.sin_addr, ipbuf1, sizeof(ipbuf1)); + inet_ntop(AF_INET, &sa_after.sin_addr, ipbuf2, sizeof(ipbuf2)); + ATF_REQUIRE_MSG(sa_before.sin_addr.s_addr == sa_after.sin_addr.s_addr, + "sockaddr is different from before send. before=%s, after=%s", + ipbuf1, ipbuf2); +} + +ATF_TC(pktinfo_send_unbound); +ATF_TC_HEAD(pktinfo_send_unbound, tc) +{ + atf_tc_set_md_var(tc, "descr", "sendmsg with IP_PKTINFO"); + atf_tc_set_md_var(tc, "timeout", "5"); +} +ATF_TC_BODY(pktinfo_send_unbound, tc) +{ + int client, server; + + setup_test_environment(); + + server = udp_server("127.0.0.1", SERVERPORT); + RL(client = rump_sys_socket(AF_INET, SOCK_DGRAM, 0)); + + /* do sendmsg w/IP_PKTINFO tests */ + do_send_pktinfo_tests(client, server, message, strlen(message)); + + rump_sys_close(client); + rump_sys_close(server); +} + + +ATF_TC(pktinfo_send_bindany); +ATF_TC_HEAD(pktinfo_send_bindany, tc) +{ + atf_tc_set_md_var(tc, "descr", + "sendmsg with IP_PKTINFO on bind(INADDR_ANY) socket"); + atf_tc_set_md_var(tc, "timeout", "5"); +} +ATF_TC_BODY(pktinfo_send_bindany, tc) +{ + int client, server, rv; + + setup_test_environment(); + + server = udp_server("127.0.0.1", SERVERPORT); + RL(client = rump_sys_socket(AF_INET, SOCK_DGRAM, 0)); + RL(rv = sock_bind(client, "0.0.0.0", 0)); + + /* do sendmsg w/IP_PKTINFO tests */ + do_send_pktinfo_tests(client, server, message, strlen(message)); + + rump_sys_close(client); + rump_sys_close(server); +} + + +ATF_TC(pktinfo_send_bindaddr); +ATF_TC_HEAD(pktinfo_send_bindaddr, tc) +{ + atf_tc_set_md_var(tc, "descr", + "sendmsg with IP_PKTINFO on bind(addr:0) socket"); + atf_tc_set_md_var(tc, "timeout", "5"); +} +ATF_TC_BODY(pktinfo_send_bindaddr, tc) +{ + int client, server, rv; + + setup_test_environment(); + + server = udp_server("127.0.0.1", SERVERPORT); + RL(client = rump_sys_socket(AF_INET, SOCK_DGRAM, 0)); + RL(rv = sock_bind(client, "127.0.0.1", 0)); + + /* do sendmsg w/IP_PKTINFO tests */ + do_send_pktinfo_tests(client, server, message, strlen(message)); + + rump_sys_close(client); + rump_sys_close(server); +} + + +ATF_TC(pktinfo_send_bindport); +ATF_TC_HEAD(pktinfo_send_bindport, tc) +{ + atf_tc_set_md_var(tc, "descr", + "sendmsg with IP_PKTINFO on bind(INADDR_ANY:12345) socket"); + atf_tc_set_md_var(tc, "timeout", "5"); +} +ATF_TC_BODY(pktinfo_send_bindport, tc) +{ + int client, server, rv; + + setup_test_environment(); + + server = udp_server("127.0.0.1", SERVERPORT); + RL(client = rump_sys_socket(AF_INET, SOCK_DGRAM, 0)); + RL(rv = sock_bind(client, "0.0.0.0", CLIENTPORT)); + + /* do sendmsg w/IP_PKTINFO tests */ + do_send_pktinfo_tests(client, server, message, strlen(message)); + + rump_sys_close(client); + rump_sys_close(server); +} + + +ATF_TC(pktinfo_send_bindaddrport); +ATF_TC_HEAD(pktinfo_send_bindaddrport, tc) +{ + atf_tc_set_md_var(tc, "descr", + "sendmsg with IP_PKTINFO on bind(addr:12345) socket"); + atf_tc_set_md_var(tc, "timeout", "5"); +} +ATF_TC_BODY(pktinfo_send_bindaddrport, tc) +{ + int client, server, rv; + + setup_test_environment(); + + server = udp_server("127.0.0.1", SERVERPORT); + RL(client = rump_sys_socket(AF_INET, SOCK_DGRAM, 0)); + RL(rv = sock_bind(client, "127.0.0.2", CLIENTPORT)); + + /* do sendmsg w/IP_PKTINFO tests */ + do_send_pktinfo_tests(client, server, message, strlen(message)); + + rump_sys_close(client); + rump_sys_close(server); +} + + +ATF_TC(pktinfo_send_bindother); +ATF_TC_HEAD(pktinfo_send_bindother, tc) +{ + atf_tc_set_md_var(tc, "descr", + "sendmsg with IP_PKTINFO from address bound by other socket"); + atf_tc_set_md_var(tc, "timeout", "5"); +} +ATF_TC_BODY(pktinfo_send_bindother, tc) +{ + int client, server, other, rv; + + setup_test_environment(); + + server = udp_server("127.0.0.1", SERVERPORT); + other = udp_server("127.0.0.2", CLIENTPORT); + RL(client = rump_sys_socket(AF_INET, SOCK_DGRAM, 0)); + RL(rv = sock_bind(client, "127.0.0.3", CLIENTPORT)); + + /* + * other socket is bound "127.0.0.2:12345". + * client socket is bound "127.0.0.3:12345". + * client socket sendto w/IP_PKTINFO "127.0.0.2", + * this should be error as EADDRINUSE. + */ + rv = sendto_pktinfo(client, message, strlen(message), 0, + "127.0.0.2", "127.0.0.1", SERVERPORT); + + ATF_REQUIRE_MSG(rv == -1, + "sendmsg with in-use address:port should be error," + " but success"); + ATF_REQUIRE_MSG(errno == EADDRINUSE, + "sendmsg with in-use address:port should be EADDRINUSE," + " but got %s", strerror(errno)); + + + rump_sys_close(client); + rump_sys_close(server); + rump_sys_close(other); +} + + +ATF_TC(pktinfo_send_connected); +ATF_TC_HEAD(pktinfo_send_connected, tc) +{ + atf_tc_set_md_var(tc, "descr", + "sendmsg with IP_PKTINFO on connected socket"); + atf_tc_set_md_var(tc, "timeout", "5"); +} +ATF_TC_BODY(pktinfo_send_connected, tc) +{ + struct sockaddr_in connectaddr; + int client, server, rv; + + setup_test_environment(); + + server = udp_server("127.0.0.1", SERVERPORT); + RL(client = rump_sys_socket(AF_INET, SOCK_DGRAM, 0)); + + sock_in_init(&connectaddr, "127.0.0.1", SERVERPORT); + RL(rv = rump_sys_connect(client, + (struct sockaddr *)&connectaddr, sizeof(connectaddr))); + + /* sendmsg w/IP_PKTINFO on connected socket should be error */ + rv = sendto_pktinfo(client, message, strlen(message), 0, + "127.0.0.2", "127.0.0.1", SERVERPORT); + + ATF_REQUIRE_MSG(rv == -1, + "sendmsg w/IP_PKTINFO on connected socket should be error," + " but success"); + ATF_REQUIRE_MSG(errno == EISCONN, + "sendmsg with in-use address:port should be EISCONN," + " but got %s", strerror(errno)); + + + rump_sys_close(client); + rump_sys_close(server); +} + + +ATF_TC(pktinfo_send_notown); +ATF_TC_HEAD(pktinfo_send_notown, tc) +{ + atf_tc_set_md_var(tc, "descr", + "sendmsg with IP_PKTINFO from no-own address"); + atf_tc_set_md_var(tc, "timeout", "5"); +} +ATF_TC_BODY(pktinfo_send_notown, tc) +{ + int client, server, rv; + + setup_test_environment(); + + server = udp_server("127.0.0.1", SERVERPORT); + RL(client = rump_sys_socket(AF_INET, SOCK_DGRAM, 0)); + + /* sendmsg w/IP_PKTINFO from 127.0.0.100 (not own) should be error */ + rv = sendto_pktinfo(client, message, strlen(message), 0, + "127.0.0.100", "127.0.0.1", SERVERPORT); + + ATF_REQUIRE_MSG(rv == -1, + "sendmsg w/IP_PKTINFO from unavailable address" + " should be error, but success"); + ATF_REQUIRE_MSG(errno == EADDRNOTAVAIL, + "sendmsg with in-use address:port" + " should be EADDRNOTAVAIL, but got %s", strerror(errno)); + + + rump_sys_close(client); + rump_sys_close(server); +} + + +ATF_TC(pktinfo_send_notown_bind); +ATF_TC_HEAD(pktinfo_send_notown_bind, tc) +{ + atf_tc_set_md_var(tc, "descr", + "sendmsg with IP_PKTINFO from no-own address on bind socket"); + atf_tc_set_md_var(tc, "timeout", "5"); +} +ATF_TC_BODY(pktinfo_send_notown_bind, tc) +{ + int client, server, rv; + + setup_test_environment(); + + server = udp_server("127.0.0.1", SERVERPORT); + RL(client = rump_sys_socket(AF_INET, SOCK_DGRAM, 0)); + RL(rv = sock_bind(client, "127.0.0.2", CLIENTPORT)); + + /* sendmsg w/IP_PKTINFO from 127.0.0.100 (not own) should be error */ + rv = sendto_pktinfo(client, message, strlen(message), 0, + "127.0.0.100", "127.0.0.1", SERVERPORT); + + ATF_REQUIRE_MSG(rv == -1, + "sendmsg w/IP_PKTINFO from unavailable address should be error," + " but success"); + ATF_REQUIRE_MSG(errno == EADDRNOTAVAIL, + "sendmsg with in-use address:port should be EADDRNOTAVAIL," + " but got %s", strerror(errno)); + + + rump_sys_close(client); + rump_sys_close(server); +} + + +static u_int16_t +in_cksum(uint16_t *p, int len) +{ + u_int32_t sum; + + for (sum = 0; len >= 2; len -= 2) + sum += *p++; + if (len == 1) + sum += ntohs(*(uint8_t *)p * 256); + sum = (sum >> 16) + (sum & 0xffff); + sum = (sum >> 16) + (sum & 0xffff); + return ~sum; +} + +ATF_TC(pktinfo_send_rawip); +ATF_TC_HEAD(pktinfo_send_rawip, tc) +{ + atf_tc_set_md_var(tc, "descr", + "sendmsg raw-ip with IP_PKTINFO"); + atf_tc_set_md_var(tc, "timeout", "5"); +} +ATF_TC_BODY(pktinfo_send_rawip, tc) +{ + struct icmp icmp; + size_t icmplen; + int client, server; + + setup_test_environment(); + + RL(server = rump_sys_socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)); + RL(client = rump_sys_socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)); + + memset(&icmp, 0, sizeof(icmp)); + icmp.icmp_type = ICMP_ECHOREPLY; /* against confuse REQ with REPLY */ + icmp.icmp_id = htons(getpid()); + icmp.icmp_cksum = in_cksum((uint16_t *)&icmp, sizeof(icmp)); + icmplen = sizeof(icmp); + + /* sendmsg w/IP_PKTINFO from 127.0.0.2 */ + try_sendmsg_pktinfo(client, server, (const char *)&icmp, icmplen, + "127.0.0.2", "127.0.0.1", 0); + + rump_sys_close(client); + rump_sys_close(server); +} + + +ATF_TC(pktinfo_send_rawip_notown); +ATF_TC_HEAD(pktinfo_send_rawip_notown, tc) +{ + atf_tc_set_md_var(tc, "descr", + "sendmsg raw-ip with IP_PKTINFO from no-own address"); + atf_tc_set_md_var(tc, "timeout", "5"); +} +ATF_TC_BODY(pktinfo_send_rawip_notown, tc) +{ + struct icmp icmp; + size_t icmplen; + int client, rv; + + setup_test_environment(); + + RL(client = rump_sys_socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)); + + memset(&icmp, 0, sizeof(icmp)); + icmp.icmp_type = ICMP_ECHOREPLY; /* against confuse REQ with REPLY */ + icmp.icmp_id = htons(getpid()); + icmp.icmp_cksum = in_cksum((uint16_t *)&icmp, sizeof(icmp)); + icmplen = sizeof(icmp); + + /* sendmsg w/IP_PKTINFO from 127.0.0.100 (not own) should be error */ + rv = sendto_pktinfo(client, (const char *)&icmp, icmplen, 0, + "127.0.0.100", "127.0.0.1", 0); + + ATF_REQUIRE_MSG(rv == -1, + "sendmsg w/IP_PKTINFO from unavailable address" + " should be error, but success"); + ATF_REQUIRE_MSG(errno == EADDRNOTAVAIL, + "sendmsg with in-use address:port" + " should be EADDRNOTAVAIL, but got %s", strerror(errno)); + + rump_sys_close(client); +} + + +ATF_TC(pktinfo_send_ifindex); +ATF_TC_HEAD(pktinfo_send_ifindex, tc) +{ + atf_tc_set_md_var(tc, "descr", + "sendmsg with IP_PKTINFO to specified interface"); + atf_tc_set_md_var(tc, "timeout", "5"); +} +ATF_TC_BODY(pktinfo_send_ifindex, tc) +{ + pid_t child; + int channel[2], i; + char ifname2[IFNAMSIZ]; + char ifname3[IFNAMSIZ]; + char ethername[MAXPATHLEN]; + char token; + + snprintf(ethername, sizeof(ethername), + "t_pktinfo_send.link.%u", getpid()); + + RL(pipe(channel)); + + child = fork(); + + RZ(rump_init()); /* XXX: lo0 is ifindex 1 */ + netcfg_rump_makeshmif(ethername, ifname2); /* XXX: ifindex=2 */ + netcfg_rump_makeshmif(ethername, ifname3); /* XXX: ifindex=3 */ + + switch (child) { + case -1: + atf_tc_fail_errno("fork failed"); + case 0: + { + int client, rv; + + netcfg_rump_if(ifname2, "192.168.2.1", "255.255.255.0"); + netcfg_rump_if(ifname3, "192.168.0.1", "255.255.0.0"); + + RL(client = rump_sys_socket(AF_INET, SOCK_DGRAM, 0)); + + /* wait to ready */ + close(channel[1]); + ATF_CHECK(read(channel[0], &token, 1) == 1 && + token == 'U'); + close(channel[0]); + + /* few packets would be discarded while resolving arp */ + for (i = 0; i < 3; i++) { + /* send from ifindex 3 = 192.168.0.1 */ + snprintf(message, sizeof(message), "Hello PKTINFO %d", i); + + RL(rv = sendto_pktinfo(client, message, strlen(message), + 0, "0.0.0.3", "192.168.2.2", SERVERPORT)); + } + + rump_sys_close(client); + pause(); + } + break; + default: + { + struct sockaddr_in from; + socklen_t fromlen; + int server, rv; + char buf[sizeof(message)]; + + netcfg_rump_if(ifname2, "192.168.2.2", "255.255.255.0"); + netcfg_rump_if(ifname3, "192.168.0.2", "255.255.255.0"); + + server = udp_server("0.0.0.0", SERVERPORT); + + /* notify to child */ + close(channel[0]); + ATF_CHECK(write(channel[1], "U", 1) == 1); + close(channel[1]); + + memset(buf, 0, sizeof(buf)); + fromlen = sizeof(from); + RL(rv = rump_sys_recvfrom(server, buf, sizeof(buf), 0, + (struct sockaddr *)&from, &fromlen)); + printf("%s: received \"%s\" from %s:%u\n", __func__, + buf, + inet_ntoa(from.sin_addr), ntohs(from.sin_port)); + + ATF_REQUIRE_MSG(addrcmp(&from, "192.168.0.1") == 0, + "source address of received packet is %s," + " must be %s", + inet_ntoa(from.sin_addr), "192.168.0.1"); + + rump_sys_close(server); + kill(child, SIGKILL); + } + break; + } +} + + +ATF_TC(pktinfo_send_multicast); +ATF_TC_HEAD(pktinfo_send_multicast, tc) +{ + atf_tc_set_md_var(tc, "descr", + "sendmsg with IP_PKTINFO to multicast address" + " and specified interface"); + atf_tc_set_md_var(tc, "timeout", "5"); +} +ATF_TC_BODY(pktinfo_send_multicast, tc) +{ + pid_t child; + int channel[2]; + char ifname2[IFNAMSIZ]; + char ifname3[IFNAMSIZ]; + char ethername[MAXPATHLEN]; + char token; + + snprintf(ethername, sizeof(ethername), + "t_pktinfo_send.link.%u", getpid()); + + RL(pipe(channel)); + + child = fork(); + + RZ(rump_init()); /* XXX: lo0 is ifindex 1 */ + netcfg_rump_makeshmif(ethername, ifname2); /* XXX: ifindex=2 */ + netcfg_rump_makeshmif(ethername, ifname3); /* XXX: ifindex=3 */ + + switch (child) { + case -1: + atf_tc_fail_errno("fork failed"); + case 0: + { + int client, rv; + + netcfg_rump_if(ifname2, "192.168.2.1", "255.255.255.0"); + netcfg_rump_if(ifname3, "192.168.0.1", "255.255.0.0"); + + RL(client = rump_sys_socket(AF_INET, SOCK_DGRAM, 0)); + + /* wait to ready */ + close(channel[1]); + ATF_CHECK(read(channel[0], &token, 1) == 1 && + token == 'U'); + close(channel[0]); + + /* send from ifindex 2 = 192.168.2.1 */ + RL(rv = sendto_pktinfo(client, message, strlen(message), + 0, "0.0.0.2", "224.0.0.1", SERVERPORT)); + + /* send from ifindex 3 = 192.168.0.1 */ + RL(rv = sendto_pktinfo(client, message, strlen(message), + 0, "0.0.0.3", "224.0.0.1", SERVERPORT)); + + rump_sys_close(client); + pause(); + } + break; + default: + { + struct sockaddr_in from; + socklen_t fromlen; + int server, i, rv; + char buf[sizeof(message) * 2]; + + netcfg_rump_if(ifname2, "192.168.2.2", "255.255.255.0"); + netcfg_rump_if(ifname3, "192.168.0.2", "255.255.255.0"); + + server = udp_server("0.0.0.0", SERVERPORT); + + /* notify to child */ + close(channel[0]); + ATF_CHECK(write(channel[1], "U", 1) == 1); + close(channel[1]); + + for (i = 0; i < 2; i++) { + fromlen = sizeof(from); + RL(rv = rump_sys_recvfrom(server, buf, + sizeof(buf), 0, + (struct sockaddr *)&from, &fromlen)); + printf("%s: received from %s:%u\n", __func__, + inet_ntoa(from.sin_addr), + ntohs(from.sin_port)); + } + + rump_sys_close(server); + kill(child, SIGKILL); + } + break; + } +} + + +ATF_TP_ADD_TCS(tp) +{ + ATF_TP_ADD_TC(tp, pktinfo_send_unbound); + ATF_TP_ADD_TC(tp, pktinfo_send_bindany); + ATF_TP_ADD_TC(tp, pktinfo_send_bindaddr); + ATF_TP_ADD_TC(tp, pktinfo_send_bindport); + ATF_TP_ADD_TC(tp, pktinfo_send_bindaddrport); + ATF_TP_ADD_TC(tp, pktinfo_send_bindother); + ATF_TP_ADD_TC(tp, pktinfo_send_connected); + ATF_TP_ADD_TC(tp, pktinfo_send_notown); + ATF_TP_ADD_TC(tp, pktinfo_send_notown_bind); + ATF_TP_ADD_TC(tp, pktinfo_send_rawip); + ATF_TP_ADD_TC(tp, pktinfo_send_rawip_notown); + ATF_TP_ADD_TC(tp, pktinfo_send_ifindex); + ATF_TP_ADD_TC(tp, pktinfo_send_multicast); + + return atf_no_error(); +} diff --git a/distrib/sets/lists/debug/mi b/distrib/sets/lists/debug/mi index 0bc9de5..0c037b5 100644 --- a/distrib/sets/lists/debug/mi +++ b/distrib/sets/lists/debug/mi @@ -2280,6 +2280,7 @@ ./usr/libdata/debug/usr/tests/net/mcast/mcast.debug tests-net-debug debug,atf,rump ./usr/libdata/debug/usr/tests/net/mcast/t_mcast.debug tests-obsolete debug,atf,rump,obsolete ./usr/libdata/debug/usr/tests/net/net/t_pktinfo.debug tests-net-debug debug,atf,compattestfile +./usr/libdata/debug/usr/tests/net/net/t_pktinfo_test.debug tests-net-debug debug,atf,rump ./usr/libdata/debug/usr/tests/net/net/t_raw.debug tests-net-debug debug,atf,rump ./usr/libdata/debug/usr/tests/net/net/t_tcp.debug tests-net-debug debug,atf,compattestfile ./usr/libdata/debug/usr/tests/net/net/t_udp.debug tests-net-debug debug,atf,compattestfile diff --git a/distrib/sets/lists/tests/mi b/distrib/sets/lists/tests/mi index aa41e4e..8c2649a 100644 --- a/distrib/sets/lists/tests/mi +++ b/distrib/sets/lists/tests/mi @@ -3360,6 +3360,7 @@ ./usr/tests/net/net/t_ping6_opts tests-net-tests atf,rump ./usr/tests/net/net/t_ping_opts tests-net-tests atf,rump ./usr/tests/net/net/t_pktinfo tests-net-tests compattestfile,atf +./usr/tests/net/net/t_pktinfo_send tests-net-tests atf,rump ./usr/tests/net/net/t_raw tests-net-tests atf,rump ./usr/tests/net/net/t_tcp tests-net-tests compattestfile,atf ./usr/tests/net/net/t_udp tests-net-tests compattestfile,atf