Print packet contents from test code.
[mctap.git] / src / mctap.c
CommitLineData
3415540f
FT
1#include <stdlib.h>
2#include <stdio.h>
3#include <string.h>
4#include <unistd.h>
5#include <sys/socket.h>
6#include <netinet/in.h>
b5038e15
FT
7#include <arpa/inet.h>
8#include <errno.h>
9
10#include "utils.h"
3415540f
FT
11
12static void usage(FILE *out)
13{
b5038e15
FT
14 fprintf(out, "usage: mctap [-h] MCASTGROUP PORT\n");
15}
16
17static char *formataddress(struct sockaddr *arg, socklen_t arglen)
18{
19 struct sockaddr_in *ipv4;
20 struct sockaddr_in6 *ipv6;
21 static char *ret = NULL;
22 char buf[1024];
23
24 if(ret != NULL)
25 free(ret);
26 ret = NULL;
27 switch(arg->sa_family)
28 {
29 case AF_UNIX:
30 ret = strdup("Unix socket");
31 break;
32 case AF_INET:
33 ipv4 = (struct sockaddr_in *)arg;
34 if(inet_ntop(AF_INET, &ipv4->sin_addr, buf, sizeof(buf)) == NULL)
35 return(NULL);
36 ret = sprintf2("%s:%i", buf, (int)ntohs(ipv4->sin_port));
37 break;
38 case AF_INET6:
39 ipv6 = (struct sockaddr_in6 *)arg;
40 if(inet_ntop(AF_INET6, &ipv6->sin6_addr, buf, sizeof(buf)) == NULL)
41 return(NULL);
42 ret = sprintf2("[%s]:%i", buf, (int)ntohs(ipv6->sin6_port));
43 break;
44 default:
45 errno = EPFNOSUPPORT;
46 break;
47 }
48 return(ret);
49}
50
51static int mkmcastsk4(struct in_addr group, int port)
52{
53 int fd;
aeddd223 54 int soval;
b5038e15
FT
55 struct sockaddr_in nm;
56 struct ip_mreqn mreq;
57
58 fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
aeddd223
FT
59 soval = 1;
60 if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &soval, sizeof(soval)))
61 return(-1);
b5038e15
FT
62 memset(&nm, 0, sizeof(nm));
63 nm.sin_family = AF_INET;
64 nm.sin_port = htons(port);
65 if(bind(fd, (struct sockaddr *)&nm, sizeof(nm)))
66 return(-1);
67 memset(&mreq, 0, sizeof(mreq));
68 mreq.imr_multiaddr = group;
aeddd223 69 if(setsockopt(fd, SOL_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)))
b5038e15 70 return(-1);
af3fc4a5
FT
71 soval = 1;
72 if(setsockopt(fd, SOL_IP, IP_MULTICAST_LOOP, &soval, sizeof(soval)))
73 return(-1);
b5038e15
FT
74 return(fd);
75}
76
77static void test(int fd)
78{
79 char buf[65536];
4f6c7408 80 int i, ret;
b5038e15
FT
81 struct sockaddr_storage nm;
82 socklen_t nmlen;
83
84 while(1) {
85 nmlen = sizeof(nm);
86 ret = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&nm, &nmlen);
87 if(ret < 0) {
88 fprintf(stderr, "mctap: recvfrom: %s\n", strerror(ret));
89 exit(1);
90 }
91 printf("%s %i:\n", formataddress((struct sockaddr *)&nm, nmlen), ret);
4f6c7408
FT
92 for(i = 0; i < ret; i++) {
93 printf("%02x ", (unsigned char)buf[i]);
94 if(i % 20 == 0)
95 putchar(10);
96 }
b5038e15 97 }
3415540f
FT
98}
99
100int main(int argc, char **argv)
101{
102 int c;
b5038e15
FT
103 int sock;
104 struct in_addr group;
105 int port;
3415540f 106
b5038e15 107 while((c = getopt(argc, argv, "h")) >= 0) {
3415540f
FT
108 switch(c) {
109 case 'h':
110 usage(stdout);
111 return(0);
112 default:
113 usage(stderr);
114 exit(1);
115 }
116 }
b5038e15
FT
117 if(argc - optind < 2) {
118 usage(stderr);
119 exit(1);
120 }
121 if(!inet_aton(argv[optind], &group)) {
122 fprintf(stderr, "mctap: invalid group address: %s\n", argv[optind]);
123 exit(1);
124 }
125 port = atoi(argv[optind + 1]);
126 if((sock = mkmcastsk4(group, port)) < 0) {
127 fprintf(stderr, "mctap: could not create multicast socket: %s\n", strerror(errno));
128 exit(1);
129 }
3415540f 130
b5038e15 131 test(sock);
3415540f
FT
132 return(0);
133}