e6f5280c8d
full networking stack operation.
222 lines
6.6 KiB
C
222 lines
6.6 KiB
C
/* $NetBSD: rumptest_net.c,v 1.5 2008/11/14 14:24:00 pooka Exp $ */
|
|
|
|
/*
|
|
* Copyright (c) 2008 Antti Kantee. All Rights Reserved.
|
|
*
|
|
* Development of this software was supported by then
|
|
* Finnish Cultural Foundation.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
|
|
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/time.h>
|
|
#include <sys/sockio.h>
|
|
|
|
#include <arpa/inet.h>
|
|
#include <net/if.h>
|
|
#include <net/route.h>
|
|
#include <netinet/in.h>
|
|
|
|
#include <rump/rump.h>
|
|
#include <rump/rump_syscalls.h>
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define DEST_ADDR "204.152.190.12" /* www.NetBSD.org */
|
|
#define DEST_PORT 80 /* take a wild guess */
|
|
|
|
#ifdef FULL_NETWORK_STACK
|
|
/*
|
|
* If we are running with the full networking stack, configure
|
|
* virtual interface. For this to currently work, you *must* have
|
|
* tap0 bridged with your main networking interface. Essentially
|
|
* the following steps are required:
|
|
*
|
|
* # ifconfig tap0 create
|
|
* # ifconfig tap0 up
|
|
* # ifconfig bridge0 create
|
|
* # brconfig bridge0 add tap0 add yourrealif0
|
|
* # brconfig bridge0 up
|
|
*
|
|
* The usability is likely to be improved later.
|
|
*/
|
|
#define MYADDR "10.181.181.11"
|
|
#define MYBCAST "10.181.181.255"
|
|
#define MYMASK "255.255.255.0"
|
|
#define MYGW "10.181.181.1"
|
|
#define IFNAME "virt0" /* XXX: hardcoded */
|
|
|
|
int rump_virtif_create(void *, void *); /* XXX: bad hack, prototype is wrong */
|
|
static void
|
|
configure_interface()
|
|
{
|
|
struct sockaddr_in *sin;
|
|
struct sockaddr_in sinstore;
|
|
struct ifaliasreq ia;
|
|
size_t len;
|
|
struct {
|
|
struct rt_msghdr m_rtm;
|
|
uint8_t m_space;
|
|
} m_rtmsg;
|
|
#define rtm m_rtmsg.m_rtm
|
|
uint8_t *bp = &m_rtmsg.m_space;
|
|
int s, rv, error;
|
|
|
|
if ((rv = rump_virtif_create(NULL, NULL)) != 0) {
|
|
printf("could not configure interface %d\n", rv);
|
|
exit(1);
|
|
}
|
|
|
|
/* get a socket for configuring the interface */
|
|
s = rump_sys___socket30(PF_INET, SOCK_DGRAM, 0, &error);
|
|
if (s == -1)
|
|
errx(1, "configuration socket %d (%s)", error, strerror(error));
|
|
|
|
/* fill out struct ifaliasreq */
|
|
memset(&ia, 0, sizeof(ia));
|
|
strcpy(ia.ifra_name, IFNAME);
|
|
sin = (struct sockaddr_in *)&ia.ifra_addr;
|
|
sin->sin_family = AF_INET;
|
|
sin->sin_len = sizeof(struct sockaddr_in);
|
|
sin->sin_addr.s_addr = inet_addr(MYADDR);
|
|
|
|
sin = (struct sockaddr_in *)&ia.ifra_broadaddr;
|
|
sin->sin_family = AF_INET;
|
|
sin->sin_len = sizeof(struct sockaddr_in);
|
|
sin->sin_addr.s_addr = inet_addr(MYBCAST);
|
|
|
|
sin = (struct sockaddr_in *)&ia.ifra_mask;
|
|
sin->sin_family = AF_INET;
|
|
sin->sin_len = sizeof(struct sockaddr_in);
|
|
sin->sin_addr.s_addr = inet_addr(MYMASK);
|
|
|
|
/* toss to the configuration socket and see what it thinks */
|
|
rv = rump_sys_ioctl(s, SIOCAIFADDR, &ia, &error);
|
|
if (rv)
|
|
errx(1, "SIOCAIFADDR %d (%s)", error, strerror(error));
|
|
rump_sys_close(s, &error);
|
|
|
|
/* open routing socket and configure our default router */
|
|
s = rump_sys___socket30(PF_ROUTE, SOCK_RAW, 0, &error);
|
|
if (s == -1)
|
|
errx(1, "routing socket %d (%s)", error, strerror(error));
|
|
|
|
/* create routing message */
|
|
memset(&m_rtmsg, 0, sizeof(m_rtmsg));
|
|
rtm.rtm_type = RTM_ADD;
|
|
rtm.rtm_flags = RTF_UP | RTF_GATEWAY | RTF_STATIC;
|
|
rtm.rtm_version = RTM_VERSION;
|
|
rtm.rtm_seq = 2;
|
|
rtm.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
|
|
|
|
/* dst */
|
|
memset(&sinstore, 0, sizeof(sinstore));
|
|
sinstore.sin_family = AF_INET;
|
|
sinstore.sin_len = sizeof(sinstore);
|
|
memcpy(bp, &sinstore, sizeof(sinstore));
|
|
bp += sizeof(sinstore);
|
|
|
|
/* gw */
|
|
memset(&sinstore, 0, sizeof(sinstore));
|
|
sinstore.sin_family = AF_INET;
|
|
sinstore.sin_len = sizeof(sinstore);
|
|
sinstore.sin_addr.s_addr = inet_addr(MYGW);
|
|
memcpy(bp, &sinstore, sizeof(sinstore));
|
|
bp += sizeof(sinstore);
|
|
|
|
/* netmask */
|
|
memset(&sinstore, 0, sizeof(sinstore));
|
|
sinstore.sin_family = AF_INET;
|
|
sinstore.sin_len = sizeof(sinstore);
|
|
memcpy(bp, &sinstore, sizeof(sinstore));
|
|
bp += sizeof(sinstore);
|
|
|
|
len = bp - (uint8_t *)&m_rtmsg;
|
|
rtm.rtm_msglen = len;
|
|
|
|
/* stuff that to the routing socket and wait for happy days */
|
|
if (rump_sys_write(s, &m_rtmsg, len, &error) != len)
|
|
errx(1, "routing incomplete %d (%s)", error, strerror(error));
|
|
rump_sys_close(s, &error);
|
|
}
|
|
#endif /* FULL_NETWORK_STACK */
|
|
|
|
int
|
|
main()
|
|
{
|
|
char buf[65536];
|
|
struct sockaddr_in sin;
|
|
struct timeval tv;
|
|
ssize_t n;
|
|
size_t off;
|
|
int s, error;
|
|
|
|
if (rump_init())
|
|
errx(1, "rump_init failed");
|
|
|
|
#ifdef FULL_NETWORK_STACK
|
|
configure_interface();
|
|
#endif
|
|
|
|
s = rump_sys___socket30(PF_INET, SOCK_STREAM, 0, &error);
|
|
if (s == -1)
|
|
errx(1, "can't open socket: %d (%s)", error, strerror(error));
|
|
|
|
tv.tv_sec = 5;
|
|
tv.tv_usec = 0;
|
|
if (rump_sys_setsockopt(s, SOL_SOCKET, SO_RCVTIMEO,
|
|
&tv, sizeof(tv), &error) == -1)
|
|
errx(1, "setsockopt %d (%s)", error, strerror(error));
|
|
|
|
memset(&sin, 0, sizeof(sin));
|
|
sin.sin_family = AF_INET;
|
|
sin.sin_port = htons(DEST_PORT);
|
|
sin.sin_addr.s_addr = inet_addr(DEST_ADDR);
|
|
|
|
if (rump_sys_connect(s, (struct sockaddr *)&sin, sizeof(sin),
|
|
&error) == -1) {
|
|
errx(1, "connect failed: %d (%s)", error, strerror(error));
|
|
}
|
|
|
|
printf("connected\n");
|
|
|
|
strcpy(buf, "GET / HTTP/1.0\n\n");
|
|
n = rump_sys_write(s, buf, strlen(buf), &error);
|
|
if (n != strlen(buf))
|
|
errx(1, "wrote only %zd vs. %zu (%s)\n",
|
|
n, strlen(buf), strerror(error));
|
|
|
|
memset(buf, 0, sizeof(buf));
|
|
for (off = 0; off < sizeof(buf) && n > 0;) {
|
|
n = rump_sys_read(s, buf+off, sizeof(buf)-off, &error);
|
|
if (n > 0)
|
|
off += n;
|
|
}
|
|
printf("read %zd (max %zu):\n", off, sizeof(buf));
|
|
printf("%s", buf);
|
|
|
|
return 0;
|
|
}
|