1 #include <arpa/inet.h>
2 #include <sys/types.h>
3 #include <sys/socket.h>
4 #include <netinet/in.h>
5 #include <errno.h>
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <netdb.h>
10 #include <unistd.h>
11
12 static char *prog;
13 static int errors;
14
15 static int join_group(int, char *, struct ip_mreq *);
16 static int leave_group(int, char *, struct ip_mreq *);
17 static void usage(void);
18
main(int argc,char * argv[])19 int main(int argc, char *argv[])
20 {
21 int s;
22 struct ip_mreq imr;
23
24 char *group_list = NULL, *interface = NULL;
25 unsigned i1, i2, i3, i4;
26 struct hostent *hp, *gethostbyname();
27 int c;
28 int lflg = 0, jflg = 0, sflg = 0;
29
30 prog = argv[0];
31 if (argc == 1)
32 usage();
33
34 while ((c = getopt(argc, argv, "jlg:s:i:")) != EOF)
35 switch (c) {
36 case 'j':
37 if (lflg)
38 usage();
39 else
40 jflg++;
41 break;
42 case 'l':
43 if (jflg)
44 usage();
45 else
46 lflg++;
47 break;
48 case 'g':
49 group_list = optarg;
50 break;
51 case 's':
52 sflg = atoi(optarg);
53 break;
54 case 'i':
55 interface = optarg;
56 break;
57 case '?':
58 usage();
59 }
60
61 if (optind != argc)
62 usage();
63
64 if (access(group_list, R_OK) != 0) {
65 printf("Unabled to read group file %s\n", group_list);
66 exit(1);
67 }
68
69 s = socket(AF_INET, SOCK_DGRAM, 0);
70 if (s == -1) {
71 perror("can not open socket");
72 exit(1);
73 }
74
75 hp = gethostbyname(interface);
76 if (hp != NULL) {
77 memcpy(&imr.imr_interface.s_addr, hp->h_addr, hp->h_length);
78 } else if (sscanf(interface, "%u.%u.%u.%u", &i1, &i2, &i3, &i4) != 4) {
79 fprintf(stderr, "bad group address\n");
80 exit(1);
81 } else {
82 imr.imr_interface.s_addr =
83 htonl((i1 << 24) | (i2 << 16) | (i3 << 8) | i4);
84 }
85 /* verify socket options */
86 if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF,
87 &imr.imr_interface.s_addr,
88 sizeof(imr.imr_interface.s_addr)) != 0) {
89 fprintf(stderr,
90 "Error: unable to set socket option IP_MULTICAST_IF\n");
91 errors++;
92 } else
93 printf("Socket set for Multicasting on: %s\n", interface);
94
95 if ((!jflg && !lflg) || jflg)
96 join_group(s, group_list, &imr);
97
98 sleep(sflg);
99
100 if ((!jflg && !lflg) || lflg)
101 leave_group(s, group_list, &imr);
102
103 close(s);
104 if (errors)
105 exit(1);
106 return 0;
107 }
108
join_group(int s,char * glist,struct ip_mreq * imr)109 static int join_group(int s, char *glist, struct ip_mreq *imr)
110 {
111 char buf[40];
112 unsigned g1, g2, g3, g4;
113 FILE *fd;
114 char group[40], itf[40];
115
116 fd = fopen(glist, "r");
117 if (fd == NULL)
118 printf("Error: unable to open %s\n", glist);
119
120 while (fgets(buf, sizeof(buf), fd) != NULL) {
121 if (sscanf(buf, "%u.%u.%u.%u", &g1, &g2, &g3, &g4) != 4) {
122 fprintf(stderr, "bad group address\n");
123 exit(1);
124 }
125
126 imr->imr_multiaddr.s_addr =
127 htonl((g1 << 24) | (g2 << 16) | (g3 << 8) | g4);
128
129 if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP,
130 imr, sizeof(struct ip_mreq)) == -1) {
131 fprintf(stderr, "errno is %d\n", errno);
132 perror("can't join group");
133 errors++;
134 } else {
135 strcpy(group, inet_ntoa(imr->imr_multiaddr));
136 strcpy(itf, inet_ntoa(imr->imr_interface));
137 printf("IPM group: %s added to interface: %s\n", group,
138 itf);
139 }
140 }
141 return 0;
142 }
143
leave_group(int s,char * glist,struct ip_mreq * imr)144 static int leave_group(int s, char *glist, struct ip_mreq *imr)
145 {
146 char buf[40];
147 unsigned g1, g2, g3, g4;
148 FILE *fd;
149 char group[40], itf[40];
150
151 fd = fopen(glist, "r");
152 if (fd == NULL)
153 printf("Error: unable to open %s\n", glist);
154
155 while (fgets(buf, sizeof(buf), fd) != NULL) {
156 if (sscanf(buf, "%u.%u.%u.%u", &g1, &g2, &g3, &g4) != 4) {
157 fprintf(stderr, "leave_group: bad group address\n");
158 exit(1);
159 }
160
161 imr->imr_multiaddr.s_addr =
162 htonl((g1 << 24) | (g2 << 16) | (g3 << 8) | g4);
163
164 if (setsockopt(s, IPPROTO_IP, IP_DROP_MEMBERSHIP,
165 imr, sizeof(struct ip_mreq)) == -1) {
166 perror("can't leave group");
167 errors++;
168 } else {
169 strcpy(group, inet_ntoa(imr->imr_multiaddr));
170 strcpy(itf, inet_ntoa(imr->imr_interface));
171 printf("IPM group: %s dropped from interface: %s\n",
172 group, itf);
173 }
174 }
175 return 0;
176 }
177
usage(void)178 static void usage(void)
179 {
180 fprintf(stderr,
181 "usage: %s [ -j -l ] -g group_list [-s time_to_sleep] -i interface_name (or i.i.i.i)\n",
182 prog);
183 exit(1);
184 }
185