int main(int argc, char **argv) { struct sockaddr_in from, to, in; char buf[TESTLEN]; char *destip = DESTIP; int port = DEF_PORT; int n, server_socket, client_socket, fl, tl, pid; if (argc > 1) destip = argv[1]; if (argc > 2) port = atoi(argv[2]); in.sin_family = AF_INET; #ifdef NEED_SIN_LEN in.sin_len = sizeof( struct sockaddr_in ); #endif in.sin_addr.s_addr = INADDR_ANY; in.sin_port = htons(port); fl = tl = sizeof(struct sockaddr_in); memset(&from, 0, sizeof(from)); memset(&to, 0, sizeof(to)); switch(pid = fork()) { case -1: perror("fork"); return 0; case 0: /* child */ usleep(100000); goto client; } /* parent: server */ server_socket = safe_socket(PF_INET, SOCK_DGRAM, 0); if (udpfromto_init(server_socket) != 0) { perror("udpfromto_init\n"); waitpid(pid, NULL, WNOHANG); return 0; } if (bind(server_socket, (struct sockaddr *)&in, sizeof(in)) < 0) { perror("server: bind"); waitpid(pid, NULL, WNOHANG); return 0; } printf("server: waiting for packets on INADDR_ANY:%d\n", port); if ((n = recvfromto(server_socket, buf, sizeof(buf), 0, (struct sockaddr *)&from, &fl, (struct sockaddr *)&to, &tl)) < 0) { perror("server: recvfromto"); waitpid(pid, NULL, WNOHANG); return 0; } printf("server: received a packet of %d bytes [%s] ", n, buf); printf("(src ip:port %s:%d ", inet_ntoa(from.sin_addr), ntohs(from.sin_port)); printf(" dst ip:port %s:%d)\n", inet_ntoa(to.sin_addr), ntohs(to.sin_port)); printf("server: replying from address packet was received on to source address\n"); if ((n = sendfromto(server_socket, buf, n, 0, (struct sockaddr *)&to, tl, (struct sockaddr *)&from, fl)) < 0) { perror("server: sendfromto"); } waitpid(pid, NULL, 0); return 0; client: close(server_socket); client_socket = safe_socket(PF_INET, SOCK_DGRAM, 0); if (udpfromto_init(client_socket) != 0) { perror("udpfromto_init"); _exit(0); } /* bind client on different port */ in.sin_port = htons(port+1); if (bind(client_socket, (struct sockaddr *)&in, sizeof(in)) < 0) { perror("client: bind"); _exit(0); } in.sin_port = htons(port); in.sin_addr.s_addr = inet_addr(destip); printf("client: sending packet to %s:%d\n", destip, port); if (sendto(client_socket, TESTSTRING, TESTLEN, 0, (struct sockaddr *)&in, sizeof(in)) < 0) { perror("client: sendto"); _exit(0); } printf("client: waiting for reply from server on INADDR_ANY:%d\n", port+1); if ((n = recvfromto(client_socket, buf, sizeof(buf), 0, (struct sockaddr *)&from, &fl, (struct sockaddr *)&to, &tl)) < 0) { perror("client: recvfromto"); _exit(0); } printf("client: received a packet of %d bytes [%s] ", n, buf); printf("(src ip:port %s:%d", inet_ntoa(from.sin_addr), ntohs(from.sin_port)); printf(" dst ip:port %s:%d)\n", inet_ntoa(to.sin_addr), ntohs(to.sin_port)); _exit(0); }
/* * Open a socket on the given IP and port. */ int fr_socket(fr_ipaddr_t *ipaddr, int port) { int sockfd; struct sockaddr_storage salocal; socklen_t salen; if ((port < 0) || (port > 65535)) { fr_strerror_printf("Port %d is out of allowed bounds", port); return -1; } sockfd = socket(ipaddr->af, SOCK_DGRAM, 0); if (sockfd < 0) { fr_strerror_printf("cannot open socket: %s", strerror(errno)); return sockfd; } #ifdef WITH_UDPFROMTO /* * Initialize udpfromto for all sockets. */ if (udpfromto_init(sockfd) != 0) { close(sockfd); fr_strerror_printf("cannot initialize udpfromto: %s", strerror(errno)); return -1; } #endif if (!fr_ipaddr2sockaddr(ipaddr, port, &salocal, &salen)) { return sockfd; } #ifdef HAVE_STRUCT_SOCKADDR_IN6 if (ipaddr->af == AF_INET6) { /* * Listening on '::' does NOT get you IPv4 to * IPv6 mapping. You've got to listen on an IPv4 * address, too. This makes the rest of the server * design a little simpler. */ #ifdef IPV6_V6ONLY if (IN6_IS_ADDR_UNSPECIFIED(&ipaddr->ipaddr.ip6addr)) { int on = 1; setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&on, sizeof(on)); } #endif /* IPV6_V6ONLY */ } #endif /* HAVE_STRUCT_SOCKADDR_IN6 */ if (ipaddr->af == AF_INET) { UNUSED int flag; #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) /* * Disable PMTU discovery. On Linux, this * also makes sure that the "don't fragment" * flag is zero. */ flag = IP_PMTUDISC_DONT; setsockopt(sockfd, IPPROTO_IP, IP_MTU_DISCOVER, &flag, sizeof(flag)); #endif #if defined(IP_DONTFRAG) /* * Ensure that the "don't fragment" flag is zero. */ flag = 0; setsockopt(sockfd, IPPROTO_IP, IP_DONTFRAG, &flag, sizeof(flag)); #endif } if (bind(sockfd, (struct sockaddr *) &salocal, salen) < 0) { close(sockfd); fr_strerror_printf("cannot bind socket: %s", strerror(errno)); return -1; } return sockfd; }