1/*
2 * Copyright 2010, Atis Elsts, the.kfx@gmail.com
3 * Distributed under the terms of the MIT license.
4 */
5
6
7#include <unistd.h>
8#include <memory.h>
9#include <netinet/in.h>
10#include <netinet/ip.h>
11#include <arpa/inet.h>
12#include <errno.h>
13#include <stdio.h>
14#include <stdlib.h>
15
16
17const unsigned short TEST_PROTOCOL = 89;
18
19
20void
21recvLoop(int fd)
22{
23	for (;;) {
24		char buffer[1000];
25		sockaddr_storage address;
26		socklen_t socklen = sizeof(address);
27		memset(&address, 0, socklen);
28
29		int status = recvfrom(fd, buffer, sizeof(buffer) - 1, 0,
30			(sockaddr *) &address, &socklen);
31		if (status < 0) {
32			perror("recvfrom");
33			exit(-1);
34		}
35		if (status == 0) {
36			printf("received EOF!\n");
37			break;
38		} else {
39			char *p = buffer;
40			if (address.ss_family == AF_INET && status >= sizeof(struct ip))
41				p += sizeof(struct ip);
42			buffer[status] = 0;
43			printf("received %d bytes: \"%s\"\n", status, p);
44		}
45	}
46}
47
48
49int
50main(int argc, char *argv[])
51{
52	int socketFamily = AF_INET;
53
54	if (argc > 1) {
55		if (!strcmp(argv[1], "-4"))
56			socketFamily = AF_INET;
57		else if (!strcmp(argv[1], "-6"))
58			socketFamily = AF_INET6;
59	}
60
61	int fd = socket(socketFamily, SOCK_RAW, TEST_PROTOCOL);
62	if (fd < 0) {
63		perror("socket");
64		return -1;
65	}
66
67	sockaddr_storage localAddress;
68	memset(&localAddress, 0, sizeof(localAddress));
69	if (socketFamily == AF_INET) {
70		sockaddr_in *sa = (sockaddr_in *) &localAddress;
71		sa->sin_family = AF_INET;
72	} else {
73		sockaddr_in6 *sa = (sockaddr_in6 *) &localAddress;
74		sa->sin6_family = AF_INET6;
75	}
76
77	// TODO: is this even necessary?
78	if (bind(fd, (sockaddr *)&localAddress, socketFamily == AF_INET ?
79			sizeof(sockaddr_in) : sizeof(sockaddr_in6)) < 0) {
80		perror("bind");
81		return -1;
82	}
83
84	for (;;)
85		recvLoop(fd);
86}
87