Multicast 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;
54 struct sockaddr_in nm;
55 struct ip_mreqn mreq;
56
57 fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
58 memset(&nm, 0, sizeof(nm));
59 nm.sin_family = AF_INET;
60 nm.sin_port = htons(port);
61 if(bind(fd, (struct sockaddr *)&nm, sizeof(nm)))
62 return(-1);
63 memset(&mreq, 0, sizeof(mreq));
64 mreq.imr_multiaddr = group;
65 if(setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)))
66 return(-1);
67 return(fd);
68}
69
70static void test(int fd)
71{
72 char buf[65536];
73 int ret;
74 struct sockaddr_storage nm;
75 socklen_t nmlen;
76
77 while(1) {
78 nmlen = sizeof(nm);
79 ret = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&nm, &nmlen);
80 if(ret < 0) {
81 fprintf(stderr, "mctap: recvfrom: %s\n", strerror(ret));
82 exit(1);
83 }
84 printf("%s %i:\n", formataddress((struct sockaddr *)&nm, nmlen), ret);
85 }
3415540f
FT
86}
87
88int main(int argc, char **argv)
89{
90 int c;
b5038e15
FT
91 int sock;
92 struct in_addr group;
93 int port;
3415540f 94
b5038e15 95 while((c = getopt(argc, argv, "h")) >= 0) {
3415540f
FT
96 switch(c) {
97 case 'h':
98 usage(stdout);
99 return(0);
100 default:
101 usage(stderr);
102 exit(1);
103 }
104 }
b5038e15
FT
105 if(argc - optind < 2) {
106 usage(stderr);
107 exit(1);
108 }
109 if(!inet_aton(argv[optind], &group)) {
110 fprintf(stderr, "mctap: invalid group address: %s\n", argv[optind]);
111 exit(1);
112 }
113 port = atoi(argv[optind + 1]);
114 if((sock = mkmcastsk4(group, port)) < 0) {
115 fprintf(stderr, "mctap: could not create multicast socket: %s\n", strerror(errno));
116 exit(1);
117 }
3415540f 118
b5038e15 119 test(sock);
3415540f
FT
120 return(0);
121}