diff --git a/src/access.c b/src/access.c index 7814025e..514e8707 100644 --- a/src/access.c +++ b/src/access.c @@ -149,6 +149,74 @@ access_ticket_verify(const char *id, const char *resource) return 0; } +/** + * + */ +static int +netmask_verify(access_entry_t *ae, struct sockaddr *src) +{ + access_ipmask_t *ai; + int isv4v6 = 0; + uint32_t v4v6 = 0; + + if(src->sa_family == AF_INET6) + { + struct in6_addr *in6 = &(((struct sockaddr_in6 *)src)->sin6_addr); + uint32_t *a32 = (uint32_t*)in6->s6_addr; + if(a32[0] == 0 && a32[1] == 0 && ntohl(a32[2]) == 0x0000FFFFu) + { + isv4v6 = 1; + v4v6 = ntohl(a32[3]); + } + } + + LIST_FOREACH(ai, &ae->ae_ipmasks, ai_link) + { + if(ai->ai_ipv6 == 0 && src->sa_family == AF_INET) + { + struct sockaddr_in *in4 = (struct sockaddr_in *)src; + uint32_t b = ntohl(in4->sin_addr.s_addr); + if((b & ai->ai_netmask) == ai->ai_network) + return 1; + } + else if(ai->ai_ipv6 == 0 && isv4v6) + { + if((v4v6 & ai->ai_netmask) == ai->ai_network) + return 1; + } + else if(ai->ai_ipv6 && isv4v6) + { + continue; + } + else if(ai->ai_ipv6 && src->sa_family == AF_INET6) + { + struct in6_addr *in6 = &(((struct sockaddr_in6 *)src)->sin6_addr); + uint8_t *a8 = (uint8_t*)in6->s6_addr; + uint8_t *m8 = (uint8_t*)ai->ai_ip6.s6_addr; + int slen = ai->ai_prefixlen; + uint32_t apos = 0; + uint8_t lastMask = (0xFFu << (8 - (slen % 8))); + + if(slen < 0 || slen > 128) + continue; + + while(slen >= 8) + { + if(a8[apos] != m8[apos]) + continue; + + apos += 1; + slen -= 8; + } + + if(slen == 0 || (a8[apos] & lastMask) == (m8[apos] & lastMask)) + return 1; + } + } + + return 0; +} + /** * */ @@ -157,8 +225,6 @@ access_verify(const char *username, const char *password, struct sockaddr *src, uint32_t mask) { uint32_t bits = 0; - struct sockaddr_in *si = (struct sockaddr_in *)src; - uint32_t b = ntohl(si->sin_addr.s_addr); access_entry_t *ae; if(username != NULL && superuser_username != NULL && @@ -182,7 +248,7 @@ access_verify(const char *username, const char *password, continue; /* username/password mismatch */ } - if((b & ae->ae_netmask) != ae->ae_network) + if(!netmask_verify(ae, src)) continue; /* IP based access mismatches */ bits |= ae->ae_rights; @@ -200,8 +266,6 @@ access_get_hashed(const char *username, const uint8_t digest[20], const uint8_t *challenge, struct sockaddr *src, int *entrymatch) { - struct sockaddr_in *si = (struct sockaddr_in *)src; - uint32_t b = ntohl(si->sin_addr.s_addr); access_entry_t *ae; SHA_CTX shactx; uint8_t d[20]; @@ -226,7 +290,7 @@ access_get_hashed(const char *username, const uint8_t digest[20], if(!ae->ae_enabled) continue; - if((b & ae->ae_netmask) != ae->ae_network) + if(!netmask_verify(ae, src)) continue; /* IP based access mismatches */ SHA1_Init(&shactx); @@ -253,8 +317,6 @@ access_get_hashed(const char *username, const uint8_t digest[20], uint32_t access_get_by_addr(struct sockaddr *src) { - struct sockaddr_in *si = (struct sockaddr_in *)src; - uint32_t b = ntohl(si->sin_addr.s_addr); access_entry_t *ae; uint32_t r = 0; @@ -263,7 +325,7 @@ access_get_by_addr(struct sockaddr *src) if(ae->ae_username[0] != '*') continue; - if((b & ae->ae_netmask) != ae->ae_network) + if(!netmask_verify(ae, src)) continue; /* IP based access mismatches */ r |= ae->ae_rights; @@ -293,28 +355,90 @@ static void access_set_prefix(access_entry_t *ae, const char *prefix) { char buf[100]; + char tokbuf[4096]; int prefixlen; - char *p; + char *p, *tok, *saveptr; + access_ipmask_t *ai; - if(strlen(prefix) > 90) - return; - - strcpy(buf, prefix); - p = strchr(buf, '/'); - if(p) { - *p++ = 0; - prefixlen = atoi(p); - if(prefixlen > 32) - return; - } else { - prefixlen = 32; + while((ai = LIST_FIRST(&ae->ae_ipmasks)) != NULL) + { + LIST_REMOVE(ai, ai_link); + free(ai); } - ae->ae_ip.s_addr = inet_addr(buf); - ae->ae_prefixlen = prefixlen; + strncpy(tokbuf, prefix, 4095); + tokbuf[4095] = 0; + tok = strtok_r(tokbuf, ",;| ", &saveptr); - ae->ae_netmask = prefixlen ? 0xffffffff << (32 - prefixlen) : 0; - ae->ae_network = ntohl(ae->ae_ip.s_addr) & ae->ae_netmask; + while(tok != NULL) + { + ai = calloc(1, sizeof(access_ipmask_t)); + + if(strlen(tok) > 90 || strlen(tok) == 0) + { + free(ai); + tok = strtok_r(NULL, ",;| ", &saveptr); + continue; + } + + strcpy(buf, tok); + + if(strchr(buf, ':') != NULL) + ai->ai_ipv6 = 1; + else + ai->ai_ipv6 = 0; + + if(ai->ai_ipv6) + { + p = strchr(buf, '/'); + if(p) + { + *p++ = 0; + prefixlen = atoi(p); + if(prefixlen > 128) + { + free(ai); + tok = strtok_r(NULL, ",;| ", &saveptr); + continue; + } + } else { + prefixlen = 128; + } + + ai->ai_prefixlen = prefixlen; + inet_pton(AF_INET6, buf, &ai->ai_ip6); + + ai->ai_netmask = 0xffffffff; + ai->ai_network = 0x00000000; + } + else + { + p = strchr(buf, '/'); + if(p) + { + *p++ = 0; + prefixlen = atoi(p); + if(prefixlen > 32) + { + free(ai); + tok = strtok_r(NULL, ",;| ", &saveptr); + continue; + } + } else { + prefixlen = 32; + } + + ai->ai_ip.s_addr = inet_addr(buf); + ai->ai_prefixlen = prefixlen; + + ai->ai_netmask = prefixlen ? 0xffffffff << (32 - prefixlen) : 0; + ai->ai_network = ntohl(ai->ai_ip.s_addr) & ai->ai_netmask; + } + + LIST_INSERT_HEAD(&ae->ae_ipmasks, ai, ai_link); + + tok = strtok_r(NULL, ",;| ", &saveptr); + } } @@ -363,6 +487,14 @@ access_entry_find(const char *id, int create) static void access_entry_destroy(access_entry_t *ae) { + access_ipmask_t *ai; + + while((ai = LIST_FIRST(&ae->ae_ipmasks)) != NULL) + { + LIST_REMOVE(ai, ai_link); + free(ai); + } + free(ae->ae_id); free(ae->ae_username); free(ae->ae_password); @@ -378,7 +510,12 @@ static htsmsg_t * access_record_build(access_entry_t *ae) { htsmsg_t *e = htsmsg_create_map(); - char buf[100]; + access_ipmask_t *ai; + char addrbuf[50]; + char buf[4096]; + int pos = 0; + + memset(buf, 0, 4096); htsmsg_add_u32(e, "enabled", !!ae->ae_enabled); @@ -386,8 +523,22 @@ access_record_build(access_entry_t *ae) htsmsg_add_str(e, "password", ae->ae_password); htsmsg_add_str(e, "comment", ae->ae_comment); - snprintf(buf, sizeof(buf), "%s/%d", inet_ntoa(ae->ae_ip), ae->ae_prefixlen); - htsmsg_add_str(e, "prefix", buf); + LIST_FOREACH(ai, &ae->ae_ipmasks, ai_link) + { + if(sizeof(buf)-pos <= 0) + break; + + if(ai->ai_ipv6) + { + inet_ntop(AF_INET6, &ai->ai_ip6, addrbuf, 50); + pos += snprintf(buf+pos, sizeof(buf)-pos, ",%s/%d", addrbuf, ai->ai_prefixlen); + } + else + { + pos += snprintf(buf+pos, sizeof(buf)-pos, ",%s/%d", inet_ntoa(ai->ai_ip), ai->ai_prefixlen); + } + } + htsmsg_add_str(e, "prefix", buf + 1); htsmsg_add_u32(e, "streaming", ae->ae_rights & ACCESS_STREAMING ? 1 : 0); htsmsg_add_u32(e, "dvr" , ae->ae_rights & ACCESS_RECORDER ? 1 : 0); @@ -537,6 +688,7 @@ access_init(int createdefault) dtable_t *dt; htsmsg_t *r, *m; access_entry_t *ae; + access_ipmask_t *ai; const char *s; static struct { @@ -563,6 +715,14 @@ access_init(int createdefault) ae->ae_enabled = 1; ae->ae_rights = 0xffffffff; + ai = calloc(1, sizeof(access_ipmask_t)); + ai->ai_ipv6 = 0; + LIST_INSERT_HEAD(&ae->ae_ipmasks, ai, ai_link); + + ai = calloc(1, sizeof(access_ipmask_t)); + ai->ai_ipv6 = 1; + LIST_INSERT_HEAD(&ae->ae_ipmasks, ai, ai_link); + r = access_record_build(ae); dtable_record_store(dt, ae->ae_id, r); htsmsg_destroy(r); diff --git a/src/access.h b/src/access.h index 35bb1d83..466e380f 100644 --- a/src/access.h +++ b/src/access.h @@ -20,6 +20,20 @@ #define ACCESS_H_ +typedef struct access_ipmask { + LIST_ENTRY(access_ipmask) ai_link; + + int ai_ipv6; + + struct in_addr ai_ip; + struct in6_addr ai_ip6; + + int ai_prefixlen; + + uint32_t ai_network; + uint32_t ai_netmask; +} access_ipmask_t; + TAILQ_HEAD(access_entry_queue, access_entry); extern struct access_entry_queue access_entries; @@ -31,15 +45,12 @@ typedef struct access_entry { char *ae_username; char *ae_password; char *ae_comment; - struct in_addr ae_ip; - int ae_prefixlen; int ae_enabled; uint32_t ae_rights; - uint32_t ae_network; /* derived from ae_ip */ - uint32_t ae_netmask; /* derived from ae_prefixlen */ + LIST_HEAD(, access_ipmask) ae_ipmasks; } access_entry_t; TAILQ_HEAD(access_ticket_queue, access_ticket); diff --git a/src/capmt.c b/src/capmt.c old mode 100755 new mode 100644 diff --git a/src/dvr/dvr_rec.c b/src/dvr/dvr_rec.c old mode 100755 new mode 100644 diff --git a/src/htsp_server.c b/src/htsp_server.c index 79f1c946..a487a1d1 100644 --- a/src/htsp_server.c +++ b/src/htsp_server.c @@ -115,7 +115,7 @@ typedef struct htsp_connection { LIST_ENTRY(htsp_connection) htsp_link; int htsp_fd; - struct sockaddr_in *htsp_peer; + struct sockaddr_storage *htsp_peer; uint32_t htsp_version; @@ -464,19 +464,22 @@ htsp_build_channel(channel_t *ch, const char *method, htsp_connection_t *htsp) htsmsg_add_str(out, "channelName", ch->ch_name); if(ch->ch_icon != NULL) { uint32_t id; - struct sockaddr_in addr; + struct sockaddr_storage addr; socklen_t addrlen; if ((id = imagecache_get_id(ch->ch_icon))) { size_t p = 0; char url[256]; + char buf[50]; if (htsp->htsp_version < 8) { addrlen = sizeof(addr); getsockname(htsp->htsp_fd, (struct sockaddr*)&addr, &addrlen); + tcp_get_ip_str((struct sockaddr*)&addr, buf, 50); strcpy(url, "http://"); p = strlen(url); - inet_ntop(AF_INET, &addr.sin_addr, url+p, sizeof(url)-p); - p = strlen(url); - p += snprintf(url+p, sizeof(url)-p, ":%hd%s", + p += snprintf(url+p, sizeof(url)-p, "%s%s%s:%hd%s", + (addr.ss_family == AF_INET6)?"[":"", + buf, + (addr.ss_family == AF_INET6)?"]":"", tvheadend_webui_port, tvheadend_webroot ?: ""); } @@ -1871,14 +1874,14 @@ htsp_write_scheduler(void *aux) * */ static void -htsp_serve(int fd, void *opaque, struct sockaddr_in *source, - struct sockaddr_in *self) +htsp_serve(int fd, void *opaque, struct sockaddr_storage *source, + struct sockaddr_storage *self) { htsp_connection_t htsp; - char buf[30]; + char buf[50]; htsp_subscription_t *s; - snprintf(buf, sizeof(buf), "%s", inet_ntoa(source->sin_addr)); + tcp_get_ip_str((struct sockaddr*)source, buf, 50); memset(&htsp, 0, sizeof(htsp_connection_t)); diff --git a/src/http.c b/src/http.c index 610e72e3..c668a02f 100644 --- a/src/http.c +++ b/src/http.c @@ -247,9 +247,12 @@ void http_error(http_connection_t *hc, int error) { const char *errtxt = http_rc2str(error); + char *addrstr = (char*)malloc(50); + tcp_get_ip_str((struct sockaddr*)hc->hc_peer, addrstr, 50); tvhlog(LOG_ERR, "HTTP", "%s: %s -- %d", - inet_ntoa(hc->hc_peer->sin_addr), hc->hc_url, error); + addrstr, hc->hc_url, error); + free(addrstr); htsbuf_queue_flush(&hc->hc_reply); @@ -315,10 +318,13 @@ http_access_verify(http_connection_t *hc, int mask) { const char *ticket_id = http_arg_get(&hc->hc_req_args, "ticket"); - if(!access_ticket_verify(ticket_id, hc->hc_url)) { + if(!access_ticket_verify(ticket_id, hc->hc_url)) + { + char *addrstr = (char*)malloc(50); + tcp_get_ip_str((struct sockaddr*)hc->hc_peer, addrstr, 50); tvhlog(LOG_INFO, "HTTP", "%s: using ticket %s for %s", - inet_ntoa(hc->hc_peer->sin_addr), ticket_id, - hc->hc_url); + addrstr, ticket_id, hc->hc_url); + free(addrstr); return 0; } @@ -504,11 +510,9 @@ process_request(http_connection_t *hc, htsbuf_queue_t *spill) if(hc->hc_username != NULL) { hc->hc_representative = strdup(hc->hc_username); } else { - hc->hc_representative = malloc(30); + hc->hc_representative = malloc(50); /* Not threadsafe ? */ - snprintf(hc->hc_representative, 30, - "%s", inet_ntoa(hc->hc_peer->sin_addr)); - + tcp_get_ip_str((struct sockaddr*)hc->hc_peer, hc->hc_representative, 50); } switch(hc->hc_version) { @@ -777,8 +781,8 @@ http_serve_requests(http_connection_t *hc, htsbuf_queue_t *spill) * */ static void -http_serve(int fd, void *opaque, struct sockaddr_in *peer, - struct sockaddr_in *self) +http_serve(int fd, void *opaque, struct sockaddr_storage *peer, + struct sockaddr_storage *self) { htsbuf_queue_t spill; http_connection_t hc; diff --git a/src/http.h b/src/http.h index 2a29b8a9..9e3d061c 100644 --- a/src/http.h +++ b/src/http.h @@ -39,8 +39,8 @@ typedef struct http_arg { typedef struct http_connection { int hc_fd; - struct sockaddr_in *hc_peer; - struct sockaddr_in *hc_self; + struct sockaddr_storage *hc_peer; + struct sockaddr_storage *hc_self; char *hc_representative; char *hc_url; diff --git a/src/main.c b/src/main.c index c6e0254d..40261213 100644 --- a/src/main.c +++ b/src/main.c @@ -359,7 +359,8 @@ main(int argc, char **argv) opt_debug = 0, opt_syslog = 0, opt_uidebug = 0, - opt_abort = 0; + opt_abort = 0, + opt_ipv6 = 0; const char *opt_config = NULL, *opt_user = NULL, *opt_group = NULL, @@ -391,8 +392,8 @@ main(int argc, char **argv) { 'a', "adapters", "Use only specified DVB adapters", OPT_STR, &opt_dvb_adapters }, #endif - { 0, NULL, "Server Connectivity", OPT_BOOL, NULL }, + { '6', "ipv6", "Listen on IPv6", OPT_BOOL, &opt_ipv6 }, { 0, "http_port", "Specify alternative http port", OPT_INT, &tvheadend_webui_port }, { 0, "http_root", "Specify alternative http webroot", @@ -606,7 +607,7 @@ main(int argc, char **argv) timeshift_init(); #endif - tcp_server_init(); + tcp_server_init(opt_ipv6); http_server_init(); webui_init(); diff --git a/src/streaming.c b/src/streaming.c old mode 100755 new mode 100644 diff --git a/src/tcp.c b/src/tcp.c index a97b079b..5ccf1bac 100644 --- a/src/tcp.c +++ b/src/tcp.c @@ -35,6 +35,7 @@ #include "tcp.h" #include "tvheadend.h" +int tcp_preferred_address_family = AF_INET; /** * @@ -344,6 +345,31 @@ tcp_read_timeout(int fd, void *buf, size_t len, int timeout) } +/** + * + */ +char * +tcp_get_ip_str(const struct sockaddr *sa, char *s, size_t maxlen) +{ + if(sa == NULL || s == NULL) + return NULL; + + switch(sa->sa_family) + { + case AF_INET: + inet_ntop(AF_INET, &(((struct sockaddr_in*)sa)->sin_addr), s, maxlen); + break; + case AF_INET6: + inet_ntop(AF_INET6, &(((struct sockaddr_in6*)sa)->sin6_addr), s, maxlen); + break; + default: + strncpy(s, "Unknown AF", maxlen); + return NULL; + } + + return s; +} + /** * */ @@ -359,8 +385,8 @@ typedef struct tcp_server_launch_t { tcp_server_callback_t *start; void *opaque; int fd; - struct sockaddr_in peer; - struct sockaddr_in self; + struct sockaddr_storage peer; + struct sockaddr_storage self; } tcp_server_launch_t; @@ -443,7 +469,7 @@ tcp_server_loop(void *aux) tsl = malloc(sizeof(tcp_server_launch_t)); tsl->start = ts->start; tsl->opaque = ts->opaque; - slen = sizeof(struct sockaddr_in); + slen = sizeof(struct sockaddr_storage); tsl->fd = accept(ts->serverfd, (struct sockaddr *)&tsl->peer, &slen); @@ -455,7 +481,7 @@ tcp_server_loop(void *aux) } - slen = sizeof(struct sockaddr_in); + slen = sizeof(struct sockaddr_storage); if(getsockname(tsl->fd, (struct sockaddr *)&tsl->self, &slen)) { close(tsl->fd); free(tsl); @@ -478,21 +504,55 @@ tcp_server_create(int port, tcp_server_callback_t *start, void *opaque) int fd, x; struct epoll_event e; tcp_server_t *ts; - struct sockaddr_in s; + struct addrinfo hints, *res, *ressave, *use = NULL; + char *portBuf = (char*)malloc(6); int one = 1; + int zero = 0; + memset(&e, 0, sizeof(e)); - fd = tvh_socket(AF_INET, SOCK_STREAM, 0); + + snprintf(portBuf, 6, "%d", port); + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_flags = AI_PASSIVE; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + + x = getaddrinfo(NULL, portBuf, &hints, &res); + free(portBuf); + + if(x != 0) + return NULL; + + ressave = res; + while(res) + { + if(res->ai_family == tcp_preferred_address_family) + { + use = res; + break; + } + else if(use == NULL) + { + use = res; + } + res = res->ai_next; + } + + fd = tvh_socket(use->ai_family, use->ai_socktype, use->ai_protocol); if(fd == -1) return NULL; - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int)); + if(use->ai_family == AF_INET6) + setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &zero, sizeof(int)); - memset(&s, 0, sizeof(s)); - s.sin_family = AF_INET; - s.sin_port = htons(port); + setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(int)); - x = bind(fd, (struct sockaddr *)&s, sizeof(s)); - if(x < 0) { + x = bind(fd, use->ai_addr, use->ai_addrlen); + freeaddrinfo(ressave); + + if(x != 0) + { close(fd); return NULL; } @@ -504,11 +564,10 @@ tcp_server_create(int port, tcp_server_callback_t *start, void *opaque) ts->start = start; ts->opaque = opaque; - e.events = EPOLLIN; e.data.ptr = ts; - epoll_ctl(tcp_server_epoll_fd, EPOLL_CTL_ADD, fd, &e); + return ts; } @@ -516,10 +575,13 @@ tcp_server_create(int port, tcp_server_callback_t *start, void *opaque) * */ void -tcp_server_init(void) +tcp_server_init(int opt_ipv6) { pthread_t tid; + if(opt_ipv6) + tcp_preferred_address_family = AF_INET6; + tcp_server_epoll_fd = epoll_create(10); pthread_create(&tid, NULL, tcp_server_loop, NULL); } diff --git a/src/tcp.h b/src/tcp.h index e9d9534c..0c061e43 100644 --- a/src/tcp.h +++ b/src/tcp.h @@ -21,14 +21,16 @@ #include "htsbuf.h" -void tcp_server_init(void); +extern int tcp_preferred_address_family; + +void tcp_server_init(int opt_ipv6); int tcp_connect(const char *hostname, int port, char *errbuf, size_t errbufsize, int timeout); typedef void (tcp_server_callback_t)(int fd, void *opaque, - struct sockaddr_in *peer, - struct sockaddr_in *self); + struct sockaddr_storage *peer, + struct sockaddr_storage *self); void *tcp_server_create(int port, tcp_server_callback_t *start, void *opaque); @@ -44,4 +46,6 @@ int tcp_write_queue(int fd, htsbuf_queue_t *q); int tcp_read_timeout(int fd, void *buf, size_t len, int timeout); +char *tcp_get_ip_str(const struct sockaddr *sa, char *s, size_t maxlen); + #endif /* TCP_H_ */ diff --git a/src/webui/comet.c b/src/webui/comet.c index a540dbf6..aaf42ae0 100644 --- a/src/webui/comet.c +++ b/src/webui/comet.c @@ -32,6 +32,7 @@ #include "http.h" #include "webui/webui.h" #include "access.h" +#include "tcp.h" static pthread_mutex_t comet_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t comet_cond = PTHREAD_COND_INITIALIZER; @@ -153,16 +154,24 @@ comet_access_update(http_connection_t *hc, comet_mailbox_t *cmb) static void comet_serverIpPort(http_connection_t *hc, comet_mailbox_t *cmb) { - char buf[INET_ADDRSTRLEN + 1]; + char buf[50]; + uint32_t port; - inet_ntop(AF_INET, &hc->hc_self->sin_addr, buf, sizeof(buf)); + tcp_get_ip_str((struct sockaddr*)hc->hc_self, buf, 50); + + if(hc->hc_self->ss_family == AF_INET) + port = ((struct sockaddr_in*)hc->hc_self)->sin_port; + else if(hc->hc_self->ss_family == AF_INET6) + port = ((struct sockaddr_in6*)hc->hc_self)->sin6_port; + else + port = 0; htsmsg_t *m = htsmsg_create_map(); htsmsg_add_str(m, "notificationClass", "setServerIpPort"); htsmsg_add_str(m, "ip", buf); - htsmsg_add_u32(m, "port", ntohs(hc->hc_self->sin_port)); + htsmsg_add_u32(m, "port", ntohs(port)); if(cmb->cmb_messages == NULL) cmb->cmb_messages = htsmsg_create_list(); diff --git a/src/webui/webui.c b/src/webui/webui.c index 29fddf05..bc7d5989 100644 --- a/src/webui/webui.c +++ b/src/webui/webui.c @@ -45,6 +45,7 @@ #include "dvb/dvb.h" #include "dvb/dvb_support.h" #include "imagecache.h" +#include "tcp.h" /** * @@ -564,6 +565,7 @@ http_stream_service(http_connection_t *hc, service_t *service) const char *str; size_t qsize; const char *name; + char addrbuf[50]; mc = muxer_container_txt2type(http_arg_get(&hc->hc_req_args, "mux")); if(mc == MC_UNKNOWN) { @@ -590,8 +592,9 @@ http_stream_service(http_connection_t *hc, service_t *service) flags = 0; } + tcp_get_ip_str((struct sockaddr*)hc->hc_peer, addrbuf, 50); s = subscription_create_from_service(service, "HTTP", st, flags, - inet_ntoa(hc->hc_peer->sin_addr), + addrbuf, hc->hc_username, http_arg_get(&hc->hc_args, "User-Agent")); if(s) { @@ -625,10 +628,12 @@ http_stream_tdmi(http_connection_t *hc, th_dvb_mux_instance_t *tdmi) th_subscription_t *s; streaming_queue_t sq; const char *name; + char addrbuf[50]; streaming_queue_init(&sq, SMT_PACKET); + tcp_get_ip_str((struct sockaddr*)hc->hc_peer, addrbuf, 50); s = dvb_subscription_create_from_tdmi(tdmi, "HTTP", &sq.sq_st, - inet_ntoa(hc->hc_peer->sin_addr), + addrbuf, hc->hc_username, http_arg_get(&hc->hc_args, "User-Agent")); name = strdupa(tdmi->tdmi_identifier); @@ -662,6 +667,7 @@ http_stream_channel(http_connection_t *hc, channel_t *ch) char *str; size_t qsize; const char *name; + char addrbuf[50]; mc = muxer_container_txt2type(http_arg_get(&hc->hc_req_args, "mux")); if(mc == MC_UNKNOWN) { @@ -688,8 +694,9 @@ http_stream_channel(http_connection_t *hc, channel_t *ch) flags = 0; } + tcp_get_ip_str((struct sockaddr*)hc->hc_peer, addrbuf, 50); s = subscription_create_from_channel(ch, priority, "HTTP", st, flags, - inet_ntoa(hc->hc_peer->sin_addr), + addrbuf, hc->hc_username, http_arg_get(&hc->hc_args, "User-Agent"));