X-Git-Url: http://dolda2000.com/gitweb/?p=mctap.git;a=blobdiff_plain;f=src%2Fmctap.c;h=b021d88740e7960f3fc5ce0c5cb46b5e4d64b3c3;hp=061edd558a7a3b39ac0b41b0fe2b189edfca1070;hb=b5038e157d54458fe2145e4ac06f0c2567382624;hpb=3415540feb47f1c379767c984620f8a7a3c4e2b1 diff --git a/src/mctap.c b/src/mctap.c index 061edd5..b021d88 100644 --- a/src/mctap.c +++ b/src/mctap.c @@ -4,17 +4,95 @@ #include #include #include +#include +#include + +#include "utils.h" static void usage(FILE *out) { - fprintf(out, "usage: mctap [-h]\n"); + fprintf(out, "usage: mctap [-h] MCASTGROUP PORT\n"); +} + +static char *formataddress(struct sockaddr *arg, socklen_t arglen) +{ + struct sockaddr_in *ipv4; + struct sockaddr_in6 *ipv6; + static char *ret = NULL; + char buf[1024]; + + if(ret != NULL) + free(ret); + ret = NULL; + switch(arg->sa_family) + { + case AF_UNIX: + ret = strdup("Unix socket"); + break; + case AF_INET: + ipv4 = (struct sockaddr_in *)arg; + if(inet_ntop(AF_INET, &ipv4->sin_addr, buf, sizeof(buf)) == NULL) + return(NULL); + ret = sprintf2("%s:%i", buf, (int)ntohs(ipv4->sin_port)); + break; + case AF_INET6: + ipv6 = (struct sockaddr_in6 *)arg; + if(inet_ntop(AF_INET6, &ipv6->sin6_addr, buf, sizeof(buf)) == NULL) + return(NULL); + ret = sprintf2("[%s]:%i", buf, (int)ntohs(ipv6->sin6_port)); + break; + default: + errno = EPFNOSUPPORT; + break; + } + return(ret); +} + +static int mkmcastsk4(struct in_addr group, int port) +{ + int fd; + struct sockaddr_in nm; + struct ip_mreqn mreq; + + fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); + memset(&nm, 0, sizeof(nm)); + nm.sin_family = AF_INET; + nm.sin_port = htons(port); + if(bind(fd, (struct sockaddr *)&nm, sizeof(nm))) + return(-1); + memset(&mreq, 0, sizeof(mreq)); + mreq.imr_multiaddr = group; + if(setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq))) + return(-1); + return(fd); +} + +static void test(int fd) +{ + char buf[65536]; + int ret; + struct sockaddr_storage nm; + socklen_t nmlen; + + while(1) { + nmlen = sizeof(nm); + ret = recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&nm, &nmlen); + if(ret < 0) { + fprintf(stderr, "mctap: recvfrom: %s\n", strerror(ret)); + exit(1); + } + printf("%s %i:\n", formataddress((struct sockaddr *)&nm, nmlen), ret); + } } int main(int argc, char **argv) { int c; + int sock; + struct in_addr group; + int port; - while((c = getopt(argc, argv, "-h")) >= 0) { + while((c = getopt(argc, argv, "h")) >= 0) { switch(c) { case 'h': usage(stdout); @@ -24,6 +102,20 @@ int main(int argc, char **argv) exit(1); } } + if(argc - optind < 2) { + usage(stderr); + exit(1); + } + if(!inet_aton(argv[optind], &group)) { + fprintf(stderr, "mctap: invalid group address: %s\n", argv[optind]); + exit(1); + } + port = atoi(argv[optind + 1]); + if((sock = mkmcastsk4(group, port)) < 0) { + fprintf(stderr, "mctap: could not create multicast socket: %s\n", strerror(errno)); + exit(1); + } + test(sock); return(0); }