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 17 const unsigned short TEST_PROTOCOL = 89; 18 19 20 void 21 recvLoop(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 49 int 50 main(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