1191739Sobrien/*	$NetBSD: rumprouter.c,v 1.4 2010/07/04 15:44:46 pooka Exp $	*/
2191739Sobrien
3191739Sobrien/*
4191739Sobrien * Copyright (c) 2008 Antti Kantee.  All Rights Reserved.
5191739Sobrien *
6191739Sobrien * Development of this software was supported by the
7191739Sobrien * Finnish Cultural Foundation.
8191739Sobrien *
9191739Sobrien * Redistribution and use in source and binary forms, with or without
10191739Sobrien * modification, are permitted provided that the following conditions
11191739Sobrien * are met:
12191739Sobrien * 1. Redistributions of source code must retain the above copyright
13191739Sobrien *    notice, this list of conditions and the following disclaimer.
14191739Sobrien * 2. Redistributions in binary form must reproduce the above copyright
15191739Sobrien *    notice, this list of conditions and the following disclaimer in the
16191739Sobrien *    documentation and/or other materials provided with the distribution.
17191739Sobrien *
18191739Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
19191739Sobrien * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20191739Sobrien * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21191739Sobrien * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22191739Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23191739Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24191739Sobrien * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25191739Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26191739Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27226048Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28226048Sobrien * SUCH DAMAGE.
29191739Sobrien */
30226048Sobrien
31226048Sobrien#include <sys/types.h>
32226048Sobrien#include <sys/socket.h>
33191739Sobrien#include <sys/time.h>
34191739Sobrien
35191739Sobrien#include <arpa/inet.h>
36191739Sobrien
37191739Sobrien#include <netinet/in.h>
38328874Seadler#include <net/route.h>
39191739Sobrien
40191739Sobrien#include <rump/rump.h>
41191739Sobrien#include <rump/rump_syscalls.h>
42191739Sobrien
43191739Sobrien#include <err.h>
44191739Sobrien#include <errno.h>
45191739Sobrien#include <stdio.h>
46191739Sobrien#include <stdlib.h>
47191739Sobrien#include <string.h>
48191739Sobrien#include <unistd.h>
49191739Sobrien
50226048Sobrien#include <sys/sockio.h>
51226048Sobrien#include <arpa/inet.h>
52226048Sobrien#include <net/if.h>
53191739Sobrien#include <net/route.h>
54191739Sobrien
55191739Sobrien#undef DEBUG
56191739Sobrien
57191739Sobrien#ifdef DEBUG
58191739Sobrien#define DP	if (1) printf
59191739Sobrien#else
60191739Sobrien#define DP	if (0) printf
61192348Sdelphij#endif
62191739Sobrien
63191739Sobrienstatic void
64191739Sobrienconfigure_interface(const char *ifname, const char *addr, const char *mask,
65191739Sobrien	const char *bcast)
66191739Sobrien{
67191739Sobrien	struct ifaliasreq ia;
68191739Sobrien	struct sockaddr_in *sin;
69191739Sobrien	int s, rv;
70191739Sobrien
71191739Sobrien	DP("Entering %s\n", __FUNCTION__);
72191739Sobrien
73226048Sobrien	DP("Create an interface(%s)\n", ifname);
74226048Sobrien	s = atoi(ifname + strlen(ifname) - 1);		/* XXX FIXME XXX */
75226048Sobrien	if ((s = rump_pub_virtif_create(s)) != 0) {
76284237Sdelphij		err(1, "rump_pub_virtif_create(%d)", s);
77284237Sdelphij	}
78284237Sdelphij
79284237Sdelphij	DP("Get a socket for configuring the interface\n");
80284237Sdelphij	if ((s = rump_sys_socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
81226048Sobrien		err(1, "rump_sys_socket");
82191739Sobrien	}
83328874Seadler
84328874Seadler	/* Address */
85328874Seadler	memset(&ia, 0, sizeof(ia));
86234250Sobrien	strcpy(ia.ifra_name, ifname);
87328874Seadler	sin = (struct sockaddr_in *)&ia.ifra_addr;
88328874Seadler	sin->sin_family = AF_INET;
89328874Seadler	sin->sin_len = sizeof(struct sockaddr_in);
90328874Seadler	sin->sin_addr.s_addr = inet_addr(addr);
91328874Seadler
92328874Seadler	/* Netmask */
93328874Seadler	sin = (struct sockaddr_in *)&ia.ifra_mask;
94328874Seadler	sin->sin_family = AF_INET;
95328874Seadler	sin->sin_len = sizeof(struct sockaddr_in);
96328874Seadler	sin->sin_addr.s_addr = inet_addr(mask);
97328874Seadler
98328874Seadler	/* Broadcast address */
99328874Seadler	sin = (struct sockaddr_in *)&ia.ifra_broadaddr;
100328874Seadler	sin->sin_family = AF_INET;
101328874Seadler	sin->sin_len = sizeof(struct sockaddr_in);
102328874Seadler	sin->sin_addr.s_addr = inet_addr(bcast);
103328874Seadler
104328874Seadler	DP("Set the addresses\n");
105328874Seadler	rv = rump_sys_ioctl(s, SIOCAIFADDR, &ia);
106328874Seadler	if (rv) {
107328874Seadler		err(1, "SIOCAIFADDR");
108328874Seadler	}
109328874Seadler	rump_sys_close(s);
110328874Seadler	DP("Done with %s\n", __FUNCTION__);
111328874Seadler}
112191739Sobrien
113191739Sobrienstatic void
114191739Sobrienconfigure_routing(const char *dst, const char *mask, const char *gw)
115226048Sobrien{
116226048Sobrien	size_t len;
117191739Sobrien	struct {
118191739Sobrien		struct rt_msghdr m_rtm;
119226048Sobrien		uint8_t m_space[512];
120226048Sobrien	} m_rtmsg;
121191739Sobrien#define rtm m_rtmsg.m_rtm
122191739Sobrien	uint8_t *bp = m_rtmsg.m_space;
123191739Sobrien	struct sockaddr_in sinstore;
124191739Sobrien	int s, rv;
125191739Sobrien
126191739Sobrien	DP("Entering %s\n", __FUNCTION__);
127191739Sobrien
128191739Sobrien	DP("Open a routing socket\n");
129226048Sobrien	s = rump_sys_socket(PF_ROUTE, SOCK_RAW, 0);
130226048Sobrien	if (s == -1) {
131191739Sobrien		err(1, "rump_sys_socket");
132191739Sobrien	}
133226048Sobrien
134226048Sobrien	memset(&m_rtmsg, 0, sizeof(m_rtmsg));
135191739Sobrien	rtm.rtm_type = RTM_ADD;
136191739Sobrien	rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
137191739Sobrien	rtm.rtm_version = RTM_VERSION;
138191739Sobrien	rtm.rtm_seq = 2;
139191739Sobrien	rtm.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
140191739Sobrien
141191739Sobrien	/* dst */
142191739Sobrien	memset(&sinstore, 0, sizeof(sinstore));
143191739Sobrien	sinstore.sin_family = AF_INET;
144191739Sobrien	sinstore.sin_len = sizeof(sinstore);
145226048Sobrien	sinstore.sin_addr.s_addr = inet_addr(dst);
146226048Sobrien	memcpy(bp, &sinstore, sizeof(sinstore));
147191739Sobrien	bp += sizeof(sinstore);
148191739Sobrien
149226048Sobrien	/* gw */
150226048Sobrien	memset(&sinstore, 0, sizeof(sinstore));
151191739Sobrien	sinstore.sin_family = AF_INET;
152191739Sobrien	sinstore.sin_len = sizeof(sinstore);
153191739Sobrien	sinstore.sin_addr.s_addr = inet_addr(gw);
154191739Sobrien	memcpy(bp, &sinstore, sizeof(sinstore));
155191739Sobrien	bp += sizeof(sinstore);
156191739Sobrien
157191739Sobrien	/* netmask */
158191739Sobrien	memset(&sinstore, 0, sizeof(sinstore));
159191739Sobrien	sinstore.sin_family = AF_INET;
160191739Sobrien	sinstore.sin_len = sizeof(sinstore);
161191739Sobrien	sinstore.sin_addr.s_addr = inet_addr(mask);
162226048Sobrien	memcpy(bp, &sinstore, sizeof(sinstore));
163226048Sobrien	bp += sizeof(sinstore);
164226048Sobrien
165226048Sobrien	len = bp - (uint8_t *)&m_rtmsg;
166226048Sobrien	rtm.rtm_msglen = len;
167226048Sobrien
168226048Sobrien	DP("Set the route\n");
169226048Sobrien	rv = rump_sys_write(s, &m_rtmsg, len);
170226048Sobrien	if (rv != (int)len) {
171226048Sobrien		err(1, "rump_sys_write");
172226048Sobrien	}
173226048Sobrien	rump_sys_close(s);
174191739Sobrien	DP("Done with %s\n", __FUNCTION__);
175191739Sobrien}
176191739Sobrien
177191739Sobrienstatic void
178191739Sobrienusage(const char *argv0)
179226048Sobrien{
180226048Sobrien	printf("Usage: %s if1 if2 [route]\n", argv0);
181226048Sobrien	printf("\n");
182226048Sobrien	printf("where both \"if1\" and \"if2\" are\n");
183226048Sobrien	printf("\n");
184226048Sobrien	printf("ifname address netmask broadcast\n");
185226048Sobrien	printf("\n");
186226048Sobrien	printf("and \"route\" is an optional default route\n");
187226048Sobrien	exit(1);
188226048Sobrien}
189226048Sobrien
190226048Sobrienint
191226048Sobrienmain(int argc, char *argv[])
192226048Sobrien{
193226048Sobrien	if (argc < 9 || argc > 10) {
194226048Sobrien		usage(argv[0]);
195226048Sobrien	}
196226048Sobrien
197191739Sobrien	rump_init();
198191739Sobrien	configure_interface(argv[1], argv[2], argv[3], argv[4]);
199191739Sobrien	configure_interface(argv[5], argv[6], argv[7], argv[8]);
200191739Sobrien	if (argc == 10) {
201191739Sobrien		configure_routing("192.168.3.0", "255.255.255.0", "192.168.1.2");
202191739Sobrien	}
203191739Sobrien	printf("Press Ctrl+C to quit...");
204191739Sobrien	pause();
205191739Sobrien
206191739Sobrien	return 0;
207191739Sobrien}
208191739Sobrien