/** * * Show multicast messages for some group on a UDP port, using a multicast * source filter * * Usage: mshow *[ip source] * * File: mshow.c * Date: 26/6/2000 * Auth: wilbertdg@hetnet.nl * **/ #include #include #include #include #ifndef WIN32 #include #include #include #include #include #include #include #include #else #define WIN32_LEAN_AND_MEAN #include #include #include #include #include #define SIOCSIPMSFILTER SIO_SET_MULTICAST_FILTER #define SIOCGIPMSFILTER SIO_GET_MULTICAST_FILTER #define EADDRNOTAVAIL WSAEADDRNOTAVAIL #define isblank(x) (((x) != ' ') && ((x) != '\t') && ((x) != '\n')) #endif /* If the igmpv3 macro IP_MSFILTER_SIZE has been defined, try the source * filter / igmpv3 api */ #ifdef IP_MSFILTER_SIZE #define MSFILTER #endif #define MAX_MSG 1024 #define MAX_SOURCES 100 #ifndef WIN32 int sockfd; #else SOCKET sockfd; #endif void catch_term(int); /* * int main() */ int main(int argc, char *argv[]) { struct sockaddr_in sa; struct hostent *addr; struct ip_mreq mreq; #ifdef MSFILTER struct ip_msfilter *imsfp; char buffer[IP_MSFILTER_SIZE(MAX_SOURCES)]; #endif struct in_addr ia; u_short port; int i, nsources, on = 1; char *group, msg[MAX_MSG]; int len, sz, err; #ifdef WIN32 /* Initialize WinSock */ WORD wVersionRequested; WSADATA wsaData; wVersionRequested = MAKEWORD(2, 2); if ((WSAStartup(wVersionRequested, &wsaData)) != 0) { printf("failed to initialize winsock\n"); exit(1); } #endif /* Determine options */ #ifdef MSFILTER if (argc < 4) { #else if (argc < 3) { #endif printf("Usage: mshow \n"); exit(0); } #ifdef MSFILTER imsfp = (struct ip_msfilter*) &buffer; #endif group = argv[1]; port = (u_short) atoi(argv[2]); if (port == 0) { printf("Usage: mshow \n"); exit(0); } #ifdef MSFILTER if (argv[3][0] == 'e') imsfp->imsf_fmode = MCAST_EXCLUDE; else imsfp->imsf_fmode = MCAST_INCLUDE; printf("fmode = %s\n", (imsfp->imsf_fmode == MCAST_INCLUDE) ? "include" : "exclude"); nsources = 0; for (i=4; iimsf_slist[nsources].s_addr = inet_addr(argv[i]); if (imsfp->imsf_slist[nsources].s_addr == INADDR_NONE) { printf("Invalid sources\n"); exit(0); } nsources++; } imsfp->imsf_numsrc = nsources; #endif /* create socket */ #ifndef WIN32 if (-1 == (sockfd = socket(AF_INET, SOCK_DGRAM, 0))) { #else if (INVALID_SOCKET == (sockfd = socket(AF_INET, SOCK_DGRAM, 0))) { #endif perror("failed to create a socket\n"); } /* determine group */ if (-1 == (ia.s_addr = inet_addr(group))) { if (NULL == (addr = gethostbyname(group))) { perror("failed to resolve"); return(-1); } memcpy(&ia.s_addr, addr->h_addr_list[0], addr->h_length); } /* name the socket */ sa.sin_family = AF_INET; sa.sin_port = htons(port); sa.sin_addr.s_addr = INADDR_ANY; err = bind(sockfd, (struct sockaddr*) &sa, sizeof(sa)); if (err == SOCKET_ERROR) { printf ("bind() port: %d failed, Err: %d\n", port, WSAGetLastError()); } printf("joining group: %s\n", inet_ntoa(ia)); /* join the group and set sourcefilter */ on = 1; setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*) &on, sizeof(on)); #ifndef WIN32 on = 1; setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, (void*) &on, sizeof(on)); #endif mreq.imr_multiaddr.s_addr = ia.s_addr; mreq.imr_interface.s_addr = INADDR_ANY; if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void*) &mreq, sizeof(mreq))) { perror("failed to join"); } #ifdef MSFILTER imsfp->imsf_multiaddr.s_addr = mreq.imr_multiaddr.s_addr; imsfp->imsf_interface.s_addr = mreq.imr_interface.s_addr; printf("group = %s\n", inet_ntoa(imsfp->imsf_multiaddr)); printf("if = %s\n", inet_ntoa(imsfp->imsf_interface)); printf("mode = %d\n", imsfp->imsf_fmode); printf("numsrc = %d\n", imsfp->imsf_numsrc); for (i=0; iimsf_numsrc; i++) { printf("\t[%d] = %s\n", i, inet_ntoa(imsfp->imsf_slist[i])); } #ifndef WIN32 if (ioctl(sockfd, SIOCSIPMSFILTER, imsfp) != 0) { printf("failed to set sourcefilter: error = %d\n", errno); } #else err = WSAIoctl(sockfd, SIO_GET_MULTICAST_FILTER, (PBYTE) imsfp, IP_MSFILTER_SIZE(imsfp->imsf_numsrc), (PBYTE) imsfp, IP_MSFILTER_SIZE(MAX_SOURCES), &sz, NULL, NULL); if (err != 0) { printf("failed to set sourcefilter: error = %d\n", WSAGetLastError()); } #endif #endif #ifndef WIN32 signal(SIGINT, catch_term); #endif while (1) { sz = sizeof(sa); len = recvfrom(sockfd, msg, sizeof(msg), 0, (struct sockaddr*) &sa, &sz); if (len > 0) { msg[len] = '\0'; printf("from %s (%d bytes):\n%s\n", inet_ntoa(sa.sin_addr), len, msg); } else { #ifndef WIN32 printf("failed: %d\n", errno); #else printf("failed: 0x%X (%u)\n", WSAGetLastError(), WSAGetLastError()); #endif break; } } /* bye */ #ifndef WIN32 close(sockfd); #else closesocket(sockfd); WSACleanup(); #endif return(0); } void catch_term(sig_num) int sig_num; { printf("terminated.\n"); #ifndef WIN32 close(sockfd); #else closesocket(sockfd); #endif exit(0); }