1 #include <sys/types.h> 2 #include <sys/socket.h> 3 4 #include <arpa/inet.h> 5 #include <netinet/in.h> 6 7 #include <err.h> 8 #include <stdint.h> 9 #include <stdio.h> 10 #include <stdlib.h> 11 #include <string.h> 12 #include <unistd.h> 13 14 static void 15 usage(const char *cmd) 16 { 17 fprintf(stderr, "%s -m addr -p port -i addr " 18 "-r remote_ip4 -P remote_port\n", cmd); 19 exit(1); 20 } 21 22 static int 23 create_sock(const struct sockaddr_in *in, const struct in_addr *iface) 24 { 25 struct ip_mreq mreq; 26 int s, on; 27 28 s = socket(AF_INET, SOCK_DGRAM, 0); 29 if (s < 0) 30 err(2, "socket failed"); 31 32 on = 1; 33 if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0) 34 err(2, "setsockopt SO_REUSEPORT failed"); 35 36 if (bind(s, (const struct sockaddr *)in, sizeof(*in)) < 0) 37 err(2, "bind failed"); 38 39 memset(&mreq, 0, sizeof(mreq)); 40 mreq.imr_multiaddr = in->sin_addr; 41 mreq.imr_interface = *iface; 42 if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, 43 &mreq, sizeof(mreq)) < 0) 44 err(2, "setsockopt IP_ADD_MEMBERSHIP failed"); 45 46 return s; 47 } 48 49 int 50 main(int argc, char *argv[]) 51 { 52 struct sockaddr_in in, remote_in; 53 struct in_addr iface; 54 int s1, s2, opt, n; 55 uint8_t buf[18]; 56 57 memset(&in, 0, sizeof(in)); 58 in.sin_family = AF_INET; 59 60 memset(&remote_in, 0, sizeof(remote_in)); 61 remote_in.sin_family = AF_INET; 62 63 memset(&iface, 0, sizeof(iface)); 64 65 while ((opt = getopt(argc, argv, "P:i:m:p:r:")) != -1) { 66 switch (opt) { 67 case 'P': 68 remote_in.sin_port = strtol(optarg, NULL, 10); 69 remote_in.sin_port = htons(remote_in.sin_port); 70 break; 71 72 case 'i': 73 if (inet_pton(AF_INET, optarg, &iface) <= 0) 74 usage(argv[0]); 75 break; 76 77 case 'm': 78 if (inet_pton(AF_INET, optarg, &in.sin_addr) <= 0) 79 usage(argv[0]); 80 break; 81 82 case 'p': 83 in.sin_port = strtol(optarg, NULL, 10); 84 in.sin_port = htons(in.sin_port); 85 break; 86 87 case 'r': 88 if (inet_pton(AF_INET, optarg, 89 &remote_in.sin_addr) <= 0) 90 usage(argv[0]); 91 break; 92 93 default: 94 usage(argv[0]); 95 } 96 } 97 98 if (in.sin_addr.s_addr == INADDR_ANY || in.sin_port == 0 || 99 iface.s_addr == INADDR_ANY || 100 remote_in.sin_addr.s_addr == INADDR_ANY || 101 remote_in.sin_port == 0) 102 usage(argv[0]); 103 104 s1 = create_sock(&in, &iface); 105 s2 = create_sock(&in, &iface); 106 107 if (connect(s2, (const struct sockaddr *)&remote_in, 108 sizeof(remote_in)) < 0) 109 err(2, "connect failed"); 110 111 n = read(s1, buf, sizeof(buf)); 112 if (n < 0) 113 err(2, "read 1 failed"); 114 fprintf(stderr, "read 1 got %d\n", n); 115 116 n = read(s2, buf, sizeof(buf)); 117 if (n < 0) 118 err(2, "read 2 failed"); 119 fprintf(stderr, "read 2 got %d\n", n); 120 121 exit(0); 122 } 123