/*** * * qi3 - generate IGMP queries * * Usage: qi3 * * File: qi3.c * Date: 28/4/2000 * Auth: wilbertdg@hetnet.nl * ***/ #include #include #include #include #include /* #define */ #include #include #include typedef u_int32_t n_long; #include #define ALL_SYSTEMS "224.0.0.1" #define ALL_ROUTERS "224.0.0.2" #define ALL_IGMPV3_ROUTERS "224.0.0.22" #define NUM_SOURCES 50 #define MRT 100 /* max response time */ #define RBV 2 /* robustness variable */ #define QQI 125 /* querier query interval */ /* * ---------------------------------------------------------------------------- * * protoypes * * ---------------------------------------------------------------------------- */ void catch_sig(int); unsigned short in_cksum(unsigned short*, int); void print_igmp(char*, int); void igmpv1_query(int, char*, struct in_addr); void igmpv2_query(int, char*, struct in_addr, char*); void igmpv3_query(int, char*, struct in_addr, char*, struct in_addr*, int); /* * ---------------------------------------------------------------------------- * * igmp structs * * ---------------------------------------------------------------------------- */ struct igmpq { u_char iq_type; u_char iq_mrt; u_short iq_cs; struct in_addr iq_group; }; struct igmpq_v3 { u_char iq_type; u_char iq_mrt; u_short iq_cs; struct in_addr iq_group; u_char iq_rsv; u_char iq_qqi; u_short iq_nsrcs; struct in_addr iq_srcs[NUM_SOURCES]; }; int sockfd; struct in_addr sources[NUM_SOURCES]; /* * ---------------------------------------------------------------------------- * * main() * * ---------------------------------------------------------------------------- */ int main(argc, argv) int argc; char *argv[]; { int n, len; char buf[256]; struct in_addr all_systems, addr; struct ip *iph; struct ip_mreq mreq; struct igmpq *igh; struct tm now; time_t t; char version; char group[20]; char ra[4]; /* * initialze */ all_systems.s_addr = inet_addr(ALL_SYSTEMS); for (n=0; n= 0 && n <= NUM_SOURCES) { igmpv3_query(sockfd, buf, all_systems, group, sources, n); printf("igmpv3 query transmitted\n"); print_igmp(buf, 12); } else printf("wrong number [1..%d]\n", NUM_SOURCES); break; default: printf("wrong version [1..3]\n"); } } quit: close(sockfd); return(0); } /* * ---------------------------------------------------------------------------- * * catch_sig * * ---------------------------------------------------------------------------- */ void catch_sig(sig_num) int sig_num; { printf("\nterminated.\n"); close(sockfd); exit(0); } /* * ---------------------------------------------------------------------------- * * in_cksum * * ---------------------------------------------------------------------------- */ unsigned short in_cksum(unsigned short *addr, int len) { int nleft = len; int sum = 0; unsigned short *w = addr; unsigned short answer = 0; while (nleft > 1) { sum += *w++; nleft -= 2; } if (nleft == 1) { *(u_char*)(&answer) = *(u_char*)w; sum += answer; } sum = (sum >> 16) + (sum & 0xffff); answer = ~sum; return (answer); } /* * ---------------------------------------------------------------------------- * * print_igmp * * ---------------------------------------------------------------------------- */ void print_igmp(p, n) char* p; int n; { struct igmpq_v3 *igh = (struct igmpq_v3*) p; int i; printf("\ttype = %02x\n", igh->iq_type); printf("\tmrt = %d\n", igh->iq_mrt); printf("\tcs = %d\n", igh->iq_cs); printf("\tgroup = %s\n", inet_ntoa(igh->iq_group)); if (n >= 12) { printf("num = %d\n", igh->iq_nsrcs); for (i=0; iiq_nsrcs); i++) printf("\t\t%s\n", inet_ntoa(igh->iq_srcs[i])); } } /* * ---------------------------------------------------------------------------- * * igmpv1 query * * ---------------------------------------------------------------------------- */ void igmpv1_query(s, buf, dst) int s; char *buf; struct in_addr dst; { struct igmpq *igh; struct sockaddr_in sa; igh = (struct igmpq*) buf; igh->iq_type = 17; /* query */ igh->iq_mrt = 0; igh->iq_cs = 0; igh->iq_group.s_addr = 0; igh->iq_cs = in_cksum((u_short*)igh, sizeof(*igh)); sa.sin_addr.s_addr = dst.s_addr; sendto(sockfd, buf, sizeof(*igh), 0, (struct sockaddr*)&sa, sizeof(sa)); } /* * ---------------------------------------------------------------------------- * * igmpv2 query * * ---------------------------------------------------------------------------- */ void igmpv2_query(s, buf, dst, group) int s; char *buf; struct in_addr dst; char *group; { struct igmpq *igh; struct sockaddr_in sa; igh = (struct igmpq*) buf; igh->iq_type = 17; /* query */ igh->iq_mrt = MRT; igh->iq_cs = 0; igh->iq_group.s_addr = inet_addr(group); igh->iq_cs = in_cksum((u_short*)igh, sizeof(*igh)); sa.sin_addr.s_addr = dst.s_addr; sendto(sockfd, buf, sizeof(*igh), 0, (struct sockaddr*)&sa, sizeof(sa)); } /* * ---------------------------------------------------------------------------- * * igmpv3 query * * ---------------------------------------------------------------------------- */ void igmpv3_query(s, buf, dst, group, srcs, num) int s; char *buf; struct in_addr dst; char *group; struct in_addr *srcs; int num; { struct igmpq_v3 *igh; struct sockaddr_in sa; int i, size; igh = (struct igmpq_v3*) buf; igh->iq_type = 17; /* query */ igh->iq_mrt = MRT; igh->iq_cs = 0; igh->iq_group.s_addr = inet_addr(group); igh->iq_rsv = RBV; igh->iq_qqi = QQI; igh->iq_nsrcs = htons(num); for (i=0; iiq_srcs[i].s_addr = srcs[i].s_addr; size = sizeof(*igh) + (num-1) * sizeof(struct in_addr); printf("size = %d\n", size); igh->iq_cs = in_cksum((u_short*)igh, size); sa.sin_addr.s_addr = dst.s_addr; sendto(sockfd, buf, size, 0, (struct sockaddr*)&sa, sizeof(sa)); } /* struct igmpq_v3 { u_char iq_type; u_char iq_mrt; u_short iq_cs; struct in_addr iq_group; u_char iq_rsv; u_char iq_qqi; u_short iq_nsrc; struct in_addr iq_srcs[1]; }; */