From b5038e157d54458fe2145e4ac06f0c2567382624 Mon Sep 17 00:00:00 2001 From: Fredrik Tolf Date: Sat, 9 Aug 2008 16:08:24 +0200 Subject: [PATCH] Multicast test code. --- src/Makefile.am | 2 +- src/mctap.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/utils.c | 67 ++++++++++++++++++++++++++++++++++++++++ src/utils.h | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 252 insertions(+), 3 deletions(-) create mode 100644 src/utils.c create mode 100644 src/utils.h diff --git a/src/Makefile.am b/src/Makefile.am index b8341da..7a6f135 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,2 +1,2 @@ bin_PROGRAMS=mctap -mctap_SOURCES=mctap.c +mctap_SOURCES=mctap.c utils.c 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); } diff --git a/src/utils.c b/src/utils.c new file mode 100644 index 0000000..d0219a0 --- /dev/null +++ b/src/utils.c @@ -0,0 +1,67 @@ +#include +#include + +#include "utils.h" + +void _sizebuf2(void **buf, size_t *sz, size_t wanted, size_t el) +{ + size_t n; + + n = *sz; + if(n == 0) + n = 1; + while(n < wanted) + n <<= 1; + if(n <= *sz) + return; + if(*buf != NULL) + *buf = srealloc(*buf, n * el); + else + *buf = smalloc(n * el); + *sz = n; +} + +void _sizebuf(struct buffer *buf, size_t wanted, size_t el) +{ + size_t n; + + n = buf->s; + if(n == 0) + n = 1; + while(n < wanted) + n <<= 1; + if(n <= buf->s) + return; + if(buf->b != NULL) + buf->b = srealloc(buf->b, n * el); + else + buf->b = smalloc(n * el); + buf->s = n; +} + +char *vsprintf2(char *format, va_list al) +{ + int ret; + char *buf; + va_list al2; + + va_copy(al2, al); + ret = vsnprintf(NULL, 0, format, al2); + va_end(al2); + buf = smalloc(ret + 1); + va_copy(al2, al); + vsnprintf(buf, ret + 1, format, al2); + va_end(al2); + return(buf); +} + +char *sprintf2(char *format, ...) +{ + va_list args; + char *buf; + + va_start(args, format); + buf = vsprintf2(format, args); + va_end(args); + return(buf); +} diff --git a/src/utils.h b/src/utils.h new file mode 100644 index 0000000..3a1c41a --- /dev/null +++ b/src/utils.h @@ -0,0 +1,90 @@ +#ifndef _UTILS_H +#define _UTILS_H + +#include +#include +#include + +#define smalloc(size) ({void *__result__; ((__result__ = malloc(size)) == NULL)?({exit(-1); (void *)0;}):__result__;}) +#define srealloc(ptr, size) ({void *__result__; ((__result__ = realloc((ptr), (size))) == NULL)?({exit(-1); (void *)0;}):__result__;}) +#define szmalloc(size) memset(smalloc(size), 0, size) +#define sstrdup(str) ({char *__strbuf__ = (str); strcpy(smalloc(strlen(__strbuf__) + 1), __strbuf__);}) +#define omalloc(o) ((o) = szmalloc(sizeof(*(o)))) + +#define bufinit(buf) memset(&(buf), 0, sizeof(buf)) +#define buffree(buf) do { if((buf).b != NULL) {free((buf).b);} } while(0) +#define bufdupc(buf) memcpy(smalloc((buf).d * sizeof(*((buf).b))), (buf).b, (buf).d * sizeof(*((buf).b))) +#define sizebuf(buf, wanted) (_sizebuf((struct buffer *)&(buf), (wanted), sizeof(*((buf).b)))) +#define sizebuf2(buf, wanted) (_sizebuf2((void **)&(buf), &(buf ## size), (wanted), sizeof(*(buf)))) +#define bufdel(buf, i) (memmove((buf).b + (i), (buf).b + (i) + 1, (--((buf).d) - (i)) * sizeof(*((buf).b)))) +#define bufadd(buf, new) \ +do { \ + _sizebuf((struct buffer *)&(buf), (buf).d + 1, sizeof(*((buf).b))); \ + (buf).b[(buf).d++] = (new); \ +} while(0) +#define bufcat(buf, new, size) \ +do { \ + size_t __bufcat_size__; \ + __bufcat_size__ = (size); \ + _sizebuf((struct buffer *)&(buf), (buf).d + __bufcat_size__, sizeof((buf).b)); \ + memcpy((buf).b + (buf).d, (new), (__bufcat_size__) * sizeof(*((buf).b))); \ + (buf).d += __bufcat_size__; \ +} while(0) +#define bufcatnum(buf, num, type) \ +do { \ + type __buf__; \ + __buf__ = (num); \ + bufcat((buf), &__buf__, sizeof(type)); \ +} while(0) +#define bufcatuid(buf, uid) \ +do { \ + uniqid_t __buf__; \ + __buf__ = (uid); \ + bufcat((buf), &__buf__, sizeof(__buf__)); \ +} while(0) +#define bufcatstr(buf, str) \ +do { \ + char *__buf__; \ + __buf__ = (str); \ + bufcat((buf), __buf__, strlen(__buf__) + 1); \ +} while(0) +#define bufcatstr2(buf, str) \ +do { \ + char *__buf__; \ + __buf__ = (str); \ + bufcat((buf), __buf__, strlen(__buf__)); \ +} while(0) +#define bufcats(buf, d) bufcat((buf), &(d), sizeof(d)) +#define bufeat(buf, len) \ +do { \ + size_t __bufeat_size__; \ + __bufeat_size__ = (len); \ + memmove((buf).b, (buf).b + __bufeat_size__, (buf).d -= __bufeat_size__); \ +} while(0) + +struct buffer { + void *b; + size_t s, d; +}; + +struct charbuf { + char *b; + size_t s, d; +}; + +struct charvbuf { + char **b; + size_t s, d; +}; + +struct ptrbuf { + void **b; + size_t s, d; +}; + +void _sizebuf(struct buffer *buf, size_t wanted, size_t el); +void _sizebuf2(void **buf, size_t *sz, size_t wanted, size_t el); +char *vsprintf2(char *format, va_list al); +char *sprintf2(char *format, ...); + +#endif -- 2.11.0