1*63d1fd59SEnji Cooper /* $NetBSD: netconfig.c,v 1.9 2017/01/13 21:30:42 christos Exp $ */ 257718be8SEnji Cooper 357718be8SEnji Cooper /*- 457718be8SEnji Cooper * Copyright (c) 2010 The NetBSD Foundation, Inc. 557718be8SEnji Cooper * All rights reserved. 657718be8SEnji Cooper * 757718be8SEnji Cooper * Redistribution and use in source and binary forms, with or without 857718be8SEnji Cooper * modification, are permitted provided that the following conditions 957718be8SEnji Cooper * are met: 1057718be8SEnji Cooper * 1. Redistributions of source code must retain the above copyright 1157718be8SEnji Cooper * notice, this list of conditions and the following disclaimer. 1257718be8SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright 1357718be8SEnji Cooper * notice, this list of conditions and the following disclaimer in the 1457718be8SEnji Cooper * documentation and/or other materials provided with the distribution. 1557718be8SEnji Cooper * 1657718be8SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 1757718be8SEnji Cooper * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 1857718be8SEnji Cooper * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 1957718be8SEnji Cooper * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2057718be8SEnji Cooper * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 2157718be8SEnji Cooper * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2257718be8SEnji Cooper * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 2357718be8SEnji Cooper * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 2457718be8SEnji Cooper * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 2557718be8SEnji Cooper * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 2657718be8SEnji Cooper * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 2757718be8SEnji Cooper * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2857718be8SEnji Cooper */ 2957718be8SEnji Cooper 3057718be8SEnji Cooper #include <sys/cdefs.h> 3157718be8SEnji Cooper #ifndef lint 32*63d1fd59SEnji Cooper __RCSID("$NetBSD: netconfig.c,v 1.9 2017/01/13 21:30:42 christos Exp $"); 3357718be8SEnji Cooper #endif /* not lint */ 3457718be8SEnji Cooper 3557718be8SEnji Cooper #include <sys/types.h> 3657718be8SEnji Cooper #include <sys/socket.h> 3757718be8SEnji Cooper #include <sys/ioctl.h> 3857718be8SEnji Cooper 3957718be8SEnji Cooper #include <arpa/inet.h> 4057718be8SEnji Cooper 4157718be8SEnji Cooper #include <net/route.h> 4257718be8SEnji Cooper 4357718be8SEnji Cooper #include <netinet/in.h> 4457718be8SEnji Cooper #include <netinet/in_systm.h> 4557718be8SEnji Cooper #include <netinet/ip.h> 4657718be8SEnji Cooper #include <netinet/ip_icmp.h> 4757718be8SEnji Cooper 4857718be8SEnji Cooper #include <atf-c.h> 4957718be8SEnji Cooper #include <err.h> 5057718be8SEnji Cooper #include <errno.h> 5157718be8SEnji Cooper #include <string.h> 5257718be8SEnji Cooper 5357718be8SEnji Cooper #include <rump/rump.h> 5457718be8SEnji Cooper #include <rump/rump_syscalls.h> 5557718be8SEnji Cooper 56*63d1fd59SEnji Cooper #include "h_macros.h" 5757718be8SEnji Cooper 5857718be8SEnji Cooper int noatf; 5957718be8SEnji Cooper 6057718be8SEnji Cooper static void __unused 6157718be8SEnji Cooper netcfg_rump_makeshmif(const char *busname, char *ifname) 6257718be8SEnji Cooper { 6357718be8SEnji Cooper int rv, ifnum; 6457718be8SEnji Cooper 6557718be8SEnji Cooper if ((rv = rump_pub_shmif_create(busname, &ifnum)) != 0) { 6657718be8SEnji Cooper if (noatf) 6757718be8SEnji Cooper err(1, "makeshmif: rump_pub_shmif_create %d", rv); 6857718be8SEnji Cooper else 6957718be8SEnji Cooper atf_tc_fail("makeshmif: rump_pub_shmif_create %d", rv); 7057718be8SEnji Cooper } 7157718be8SEnji Cooper sprintf(ifname, "shmif%d", ifnum); 7257718be8SEnji Cooper } 7357718be8SEnji Cooper 7457718be8SEnji Cooper static void __unused 7557718be8SEnji Cooper netcfg_rump_if(const char *ifname, const char *addr, const char *mask) 7657718be8SEnji Cooper { 7757718be8SEnji Cooper struct ifaliasreq ia; 7857718be8SEnji Cooper struct sockaddr_in *sin; 7957718be8SEnji Cooper in_addr_t inaddr, inmask; 8057718be8SEnji Cooper int s, rv; 8157718be8SEnji Cooper 8257718be8SEnji Cooper s = -1; 8357718be8SEnji Cooper if ((s = rump_sys_socket(PF_INET, SOCK_DGRAM, 0)) < 0) { 8457718be8SEnji Cooper if (noatf) 8557718be8SEnji Cooper err(1, "if config socket"); 8657718be8SEnji Cooper else 8757718be8SEnji Cooper atf_tc_fail_errno("if config socket"); 8857718be8SEnji Cooper } 8957718be8SEnji Cooper 9057718be8SEnji Cooper inaddr = inet_addr(addr); 9157718be8SEnji Cooper inmask = inet_addr(mask); 9257718be8SEnji Cooper 9357718be8SEnji Cooper /* Address */ 9457718be8SEnji Cooper memset(&ia, 0, sizeof(ia)); 9557718be8SEnji Cooper strcpy(ia.ifra_name, ifname); 9657718be8SEnji Cooper sin = (struct sockaddr_in *)&ia.ifra_addr; 9757718be8SEnji Cooper sin->sin_family = AF_INET; 9857718be8SEnji Cooper sin->sin_len = sizeof(struct sockaddr_in); 9957718be8SEnji Cooper sin->sin_addr.s_addr = inaddr; 10057718be8SEnji Cooper 10157718be8SEnji Cooper /* Netmask */ 10257718be8SEnji Cooper sin = (struct sockaddr_in *)&ia.ifra_mask; 10357718be8SEnji Cooper sin->sin_family = AF_INET; 10457718be8SEnji Cooper sin->sin_len = sizeof(struct sockaddr_in); 10557718be8SEnji Cooper sin->sin_addr.s_addr = inmask; 10657718be8SEnji Cooper 10757718be8SEnji Cooper /* Broadcast address */ 10857718be8SEnji Cooper sin = (struct sockaddr_in *)&ia.ifra_broadaddr; 10957718be8SEnji Cooper sin->sin_family = AF_INET; 11057718be8SEnji Cooper sin->sin_len = sizeof(struct sockaddr_in); 11157718be8SEnji Cooper sin->sin_addr.s_addr = inaddr | ~inmask; 11257718be8SEnji Cooper 11357718be8SEnji Cooper rv = rump_sys_ioctl(s, SIOCAIFADDR, &ia); 11457718be8SEnji Cooper if (rv == -1) { 11557718be8SEnji Cooper if (noatf) 11657718be8SEnji Cooper err(1, "SIOCAIFADDR"); 11757718be8SEnji Cooper else 11857718be8SEnji Cooper atf_tc_fail_errno("SIOCAIFADDR"); 11957718be8SEnji Cooper } 12057718be8SEnji Cooper rump_sys_close(s); 12157718be8SEnji Cooper } 12257718be8SEnji Cooper 12357718be8SEnji Cooper static void __unused 12457718be8SEnji Cooper netcfg_rump_route(const char *dst, const char *mask, const char *gw) 12557718be8SEnji Cooper { 12657718be8SEnji Cooper size_t len; 12757718be8SEnji Cooper struct { 12857718be8SEnji Cooper struct rt_msghdr m_rtm; 12957718be8SEnji Cooper uint8_t m_space[512]; 13057718be8SEnji Cooper } m_rtmsg; 13157718be8SEnji Cooper #define rtm m_rtmsg.m_rtm 13257718be8SEnji Cooper uint8_t *bp = m_rtmsg.m_space; 13357718be8SEnji Cooper struct sockaddr_in sinstore; 13457718be8SEnji Cooper int s, rv; 13557718be8SEnji Cooper 13657718be8SEnji Cooper s = rump_sys_socket(PF_ROUTE, SOCK_RAW, 0); 13757718be8SEnji Cooper if (s == -1) { 13857718be8SEnji Cooper if (noatf) 13957718be8SEnji Cooper err(1, "routing socket"); 14057718be8SEnji Cooper else 14157718be8SEnji Cooper atf_tc_fail_errno("routing socket"); 14257718be8SEnji Cooper } 14357718be8SEnji Cooper 14457718be8SEnji Cooper memset(&m_rtmsg, 0, sizeof(m_rtmsg)); 14557718be8SEnji Cooper rtm.rtm_type = RTM_ADD; 14657718be8SEnji Cooper rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC; 14757718be8SEnji Cooper rtm.rtm_version = RTM_VERSION; 14857718be8SEnji Cooper rtm.rtm_seq = 2; 14957718be8SEnji Cooper rtm.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; 15057718be8SEnji Cooper 15157718be8SEnji Cooper /* dst */ 15257718be8SEnji Cooper memset(&sinstore, 0, sizeof(sinstore)); 15357718be8SEnji Cooper sinstore.sin_family = AF_INET; 15457718be8SEnji Cooper sinstore.sin_len = sizeof(sinstore); 15557718be8SEnji Cooper sinstore.sin_addr.s_addr = inet_addr(dst); 15657718be8SEnji Cooper memcpy(bp, &sinstore, sizeof(sinstore)); 15757718be8SEnji Cooper bp += sizeof(sinstore); 15857718be8SEnji Cooper 15957718be8SEnji Cooper /* gw */ 16057718be8SEnji Cooper memset(&sinstore, 0, sizeof(sinstore)); 16157718be8SEnji Cooper sinstore.sin_family = AF_INET; 16257718be8SEnji Cooper sinstore.sin_len = sizeof(sinstore); 16357718be8SEnji Cooper sinstore.sin_addr.s_addr = inet_addr(gw); 16457718be8SEnji Cooper memcpy(bp, &sinstore, sizeof(sinstore)); 16557718be8SEnji Cooper bp += sizeof(sinstore); 16657718be8SEnji Cooper 16757718be8SEnji Cooper /* netmask */ 16857718be8SEnji Cooper memset(&sinstore, 0, sizeof(sinstore)); 16957718be8SEnji Cooper sinstore.sin_family = AF_INET; 17057718be8SEnji Cooper sinstore.sin_len = sizeof(sinstore); 17157718be8SEnji Cooper sinstore.sin_addr.s_addr = inet_addr(mask); 17257718be8SEnji Cooper memcpy(bp, &sinstore, sizeof(sinstore)); 17357718be8SEnji Cooper bp += sizeof(sinstore); 17457718be8SEnji Cooper 17557718be8SEnji Cooper len = bp - (uint8_t *)&m_rtmsg; 17657718be8SEnji Cooper rtm.rtm_msglen = len; 17757718be8SEnji Cooper 17857718be8SEnji Cooper rv = rump_sys_write(s, &m_rtmsg, len); 17957718be8SEnji Cooper if (rv != (int)len) { 18057718be8SEnji Cooper if (noatf) 18157718be8SEnji Cooper err(1, "write routing message"); 18257718be8SEnji Cooper else 18357718be8SEnji Cooper atf_tc_fail_errno("write routing message"); 18457718be8SEnji Cooper } 18557718be8SEnji Cooper rump_sys_close(s); 18657718be8SEnji Cooper } 18757718be8SEnji Cooper 18857718be8SEnji Cooper static bool __unused 18957718be8SEnji Cooper netcfg_rump_pingtest(const char *dst, int ms_timo) 19057718be8SEnji Cooper { 19157718be8SEnji Cooper struct timeval tv; 19257718be8SEnji Cooper struct sockaddr_in sin; 19357718be8SEnji Cooper struct icmp icmp; 19457718be8SEnji Cooper socklen_t slen; 19557718be8SEnji Cooper int s; 19657718be8SEnji Cooper bool rv = false; 19757718be8SEnji Cooper 19857718be8SEnji Cooper s = rump_sys_socket(PF_INET, SOCK_RAW, IPPROTO_ICMP); 19957718be8SEnji Cooper if (s == -1) 20057718be8SEnji Cooper return false; 20157718be8SEnji Cooper tv.tv_sec = ms_timo / 1000; 20257718be8SEnji Cooper tv.tv_usec = 1000 * (ms_timo % 1000); 20357718be8SEnji Cooper if (rump_sys_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, 20457718be8SEnji Cooper &tv, sizeof(tv)) == -1) 20557718be8SEnji Cooper goto out; 20657718be8SEnji Cooper 20757718be8SEnji Cooper memset(&sin, 0, sizeof(sin)); 20857718be8SEnji Cooper sin.sin_len = sizeof(sin); 20957718be8SEnji Cooper sin.sin_family = AF_INET; 21057718be8SEnji Cooper sin.sin_addr.s_addr = inet_addr(dst); 21157718be8SEnji Cooper 21257718be8SEnji Cooper memset(&icmp, 0, sizeof(icmp)); 21357718be8SEnji Cooper icmp.icmp_type = ICMP_ECHO; 21457718be8SEnji Cooper icmp.icmp_id = htons(37); 21557718be8SEnji Cooper icmp.icmp_cksum = htons(0xf7da); /* precalc */ 21657718be8SEnji Cooper 21757718be8SEnji Cooper slen = sizeof(sin); 21857718be8SEnji Cooper if (rump_sys_sendto(s, &icmp, sizeof(icmp), 0, 21957718be8SEnji Cooper (struct sockaddr *)&sin, slen) == -1) { 22057718be8SEnji Cooper goto out; 22157718be8SEnji Cooper } 22257718be8SEnji Cooper 22357718be8SEnji Cooper if (rump_sys_recvfrom(s, &icmp, sizeof(icmp), 0, 22457718be8SEnji Cooper (struct sockaddr *)&sin, &slen) == -1) 22557718be8SEnji Cooper goto out; 22657718be8SEnji Cooper 22757718be8SEnji Cooper rv = true; 22857718be8SEnji Cooper out: 22957718be8SEnji Cooper rump_sys_close(s); 23057718be8SEnji Cooper return rv; 23157718be8SEnji Cooper } 232