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
netcfg_rump_makeshmif(const char * busname,char * ifname)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
netcfg_rump_if(const char * ifname,const char * addr,const char * mask)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
netcfg_rump_route(const char * dst,const char * mask,const char * gw)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
netcfg_rump_pingtest(const char * dst,int ms_timo)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