1160996Ssam/*-
2160996Ssam * Copyright (c) 2006, Andrea Bittau <a.bittau@cs.ucl.ac.uk>
3160996Ssam * All rights reserved.
4160996Ssam *
5160996Ssam * Redistribution and use in source and binary forms, with or without
6160996Ssam * modification, are permitted provided that the following conditions
7160996Ssam * are met:
8160996Ssam * 1. Redistributions of source code must retain the above copyright
9160996Ssam *    notice, this list of conditions and the following disclaimer.
10160996Ssam * 2. Redistributions in binary form must reproduce the above copyright
11160996Ssam *    notice, this list of conditions and the following disclaimer in the
12160996Ssam *    documentation and/or other materials provided with the distribution.
13160996Ssam *
14160996Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15160996Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16160996Ssam * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17160996Ssam * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18160996Ssam * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19160996Ssam * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20160996Ssam * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21160996Ssam * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22160996Ssam * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23160996Ssam * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24160996Ssam * SUCH DAMAGE.
25160996Ssam *
26160996Ssam * $FreeBSD$
27160996Ssam */
28160996Ssam#include <sys/uio.h>
29160996Ssam#include <sys/types.h>
30160996Ssam#include <sys/socket.h>
31160996Ssam#include <netinet/in_systm.h>
32160996Ssam#include <netinet/in.h>
33160996Ssam#include <arpa/inet.h>
34160996Ssam#include <netinet/ip.h>
35160996Ssam#include <stdio.h>
36160996Ssam#include <stdlib.h>
37160996Ssam#include <string.h>
38160996Ssam#include <unistd.h>
39160996Ssam#include <fcntl.h>
40160996Ssam#include <errno.h>
41160996Ssam#include <signal.h>
42160996Ssam#include <err.h>
43160996Ssam
44160996Ssamvoid hexdump(void *b, int len)
45160996Ssam{
46160996Ssam        unsigned char *p = (unsigned char*) b;
47160996Ssam
48160996Ssam        while (len--)
49160996Ssam                printf("%.2X ", *p++);
50160996Ssam        printf("\n");
51160996Ssam}
52160996Ssam
53160996Ssamint handle_data(int dude, char *buf, int len)
54160996Ssam{
55160996Ssam	struct ip *ih;
56160996Ssam	unsigned short id;
57160996Ssam	char tmp[4];
58160996Ssam	struct iovec iov[2];
59160996Ssam	struct msghdr mh;
60160996Ssam
61160996Ssam	ih = (struct ip*) buf;
62160996Ssam
63160996Ssam	/* XXX IP FRAGS */
64160996Ssam
65160996Ssam	/* filter */
66160996Ssam	if (ih->ip_p != 0)
67160996Ssam		return 0;
68160996Ssam
69160996Ssam	if (ih->ip_hl != 5)
70160996Ssam		return 0;
71160996Ssam
72160996Ssam	/* get info */
73160996Ssam	id = ih->ip_id;
74160996Ssam	len -= 20;
75160996Ssam	buf += 20;
76160996Ssam	printf("Got %d bytes [%d]\n", len, ntohs(id));
77160996Ssam#if 0
78160996Ssam	hexdump(buf, len);
79160996Ssam#endif
80160996Ssam
81160996Ssam	/* prepare packet */
82160996Ssam	memcpy(tmp, &id, 2);
83160996Ssam	id = htons(len);
84160996Ssam	memcpy(&tmp[2], &id, 2);
85160996Ssam
86160996Ssam	iov[0].iov_base = tmp;
87160996Ssam	iov[0].iov_len = 4;
88160996Ssam	iov[1].iov_base = buf;
89160996Ssam	iov[1].iov_len = len;
90160996Ssam
91160996Ssam	memset(&mh, 0, sizeof(mh));
92160996Ssam	mh.msg_iov = iov;
93160996Ssam	mh.msg_iovlen = sizeof(iov)/sizeof(struct iovec);
94160996Ssam
95160996Ssam	/* write */
96160996Ssam	if (sendmsg(dude, &mh, 0) != (4 + len))
97160996Ssam		return -1;
98160996Ssam	return 0;
99160996Ssam}
100160996Ssam
101160996Ssamvoid handle_dude(int dude, int raw)
102160996Ssam{
103160996Ssam	char buf[4096];
104160996Ssam	int rd;
105160996Ssam
106160996Ssam	while (1) {
107160996Ssam		rd = recv(raw, buf, sizeof(buf), 0);
108160996Ssam		if (rd == -1)
109160996Ssam			err(1, "recv()");
110160996Ssam
111160996Ssam		if (handle_data(dude, buf, rd) == -1)
112160996Ssam			return;
113160996Ssam	}
114160996Ssam}
115160996Ssam
116160996Ssamvoid hand(int s)
117160996Ssam{
118160996Ssam	printf("sigpipe\n");
119160996Ssam}
120160996Ssam
121160996Ssamint main(int argc, char *argv[])
122160996Ssam{
123160996Ssam	int s, dude;
124160996Ssam	struct sockaddr_in s_in;
125160996Ssam	int len;
126160996Ssam	int raw;
127160996Ssam
128160996Ssam	memset(&s_in, 0, sizeof(&s_in));
129160996Ssam	s_in.sin_family = PF_INET;
130160996Ssam	s_in.sin_port = htons(666);
131160996Ssam	s_in.sin_addr.s_addr = INADDR_ANY;
132160996Ssam
133160996Ssam	if ((raw = socket(PF_INET, SOCK_RAW, 0)) == -1)
134160996Ssam		err(1, "socket()");
135160996Ssam
136160996Ssam	if ((s = socket(s_in.sin_family, SOCK_STREAM, IPPROTO_TCP)) == -1)
137160996Ssam		err(1, "socket()");
138160996Ssam
139160996Ssam	if (bind(s, (struct sockaddr*)&s_in, sizeof(s_in)) == -1)
140160996Ssam		err(1, "bind()");
141160996Ssam
142160996Ssam	if (listen(s, 5) == -1)
143160996Ssam		err(1, "listen()");
144160996Ssam
145160996Ssam	if (signal(SIGPIPE, hand) == SIG_ERR)
146160996Ssam		err(1, "signal()");
147160996Ssam
148160996Ssam	while (1) {
149160996Ssam		len = sizeof(s_in);
150160996Ssam		dude = accept(s, (struct sockaddr*)&s_in, &len);
151160996Ssam		if (dude == -1)
152160996Ssam			err(1, "accept()");
153160996Ssam
154160996Ssam		printf("Got dude %s\n", inet_ntoa(s_in.sin_addr));
155160996Ssam		handle_dude(dude, raw);
156160996Ssam		printf("Done\n");
157160996Ssam	}
158160996Ssam}
159