3 * NAT type testing (server).
5 * Created by Gertjan Halkes.
6 * Copyright 2010 Delft University of Technology. All rights reserved.
10 //FIXME: add timestamp to log output
17 #include <sys/types.h>
18 #include <sys/socket.h>
19 #include <netinet/ip.h>
20 #include <arpa/inet.h>
23 #define REQUEST_MAGIC 0x5a9e5fa1
24 #define REPLY_MAGIC 0xa655c5d5
25 #define REPLY_SEC_MAGIC 0x85e4a5ca
27 static int has_secondary;
29 /** Alert the user of a fatal error and quit.
30 @param fmt The format string for the message. See fprintf(3) for details.
31 @param ... The arguments for printing.
33 void fatal(const char *fmt, ...) {
37 vfprintf(stderr, fmt, args);
42 const char *getTimestamp(void) {
43 static char timeBuffer[1024];
47 gettimeofday(&now, NULL);
48 nowF = (double) now.tv_sec + (double) now.tv_usec / 1000000;
49 snprintf(timeBuffer, 1024, "%.4f", nowF);
53 int main(int argc, char *argv[]) {
54 struct sockaddr_in local, remote, secondary;
56 int c, sock, sock2, sock3, sock4;
59 local.sin_addr.s_addr = INADDR_ANY;
61 while ((c = getopt(argc, argv, "s:")) > 0) {
65 secondary.sin_addr.s_addr = inet_addr(optarg);
68 fatal("Unknown option %c\n", c);
73 if (argc - optind != 3)
74 fatal("Usage: nat_test_server [<options>] <primary address> <primary port> <secondary port>\n");
76 local.sin_family = AF_INET;
77 local.sin_addr.s_addr = inet_addr(argv[optind++]);
78 local.sin_port = htons(atoi(argv[optind++]));
80 if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
81 fatal("Error opening primary socket: %m\n");
82 if (bind(sock, (struct sockaddr *) &local, sizeof(local)) < 0)
83 fatal("Error binding primary socket: %m\n");
86 secondary.sin_family = AF_INET;
87 secondary.sin_port = local.sin_port;
89 if ((sock3 = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
90 fatal("Error opening primary socket on secondary address: %m\n");
91 if (bind(sock3, (struct sockaddr *) &secondary, sizeof(secondary)) < 0)
92 fatal("Error binding primary socket on secondary address: %m\n");
95 local.sin_port = htons(atoi(argv[optind++]));
97 if ((sock2 = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
98 fatal("Error opening secondary socket: %m\n");
99 if (bind(sock2, (struct sockaddr *) &local, sizeof(local)) < 0)
100 fatal("Error binding secondary socket: %m\n");
103 secondary.sin_port = local.sin_port;
105 if ((sock4 = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
106 fatal("Error opening secondary socket on secondary address: %m\n");
107 if (bind(sock4, (struct sockaddr *) &secondary, sizeof(secondary)) < 0)
108 fatal("Error binding secondary socket on secondary address: %m\n");
112 socklen_t socklen = sizeof(remote);
113 if ((result = recvfrom(sock, &packet, sizeof(packet), 0, (struct sockaddr *) &remote, &socklen)) < 0) {
116 fatal("%s: Error receiving packet: %m\n", getTimestamp());
117 } else if (result != 4 || ntohl(packet[0]) != REQUEST_MAGIC) {
118 fprintf(stderr, "Strange packet received from %s\n", inet_ntoa(remote.sin_addr));
120 fprintf(stderr, "%s: Received packet from %s:%d\n", getTimestamp(), inet_ntoa(remote.sin_addr), ntohs(remote.sin_port));
121 packet[0] = htonl(REPLY_MAGIC);
122 packet[1] = remote.sin_addr.s_addr;
123 *(uint16_t *)(packet + 2) = remote.sin_port;
125 if (sendto(sock, packet, 10, 0, (const struct sockaddr *) &remote, socklen) < 10) {
128 fprintf(stderr, "%s: Error sending packet on primary socket: %m\n", getTimestamp());
131 if (sendto(sock2, packet, 10, 0, (const struct sockaddr *) &remote, socklen) < 10) {
134 fprintf(stderr, "%s: Error sending packet on secondary socket: %m\n", getTimestamp());
138 packet[0] = htonl(REPLY_SEC_MAGIC);
140 if (sendto(sock3, packet, 4, 0, (const struct sockaddr *) &remote, socklen) < 4) {
143 fprintf(stderr, "%s: Error sending packet on primary socket on secondary address: %m\n", getTimestamp());
146 if (sendto(sock4, packet, 4, 0, (const struct sockaddr *) &remote, socklen) < 4) {
149 fprintf(stderr, "%s: Error sending packet on secondary socket on secondary address: %m\n", getTimestamp());