1e2c3f7afd092b0a20c3417954cc4fc6f7e6cc6c7robbiew#include <arpa/inet.h> 2865695bbc89088b9526ea9045410e5afb70a985cplars#include <sys/types.h> 3865695bbc89088b9526ea9045410e5afb70a985cplars#include <sys/socket.h> 4865695bbc89088b9526ea9045410e5afb70a985cplars#include <netinet/in.h> 5865695bbc89088b9526ea9045410e5afb70a985cplars#include <errno.h> 6865695bbc89088b9526ea9045410e5afb70a985cplars#include <stdio.h> 7e2c3f7afd092b0a20c3417954cc4fc6f7e6cc6c7robbiew#include <stdlib.h> 8e2c3f7afd092b0a20c3417954cc4fc6f7e6cc6c7robbiew#include <string.h> 9865695bbc89088b9526ea9045410e5afb70a985cplars#include <netdb.h> 10865695bbc89088b9526ea9045410e5afb70a985cplars#include <unistd.h> 11865695bbc89088b9526ea9045410e5afb70a985cplars 12cb49919064fe0f527437fe0587dfc820290e4c35Zeng Linggangstatic char *prog; 13cb49919064fe0f527437fe0587dfc820290e4c35Zeng Linggangstatic int errors; 14865695bbc89088b9526ea9045410e5afb70a985cplars 15cb49919064fe0f527437fe0587dfc820290e4c35Zeng Linggangstatic int join_group(int, char *, struct ip_mreq *); 16cb49919064fe0f527437fe0587dfc820290e4c35Zeng Linggangstatic int leave_group(int, char *, struct ip_mreq *); 17cb49919064fe0f527437fe0587dfc820290e4c35Zeng Linggangstatic void usage(void); 18e2c3f7afd092b0a20c3417954cc4fc6f7e6cc6c7robbiew 19cb49919064fe0f527437fe0587dfc820290e4c35Zeng Linggangint main(int argc, char *argv[]) 202c28215423293e443469a07ae7011135d058b671Garrett Cooper{ 21354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao int s; 22354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct ip_mreq imr; 23865695bbc89088b9526ea9045410e5afb70a985cplars 24354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao char *group_list = NULL, *interface = NULL; 25354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao unsigned i1, i2, i3, i4; 26354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao struct hostent *hp, *gethostbyname(); 27cb49919064fe0f527437fe0587dfc820290e4c35Zeng Linggang int c; 28354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao int lflg = 0, jflg = 0, sflg = 0; 29354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 30354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao prog = argv[0]; 31354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (argc == 1) 32354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao usage(); 33354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 34354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao while ((c = getopt(argc, argv, "jlg:s:i:")) != EOF) 35354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao switch (c) { 36354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao case 'j': 37354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (lflg) 38354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao usage(); 39354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao else 40354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao jflg++; 41354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 42354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao case 'l': 43354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (jflg) 44354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao usage(); 45354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao else 46354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao lflg++; 47354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 48354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao case 'g': 49354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao group_list = optarg; 50354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 51354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao case 's': 52354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao sflg = atoi(optarg); 53354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 54354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao case 'i': 55354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao interface = optarg; 56354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao break; 57354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao case '?': 58354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao usage(); 59354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 60354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 61354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (optind != argc) 62354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao usage(); 63354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 64354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (access(group_list, R_OK) != 0) { 65354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao printf("Unabled to read group file %s\n", group_list); 66354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao exit(1); 67354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 68354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 69cb49919064fe0f527437fe0587dfc820290e4c35Zeng Linggang s = socket(AF_INET, SOCK_DGRAM, 0); 70cb49919064fe0f527437fe0587dfc820290e4c35Zeng Linggang if (s == -1) { 71354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao perror("can not open socket"); 72354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao exit(1); 73354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 74354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 75cb49919064fe0f527437fe0587dfc820290e4c35Zeng Linggang hp = gethostbyname(interface); 76cb49919064fe0f527437fe0587dfc820290e4c35Zeng Linggang if (hp != NULL) { 77354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao memcpy(&imr.imr_interface.s_addr, hp->h_addr, hp->h_length); 78cb49919064fe0f527437fe0587dfc820290e4c35Zeng Linggang } else if (sscanf(interface, "%u.%u.%u.%u", &i1, &i2, &i3, &i4) != 4) { 79354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, "bad group address\n"); 80354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao exit(1); 81cb49919064fe0f527437fe0587dfc820290e4c35Zeng Linggang } else { 82354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao imr.imr_interface.s_addr = 83354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao htonl((i1 << 24) | (i2 << 16) | (i3 << 8) | i4); 84cb49919064fe0f527437fe0587dfc820290e4c35Zeng Linggang } 85354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao /* verify socket options */ 86354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, 87354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao &imr.imr_interface.s_addr, 88354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao sizeof(imr.imr_interface.s_addr)) != 0) { 89354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, 90354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "Error: unable to set socket option IP_MULTICAST_IF\n"); 91354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao errors++; 92354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } else 93354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao printf("Socket set for Multicasting on: %s\n", interface); 94865695bbc89088b9526ea9045410e5afb70a985cplars 95354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if ((!jflg && !lflg) || jflg) 96354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao join_group(s, group_list, &imr); 97865695bbc89088b9526ea9045410e5afb70a985cplars 98354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao sleep(sflg); 99865695bbc89088b9526ea9045410e5afb70a985cplars 100354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if ((!jflg && !lflg) || lflg) 101354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao leave_group(s, group_list, &imr); 102865695bbc89088b9526ea9045410e5afb70a985cplars 103354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao close(s); 104354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (errors) 105354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao exit(1); 106cb49919064fe0f527437fe0587dfc820290e4c35Zeng Linggang return 0; 107865695bbc89088b9526ea9045410e5afb70a985cplars} 108865695bbc89088b9526ea9045410e5afb70a985cplars 109cb49919064fe0f527437fe0587dfc820290e4c35Zeng Linggangstatic int join_group(int s, char *glist, struct ip_mreq *imr) 110865695bbc89088b9526ea9045410e5afb70a985cplars{ 111354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao char buf[40]; 112354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao unsigned g1, g2, g3, g4; 113354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao FILE *fd; 114354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao char group[40], itf[40]; 115354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 116cb49919064fe0f527437fe0587dfc820290e4c35Zeng Linggang fd = fopen(glist, "r"); 117cb49919064fe0f527437fe0587dfc820290e4c35Zeng Linggang if (fd == NULL) 118354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao printf("Error: unable to open %s\n", glist); 119354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 120354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao while (fgets(buf, sizeof(buf), fd) != NULL) { 121354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (sscanf(buf, "%u.%u.%u.%u", &g1, &g2, &g3, &g4) != 4) { 122354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, "bad group address\n"); 123354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao exit(1); 124354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 125354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 126354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao imr->imr_multiaddr.s_addr = 127354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao htonl((g1 << 24) | (g2 << 16) | (g3 << 8) | g4); 128354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 129354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, 130354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao imr, sizeof(struct ip_mreq)) == -1) { 131cb49919064fe0f527437fe0587dfc820290e4c35Zeng Linggang fprintf(stderr, "errno is %d\n", errno); 132354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao perror("can't join group"); 133354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao errors++; 134354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } else { 135354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao strcpy(group, inet_ntoa(imr->imr_multiaddr)); 136354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao strcpy(itf, inet_ntoa(imr->imr_interface)); 137354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao printf("IPM group: %s added to interface: %s\n", group, 138354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao itf); 139354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 140354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 141cb49919064fe0f527437fe0587dfc820290e4c35Zeng Linggang return 0; 142865695bbc89088b9526ea9045410e5afb70a985cplars} 143865695bbc89088b9526ea9045410e5afb70a985cplars 144cb49919064fe0f527437fe0587dfc820290e4c35Zeng Linggangstatic int leave_group(int s, char *glist, struct ip_mreq *imr) 145865695bbc89088b9526ea9045410e5afb70a985cplars{ 146354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao char buf[40]; 147354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao unsigned g1, g2, g3, g4; 148354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao FILE *fd; 149354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao char group[40], itf[40]; 150354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 151cb49919064fe0f527437fe0587dfc820290e4c35Zeng Linggang fd = fopen(glist, "r"); 152cb49919064fe0f527437fe0587dfc820290e4c35Zeng Linggang if (fd == NULL) 153354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao printf("Error: unable to open %s\n", glist); 154354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 155354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao while (fgets(buf, sizeof(buf), fd) != NULL) { 156354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (sscanf(buf, "%u.%u.%u.%u", &g1, &g2, &g3, &g4) != 4) { 157354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, "leave_group: bad group address\n"); 158354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao exit(1); 159354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 160354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 161354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao imr->imr_multiaddr.s_addr = 162354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao htonl((g1 << 24) | (g2 << 16) | (g3 << 8) | g4); 163354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao 164354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao if (setsockopt(s, IPPROTO_IP, IP_DROP_MEMBERSHIP, 165354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao imr, sizeof(struct ip_mreq)) == -1) { 166354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao perror("can't leave group"); 167354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao errors++; 168354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } else { 169354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao strcpy(group, inet_ntoa(imr->imr_multiaddr)); 170354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao strcpy(itf, inet_ntoa(imr->imr_interface)); 171354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao printf("IPM group: %s dropped from interface: %s\n", 172354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao group, itf); 173354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 174354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao } 175cb49919064fe0f527437fe0587dfc820290e4c35Zeng Linggang return 0; 176865695bbc89088b9526ea9045410e5afb70a985cplars} 177865695bbc89088b9526ea9045410e5afb70a985cplars 178cb49919064fe0f527437fe0587dfc820290e4c35Zeng Linggangstatic void usage(void) 179865695bbc89088b9526ea9045410e5afb70a985cplars{ 180354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao fprintf(stderr, 181354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao "usage: %s [ -j -l ] -g group_list [-s time_to_sleep] -i interface_name (or i.i.i.i)\n", 182354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao prog); 183354ebb48db8e66a853a58379a4808d5dcd1ceac3Wanlong Gao exit(1); 184ec6edca7aa42b6affd989ef91b5897f96795e40fChris Dearman} 185