From e6e151bdd416355966e1c9cb293a07172bae3f3c Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Thu, 15 Dec 2011 16:28:26 +0000 Subject: [PATCH] and while we're at it, add support for ipv6 on the udp control protocol as well --- daemon/aux.h | 4 +++- daemon/call.c | 6 ++---- daemon/control_udp.c | 26 +++++++++++++++----------- daemon/control_udp.h | 3 ++- daemon/main.c | 31 ++++++++++++++++++++++++++++--- 5 files changed, 50 insertions(+), 20 deletions(-) diff --git a/daemon/aux.h b/daemon/aux.h index 62f19c330..b493582c8 100644 --- a/daemon/aux.h +++ b/daemon/aux.h @@ -60,11 +60,13 @@ void g_queue_clear(GQueue *); static inline void nonblock(int fd) { fcntl(fd, F_SETFL, O_NONBLOCK); } - static inline void reuseaddr(int fd) { int one = 1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)); } +static inline void ipv6only(int fd, int yn) { + setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &yn, sizeof(yn)); +} static inline int bit_array_isset(int *name, unsigned int bit) { return name[(bit) / (sizeof(int) * 8)] & (1 << ((bit) % (sizeof(int) * 8))); diff --git a/daemon/call.c b/daemon/call.c index bcf27b7ef..3d432fd18 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -582,7 +582,6 @@ fail: static int get_port6(struct streamrelay *r, u_int16_t p) { int fd; struct sockaddr_in6 sin; - int i; fd = socket(AF_INET6, SOCK_DGRAM, 0); if (fd < 0) @@ -591,8 +590,7 @@ static int get_port6(struct streamrelay *r, u_int16_t p) { nonblock(fd); reuseaddr(fd); setsockopt(fd, IPPROTO_IP, IP_TOS, &r->up->up->call->callmaster->tos, sizeof(r->up->up->call->callmaster->tos)); - i = 0; - setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &i, sizeof(i)); + ipv6only(fd, 0); ZERO(sin); sin.sin6_family = AF_INET6; @@ -1128,7 +1126,7 @@ static char *streams_print(GQueue *s, unsigned int num, unsigned int off, const } else { if (IN6_IS_ADDR_UNSPECIFIED(&t->peers[off].rtps[0].peer.ip46)) - strcpy(ips, "::0"); + strcpy(ips, "::"); else if (!IN6_IS_ADDR_UNSPECIFIED(&t->call->callmaster->adv_ipv6)) inet_ntop(AF_INET6, &t->call->callmaster->adv_ipv6, ips, sizeof(ips)); else diff --git a/daemon/control_udp.c b/daemon/control_udp.c index 341841010..fc040cb43 100644 --- a/daemon/control_udp.c +++ b/daemon/control_udp.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "control_udp.h" #include "poller.h" @@ -29,13 +30,14 @@ static void control_udp_incoming(int fd, void *p) { struct control_udp *u = p; int ret, len; char buf[8192]; - struct sockaddr_in sin; + struct sockaddr_in6 sin; socklen_t sin_len; int ovec[60]; const char **out; char *reply; struct msghdr mh; struct iovec iov[10]; + char addr[64]; sin_len = sizeof(sin); len = recvfrom(fd, buf, sizeof(buf) - 1, 0, (struct sockaddr *) &sin, &sin_len); @@ -45,16 +47,17 @@ static void control_udp_incoming(int fd, void *p) { } buf[len] = '\0'; + smart_ntop(addr, &sin.sin6_addr, sizeof(addr)); ret = pcre_exec(u->parse_re, u->parse_ree, buf, len, 0, 0, ovec, G_N_ELEMENTS(ovec)); if (ret <= 0) { ret = pcre_exec(u->fallback_re, NULL, buf, len, 0, 0, ovec, G_N_ELEMENTS(ovec)); if (ret <= 0) { - mylog(LOG_WARNING, "Unable to parse command line from udp:" DF ": %s", DP(sin), buf); + mylog(LOG_WARNING, "Unable to parse command line from udp:%s:%u: %s", addr, ntohs(sin.sin6_port), buf); return; } - mylog(LOG_WARNING, "Failed to properly parse UDP command line '%s' from "DF", using fallback RE", buf, DP(sin)); + mylog(LOG_WARNING, "Failed to properly parse UDP command line '%s' from %s:%u, using fallback RE", buf, addr, ntohs(sin.sin6_port)); pcre_get_substring_list(buf, ovec, ret, &out); @@ -87,7 +90,7 @@ static void control_udp_incoming(int fd, void *p) { return; } - mylog(LOG_INFO, "Got valid command from udp:" DF ": %s", DP(sin), buf); + mylog(LOG_INFO, "Got valid command from udp:%s:%u: %s", addr, ntohs(sin.sin6_port), buf); pcre_get_substring_list(buf, ovec, ret, &out); @@ -104,7 +107,7 @@ static void control_udp_incoming(int fd, void *p) { if (!reply) reply = g_hash_table_lookup(u->stale_cookies, out[1]); if (reply) { - mylog(LOG_INFO, "Detected command from udp:" DF " as a duplicate", DP(sin)); + mylog(LOG_INFO, "Detected command from udp:%s:%u as a duplicate", addr, ntohs(sin.sin6_port)); sendto(fd, reply, strlen(reply), 0, (struct sockaddr *) &sin, sin_len); goto out; } @@ -158,28 +161,29 @@ out: pcre_free(out); } -struct control_udp *control_udp_new(struct poller *p, u_int32_t ip, u_int16_t port, struct callmaster *m) { +struct control_udp *control_udp_new(struct poller *p, struct in6_addr ip, u_int16_t port, struct callmaster *m) { int fd; struct control_udp *c; struct poller_item i; - struct sockaddr_in sin; + struct sockaddr_in6 sin; const char *errptr; int erroff; if (!p || !m) return NULL; - fd = socket(AF_INET, SOCK_DGRAM, 0); + fd = socket(AF_INET6, SOCK_DGRAM, 0); if (fd == -1) return NULL; nonblock(fd); reuseaddr(fd); + ipv6only(fd, 0); ZERO(sin); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = ip; - sin.sin_port = htons(port); + sin.sin6_family = AF_INET6; + sin.sin6_addr = ip; + sin.sin6_port = htons(port); if (bind(fd, (struct sockaddr *) &sin, sizeof(sin))) goto fail; diff --git a/daemon/control_udp.h b/daemon/control_udp.h index 166d7d6e5..b24a8911c 100644 --- a/daemon/control_udp.h +++ b/daemon/control_udp.h @@ -8,6 +8,7 @@ #include #include #include +#include @@ -36,7 +37,7 @@ struct control_udp { -struct control_udp *control_udp_new(struct poller *, u_int32_t, u_int16_t, struct callmaster *); +struct control_udp *control_udp_new(struct poller *, struct in6_addr, u_int16_t, struct callmaster *); diff --git a/daemon/main.c b/daemon/main.c index c08672204..3babb2195 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -36,7 +36,7 @@ static struct in6_addr ipv6; static struct in6_addr adv_ipv6; static u_int32_t listenp; static u_int16_t listenport; -static u_int32_t udp_listenp; +static struct in6_addr udp_listenp; static u_int16_t udp_listenport; static int tos; static int table; @@ -108,6 +108,31 @@ out: return ret; } +static int parse_ip6_port(struct in6_addr *ip6, u_int16_t *port, char *s) { + u_int32_t ip; + char *p; + + if (!parse_ip_port(&ip, port, s)) { + if (ip) + in4_to_6(ip6, ip); + else + *ip6 = in6addr_any; + return 0; + } + if (*s != '[') + return -1; + if (inet_pton(AF_INET6, s+1, ip6) != 1) + return -1; + p = strstr(s, "]:"); + if (!p) + return -1; + *port = atoi(p+2); + if (!*port) + return -1; + + return 0; +} + static void options(int *argc, char ***argv) { @@ -130,7 +155,7 @@ static void options(int *argc, char ***argv) { { "ip6", 'I', 0, G_OPTION_ARG_STRING, &ipv6s, "Local IPv6 address for RTP", "IP6" }, { "advertised-ip6",'A',0,G_OPTION_ARG_STRING, &adv_ipv6s, "IPv6 address to advertise", "IP6" }, { "listen", 'l', 0, G_OPTION_ARG_STRING, &listenps, "TCP port to listen on", "[IP:]PORT" }, - { "listen-udp", 'u', 0, G_OPTION_ARG_STRING, &listenudps, "UDP port to listen on", "[IP:]PORT" }, + { "listen-udp", 'u', 0, G_OPTION_ARG_STRING, &listenudps, "UDP port to listen on", "[IP46:]PORT" }, { "tos", 'T', 0, G_OPTION_ARG_INT, &tos, "TOS value to set on streams", "INT" }, { "timeout", 'o', 0, G_OPTION_ARG_INT, &timeout, "RTP timeout", "SECS" }, { "silent-timeout",'s',0,G_OPTION_ARG_INT, &silent_timeout,"RTP timeout for muted", "SECS" }, @@ -185,7 +210,7 @@ static void options(int *argc, char ***argv) { die("Invalid IP or port (--listen)\n"); } if (listenudps) { - if (parse_ip_port(&udp_listenp, &udp_listenport, listenudps)) + if (parse_ip6_port(&udp_listenp, &udp_listenport, listenudps)) die("Invalid IP or port (--listen-udp)\n"); }