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 12static char *prog; 13static int errors; 14 15static int join_group(int, char *, struct ip_mreq *); 16static int leave_group(int, char *, struct ip_mreq *); 17static void usage(void); 18 19int 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 109static 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 144static 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 178static 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