1 /* $NetBSD: rumprouter.c,v 1.5 2010/07/04 17:24:10 pooka Exp $ */ 2 3 /* 4 * Copyright (c) 2008 Antti Kantee. All Rights Reserved. 5 * 6 * Development of this software was supported by the 7 * Finnish Cultural Foundation. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 19 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include <sys/types.h> 32 #include <sys/socket.h> 33 #include <sys/time.h> 34 35 #include <arpa/inet.h> 36 37 #include <netinet/in.h> 38 #include <net/route.h> 39 40 #include <rump/rump.h> 41 #include <rump/rump_syscalls.h> 42 43 #include <err.h> 44 #include <errno.h> 45 #include <stdio.h> 46 #include <stdlib.h> 47 #include <string.h> 48 #include <unistd.h> 49 50 #include <sys/sockio.h> 51 #include <arpa/inet.h> 52 #include <net/if.h> 53 #include <net/route.h> 54 55 #undef DEBUG 56 57 #ifdef DEBUG 58 #define DP if (1) printf 59 #else 60 #define DP if (0) printf 61 #endif 62 63 static void 64 configure_interface(const char *ifname, const char *addr, const char *mask, 65 const char *bcast) 66 { 67 struct ifaliasreq ia; 68 struct sockaddr_in *sin; 69 int s, rv; 70 71 DP("Entering %s\n", __FUNCTION__); 72 73 DP("Create an interface(%s)\n", ifname); 74 s = atoi(ifname + strlen(ifname) - 1); /* XXX FIXME XXX */ 75 if ((s = rump_pub_virtif_create(s)) != 0) { 76 err(1, "rump_pub_virtif_create(%d)", s); 77 } 78 79 DP("Get a socket for configuring the interface\n"); 80 if ((s = rump_sys_socket(PF_INET, SOCK_DGRAM, 0)) < 0) { 81 err(1, "rump_sys_socket"); 82 } 83 84 /* Address */ 85 memset(&ia, 0, sizeof(ia)); 86 strcpy(ia.ifra_name, ifname); 87 sin = (struct sockaddr_in *)&ia.ifra_addr; 88 sin->sin_family = AF_INET; 89 sin->sin_len = sizeof(struct sockaddr_in); 90 sin->sin_addr.s_addr = inet_addr(addr); 91 92 /* Netmask */ 93 sin = (struct sockaddr_in *)&ia.ifra_mask; 94 sin->sin_family = AF_INET; 95 sin->sin_len = sizeof(struct sockaddr_in); 96 sin->sin_addr.s_addr = inet_addr(mask); 97 98 /* Broadcast address */ 99 sin = (struct sockaddr_in *)&ia.ifra_broadaddr; 100 sin->sin_family = AF_INET; 101 sin->sin_len = sizeof(struct sockaddr_in); 102 sin->sin_addr.s_addr = inet_addr(bcast); 103 104 DP("Set the addresses\n"); 105 rv = rump_sys_ioctl(s, SIOCAIFADDR, &ia); 106 if (rv) { 107 err(1, "SIOCAIFADDR"); 108 } 109 rump_sys_close(s); 110 DP("Done with %s\n", __FUNCTION__); 111 } 112 113 static void 114 configure_routing(const char *dst, const char *mask, const char *gw) 115 { 116 size_t len; 117 struct { 118 struct rt_msghdr m_rtm; 119 uint8_t m_space[512]; 120 } m_rtmsg; 121 #define rtm m_rtmsg.m_rtm 122 uint8_t *bp = m_rtmsg.m_space; 123 struct sockaddr_in sinstore; 124 int s, rv; 125 126 DP("Entering %s\n", __FUNCTION__); 127 128 DP("Open a routing socket\n"); 129 s = rump_sys_socket(PF_ROUTE, SOCK_RAW, 0); 130 if (s == -1) { 131 err(1, "rump_sys_socket"); 132 } 133 134 memset(&m_rtmsg, 0, sizeof(m_rtmsg)); 135 rtm.rtm_type = RTM_ADD; 136 rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC; 137 rtm.rtm_version = RTM_VERSION; 138 rtm.rtm_seq = 2; 139 rtm.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK; 140 141 /* dst */ 142 memset(&sinstore, 0, sizeof(sinstore)); 143 sinstore.sin_family = AF_INET; 144 sinstore.sin_len = sizeof(sinstore); 145 sinstore.sin_addr.s_addr = inet_addr(dst); 146 memcpy(bp, &sinstore, sizeof(sinstore)); 147 bp += sizeof(sinstore); 148 149 /* gw */ 150 memset(&sinstore, 0, sizeof(sinstore)); 151 sinstore.sin_family = AF_INET; 152 sinstore.sin_len = sizeof(sinstore); 153 sinstore.sin_addr.s_addr = inet_addr(gw); 154 memcpy(bp, &sinstore, sizeof(sinstore)); 155 bp += sizeof(sinstore); 156 157 /* netmask */ 158 memset(&sinstore, 0, sizeof(sinstore)); 159 sinstore.sin_family = AF_INET; 160 sinstore.sin_len = sizeof(sinstore); 161 sinstore.sin_addr.s_addr = inet_addr(mask); 162 memcpy(bp, &sinstore, sizeof(sinstore)); 163 bp += sizeof(sinstore); 164 165 len = bp - (uint8_t *)&m_rtmsg; 166 rtm.rtm_msglen = len; 167 168 DP("Set the route\n"); 169 rv = rump_sys_write(s, &m_rtmsg, len); 170 if (rv != (int)len) { 171 err(1, "rump_sys_write"); 172 } 173 rump_sys_close(s); 174 DP("Done with %s\n", __FUNCTION__); 175 } 176 177 static void 178 usage(const char *argv0) 179 { 180 printf("Usage: %s if1 if2 [route]\n", argv0); 181 printf("\n"); 182 printf("where both \"if1\" and \"if2\" are\n"); 183 printf("\n"); 184 printf("ifname address netmask broadcast\n"); 185 printf("\n"); 186 printf("and \"route\" is an optional default route\n"); 187 exit(1); 188 } 189 190 int 191 main(int argc, char *argv[]) 192 { 193 if (argc < 9 || argc > 10) { 194 usage(argv[0]); 195 } 196 197 rump_init(); 198 configure_interface(argv[1], argv[2], argv[3], argv[4]); 199 configure_interface(argv[5], argv[6], argv[7], argv[8]); 200 if (argc == 10) { 201 configure_routing("192.168.3.0", "255.255.255.0", "192.168.1.2"); 202 } 203 printf("Press Ctrl+C to quit..."); 204 pause(); 205 206 return 0; 207 } 208