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