1272343Sngie/* $NetBSD: netconfig.c,v 1.8 2013/07/03 19:13:33 pooka Exp $ */ 2272343Sngie 3272343Sngie/*- 4272343Sngie * Copyright (c) 2010 The NetBSD Foundation, Inc. 5272343Sngie * All rights reserved. 6272343Sngie * 7272343Sngie * Redistribution and use in source and binary forms, with or without 8272343Sngie * modification, are permitted provided that the following conditions 9272343Sngie * are met: 10272343Sngie * 1. Redistributions of source code must retain the above copyright 11272343Sngie * notice, this list of conditions and the following disclaimer. 12272343Sngie * 2. Redistributions in binary form must reproduce the above copyright 13272343Sngie * notice, this list of conditions and the following disclaimer in the 14272343Sngie * documentation and/or other materials provided with the distribution. 15272343Sngie * 16272343Sngie * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 17272343Sngie * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 18272343Sngie * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19272343Sngie * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20272343Sngie * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 21272343Sngie * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22272343Sngie * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 23272343Sngie * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24272343Sngie * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25272343Sngie * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26272343Sngie * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27272343Sngie * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28272343Sngie */ 29272343Sngie 30272343Sngie#include <sys/cdefs.h> 31272343Sngie#ifndef lint 32272343Sngie__RCSID("$NetBSD: netconfig.c,v 1.8 2013/07/03 19:13:33 pooka Exp $"); 33272343Sngie#endif /* not lint */ 34272343Sngie 35272343Sngie#include <sys/types.h> 36272343Sngie#include <sys/socket.h> 37272343Sngie#include <sys/ioctl.h> 38272343Sngie 39272343Sngie#include <arpa/inet.h> 40272343Sngie 41272343Sngie#include <net/route.h> 42272343Sngie 43272343Sngie#include <netinet/in.h> 44272343Sngie#include <netinet/in_systm.h> 45272343Sngie#include <netinet/ip.h> 46272343Sngie#include <netinet/ip_icmp.h> 47272343Sngie 48272343Sngie#include <atf-c.h> 49272343Sngie#include <err.h> 50272343Sngie#include <errno.h> 51272343Sngie#include <string.h> 52272343Sngie 53272343Sngie#include <rump/rump.h> 54272343Sngie#include <rump/rump_syscalls.h> 55272343Sngie 56272343Sngie#include "../../h_macros.h" 57272343Sngie 58272343Sngieint noatf; 59272343Sngie 60272343Sngiestatic void __unused 61272343Sngienetcfg_rump_makeshmif(const char *busname, char *ifname) 62272343Sngie{ 63272343Sngie int rv, ifnum; 64272343Sngie 65272343Sngie if ((rv = rump_pub_shmif_create(busname, &ifnum)) != 0) { 66272343Sngie if (noatf) 67272343Sngie err(1, "makeshmif: rump_pub_shmif_create %d", rv); 68272343Sngie else 69272343Sngie atf_tc_fail("makeshmif: rump_pub_shmif_create %d", rv); 70272343Sngie } 71272343Sngie sprintf(ifname, "shmif%d", ifnum); 72272343Sngie} 73272343Sngie 74272343Sngiestatic void __unused 75272343Sngienetcfg_rump_if(const char *ifname, const char *addr, const char *mask) 76272343Sngie{ 77272343Sngie struct ifaliasreq ia; 78272343Sngie struct sockaddr_in *sin; 79272343Sngie in_addr_t inaddr, inmask; 80272343Sngie int s, rv; 81272343Sngie 82272343Sngie s = -1; 83272343Sngie if ((s = rump_sys_socket(PF_INET, SOCK_DGRAM, 0)) < 0) { 84272343Sngie if (noatf) 85272343Sngie err(1, "if config socket"); 86272343Sngie else 87272343Sngie atf_tc_fail_errno("if config socket"); 88272343Sngie } 89272343Sngie 90272343Sngie inaddr = inet_addr(addr); 91272343Sngie inmask = inet_addr(mask); 92272343Sngie 93272343Sngie /* Address */ 94272343Sngie memset(&ia, 0, sizeof(ia)); 95272343Sngie strcpy(ia.ifra_name, ifname); 96272343Sngie sin = (struct sockaddr_in *)&ia.ifra_addr; 97272343Sngie sin->sin_family = AF_INET; 98272343Sngie sin->sin_len = sizeof(struct sockaddr_in); 99272343Sngie sin->sin_addr.s_addr = inaddr; 100272343Sngie 101272343Sngie /* Netmask */ 102272343Sngie sin = (struct sockaddr_in *)&ia.ifra_mask; 103272343Sngie sin->sin_family = AF_INET; 104272343Sngie sin->sin_len = sizeof(struct sockaddr_in); 105272343Sngie sin->sin_addr.s_addr = inmask; 106272343Sngie 107272343Sngie /* Broadcast address */ 108272343Sngie sin = (struct sockaddr_in *)&ia.ifra_broadaddr; 109272343Sngie sin->sin_family = AF_INET; 110272343Sngie sin->sin_len = sizeof(struct sockaddr_in); 111272343Sngie sin->sin_addr.s_addr = inaddr | ~inmask; 112272343Sngie 113272343Sngie rv = rump_sys_ioctl(s, SIOCAIFADDR, &ia); 114272343Sngie if (rv == -1) { 115272343Sngie if (noatf) 116272343Sngie err(1, "SIOCAIFADDR"); 117272343Sngie else 118272343Sngie atf_tc_fail_errno("SIOCAIFADDR"); 119272343Sngie } 120272343Sngie rump_sys_close(s); 121272343Sngie} 122272343Sngie 123272343Sngiestatic void __unused 124272343Sngienetcfg_rump_route(const char *dst, const char *mask, const char *gw) 125272343Sngie{ 126272343Sngie size_t len; 127272343Sngie struct { 128272343Sngie struct rt_msghdr m_rtm; 129272343Sngie uint8_t m_space[512]; 130272343Sngie } m_rtmsg; 131272343Sngie#define rtm m_rtmsg.m_rtm 132272343Sngie uint8_t *bp = m_rtmsg.m_space; 133272343Sngie struct sockaddr_in sinstore; 134272343Sngie int s, rv; 135272343Sngie 136272343Sngie s = rump_sys_socket(PF_ROUTE, SOCK_RAW, 0); 137272343Sngie if (s == -1) { 138272343Sngie if (noatf) 139272343Sngie err(1, "routing socket"); 140272343Sngie else 141272343Sngie atf_tc_fail_errno("routing socket"); 142272343Sngie } 143272343Sngie 144272343Sngie memset(&m_rtmsg, 0, sizeof(m_rtmsg)); 145272343Sngie rtm.rtm_type = RTM_ADD; 146272343Sngie rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC; 147272343Sngie rtm.rtm_version = RTM_VERSION; 148272343Sngie rtm.rtm_seq = 2; 149272343Sngie rtm.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; 150272343Sngie 151272343Sngie /* dst */ 152272343Sngie memset(&sinstore, 0, sizeof(sinstore)); 153272343Sngie sinstore.sin_family = AF_INET; 154272343Sngie sinstore.sin_len = sizeof(sinstore); 155272343Sngie sinstore.sin_addr.s_addr = inet_addr(dst); 156272343Sngie memcpy(bp, &sinstore, sizeof(sinstore)); 157272343Sngie bp += sizeof(sinstore); 158272343Sngie 159272343Sngie /* gw */ 160272343Sngie memset(&sinstore, 0, sizeof(sinstore)); 161272343Sngie sinstore.sin_family = AF_INET; 162272343Sngie sinstore.sin_len = sizeof(sinstore); 163272343Sngie sinstore.sin_addr.s_addr = inet_addr(gw); 164272343Sngie memcpy(bp, &sinstore, sizeof(sinstore)); 165272343Sngie bp += sizeof(sinstore); 166272343Sngie 167272343Sngie /* netmask */ 168272343Sngie memset(&sinstore, 0, sizeof(sinstore)); 169272343Sngie sinstore.sin_family = AF_INET; 170272343Sngie sinstore.sin_len = sizeof(sinstore); 171272343Sngie sinstore.sin_addr.s_addr = inet_addr(mask); 172272343Sngie memcpy(bp, &sinstore, sizeof(sinstore)); 173272343Sngie bp += sizeof(sinstore); 174272343Sngie 175272343Sngie len = bp - (uint8_t *)&m_rtmsg; 176272343Sngie rtm.rtm_msglen = len; 177272343Sngie 178272343Sngie rv = rump_sys_write(s, &m_rtmsg, len); 179272343Sngie if (rv != (int)len) { 180272343Sngie if (noatf) 181272343Sngie err(1, "write routing message"); 182272343Sngie else 183272343Sngie atf_tc_fail_errno("write routing message"); 184272343Sngie } 185272343Sngie rump_sys_close(s); 186272343Sngie} 187272343Sngie 188272343Sngiestatic bool __unused 189272343Sngienetcfg_rump_pingtest(const char *dst, int ms_timo) 190272343Sngie{ 191272343Sngie struct timeval tv; 192272343Sngie struct sockaddr_in sin; 193272343Sngie struct icmp icmp; 194272343Sngie socklen_t slen; 195272343Sngie int s; 196272343Sngie bool rv = false; 197272343Sngie 198272343Sngie s = rump_sys_socket(PF_INET, SOCK_RAW, IPPROTO_ICMP); 199272343Sngie if (s == -1) 200272343Sngie return false; 201272343Sngie tv.tv_sec = ms_timo / 1000; 202272343Sngie tv.tv_usec = 1000 * (ms_timo % 1000); 203272343Sngie if (rump_sys_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, 204272343Sngie &tv, sizeof(tv)) == -1) 205272343Sngie goto out; 206272343Sngie 207272343Sngie memset(&sin, 0, sizeof(sin)); 208272343Sngie sin.sin_len = sizeof(sin); 209272343Sngie sin.sin_family = AF_INET; 210272343Sngie sin.sin_addr.s_addr = inet_addr(dst); 211272343Sngie 212272343Sngie memset(&icmp, 0, sizeof(icmp)); 213272343Sngie icmp.icmp_type = ICMP_ECHO; 214272343Sngie icmp.icmp_id = htons(37); 215272343Sngie icmp.icmp_cksum = htons(0xf7da); /* precalc */ 216272343Sngie 217272343Sngie slen = sizeof(sin); 218272343Sngie if (rump_sys_sendto(s, &icmp, sizeof(icmp), 0, 219272343Sngie (struct sockaddr *)&sin, slen) == -1) { 220272343Sngie goto out; 221272343Sngie } 222272343Sngie 223272343Sngie if (rump_sys_recvfrom(s, &icmp, sizeof(icmp), 0, 224272343Sngie (struct sockaddr *)&sin, &slen) == -1) 225272343Sngie goto out; 226272343Sngie 227272343Sngie rv = true; 228272343Sngie out: 229272343Sngie rump_sys_close(s); 230272343Sngie return rv; 231272343Sngie} 232