From: Jaroslav Kysela Date: Tue, 21 Nov 2017 09:37:49 +0000 (+0100) Subject: tcp: cleanups for ip_check functions X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3de659c83c589a95a9635096152ceaf8075cd966;p=thirdparty%2Ftvheadend.git tcp: cleanups for ip_check functions --- diff --git a/src/satip/rtsp.c b/src/satip/rtsp.c index 8f2aae8a6..5de4fdedb 100644 --- a/src/satip/rtsp.c +++ b/src/satip/rtsp.c @@ -325,7 +325,7 @@ rtsp_announced_port(struct sockaddr_storage *peer, struct sockaddr_storage *self { int used_port = 0; - if (satip_server_conf.satip_nat_name_force || !check_is_local_address(peer,self)) { + if (satip_server_conf.satip_nat_name_force || !ip_check_is_local_address(peer,self)) { used_port = (rtsp_nat_port > 0)? rtsp_nat_port : rtsp_port; } else { used_port = rtsp_port; @@ -342,7 +342,7 @@ rtsp_announced_ip(struct sockaddr_storage *peer, struct sockaddr_storage *self) { char *used_ip; - if (satip_server_conf.satip_nat_name_force || !check_is_local_address(peer,self)) { + if (satip_server_conf.satip_nat_name_force || !ip_check_is_local_address(peer,self)) { used_ip = rtsp_nat_ip; } else { used_ip = rtsp_ip; diff --git a/src/tcp.c b/src/tcp.c index 13be11313..4ac1f52f2 100644 --- a/src/tcp.c +++ b/src/tcp.c @@ -72,119 +72,37 @@ socket_set_dscp(int sockfd, uint32_t dscp, char *errbuf, size_t errbufsize) return 0; } -/** - * - */ -inline int -check_equal_v4(const struct in_addr * a, - const struct in_addr * b) -{ - return (a->s_addr == b->s_addr); -} - -/** - * - */ -inline int -check_equal_v6(const struct in6_addr * a, - const struct in6_addr * b) -{ - return (memcmp(a->s6_addr, b->s6_addr, 16) == 0) ? 1 : 0; -} - -/** - * - */ -inline int -check_in_network_v4(const struct in_addr * network, - const struct in_addr * mask, - const struct in_addr * address) -{ - return ((address->s_addr & mask->s_addr) == (network->s_addr & mask->s_addr)); -} - -/** - * - */ -inline int -check_in_network_v6(const struct in6_addr * network, - const struct in6_addr * mask, - const struct in6_addr * address) -{ - unsigned int i; - for (i=0; is_addr == INADDR_ANY); -} - -/** - * - */ -inline int -check_is_any_v6(const struct in6_addr * address) -{ - return (check_equal_v6(address,&in6addr_any)); -} - /** * */ int -check_is_local_address(const struct sockaddr_storage *peer, const struct sockaddr_storage *local) +ip_check_is_local_address + (const struct sockaddr_storage *peer, const struct sockaddr_storage *local) { struct ifaddrs *iflist, *ifdev = NULL; struct sockaddr_storage *ifaddr, *ifnetmask; - int any_address = 0; - - if ( (local->ss_family == AF_INET && check_is_any_v4(&((struct sockaddr_in *)local)->sin_addr) ) || - (local->ss_family == AF_INET6 && check_is_any_v6(&((struct sockaddr_in6 *)local)->sin6_addr) ) ) { - any_address = 1; - } - tvhdebug(LS_SATIPS, "tcp_is_local_address(): ANY=%i",any_address); + int any_address, ret; // Note: Not all platforms have getifaddrs() // See http://docs.freeswitch.org/switch__utils_8c_source.html - if (!local || !peer || getifaddrs(&iflist) < 0) return 0; + if (!local || !peer || getifaddrs(&iflist) < 0) + return 0; - for (ifdev = iflist; ifdev; ifdev = ifdev->ifa_next) { - ifaddr = (struct sockaddr_storage *)(ifdev->ifa_addr); - ifnetmask = (struct sockaddr_storage *)(ifdev->ifa_netmask); + if (peer->ss_family != local->ss_family) + return 0; - if (ifaddr && ifnetmask && ifaddr->ss_family == local->ss_family && ifaddr->ss_family == peer->ss_family) { + any_address = ip_check_is_any(local); - if (ifaddr->ss_family == AF_INET) { - if ((any_address || check_equal_v4( &((struct sockaddr_in *)ifaddr)->sin_addr, &((struct sockaddr_in *)local)->sin_addr )) - && check_in_network_v4( &((struct sockaddr_in *)ifaddr)->sin_addr, - &((struct sockaddr_in *)ifnetmask)->sin_addr, - &((struct sockaddr_in *)peer)->sin_addr) ) { - freeifaddrs(iflist); - return 1; - } - } else if (ifaddr->ss_family == AF_INET6) { - if ((any_address || check_equal_v6( &((struct sockaddr_in6 *)ifaddr)->sin6_addr, &((struct sockaddr_in6 *)local)->sin6_addr )) - && check_in_network_v6( &((struct sockaddr_in6 *)ifaddr)->sin6_addr, - &((struct sockaddr_in6 *)ifnetmask)->sin6_addr, - &((struct sockaddr_in6 *)peer)->sin6_addr) ) { - freeifaddrs(iflist); - return 1; - } - } - } + for (ifdev = iflist, ret = 0; ifdev && ret == 0; ifdev = ifdev->ifa_next) { + ifaddr = (struct sockaddr_storage *)(ifdev->ifa_addr); + ifnetmask = (struct sockaddr_storage *)(ifdev->ifa_netmask); + if (!ifaddr || !ifnetmask) continue; + if (ifaddr->ss_family != local->ss_family) continue; + if (!any_address && !ip_check_equal(ifaddr, local)) continue; + ret = !!ip_check_in_network_v4(ifaddr, ifnetmask, peer); } freeifaddrs(iflist); - return 0; + return ret; } /** diff --git a/src/tcp.h b/src/tcp.h index e7501c4f4..97d34e6cd 100644 --- a/src/tcp.h +++ b/src/tcp.h @@ -58,17 +58,53 @@ void tcp_server_preinit(int opt_ipv6); void tcp_server_init(void); void tcp_server_done(void); -int check_equal_v4(const struct in_addr * a, const struct in_addr * b); -int check_equal_v6(const struct in6_addr * a, const struct in6_addr * b); -int check_in_network_v4(const struct in_addr * network, - const struct in_addr * mask, - const struct in_addr * address); -int check_in_network_v6(const struct in6_addr * network, - const struct in6_addr * mask, - const struct in6_addr * address); -int check_is_any_v4(const struct in_addr * address); -int check_is_any_v6(const struct in6_addr * address); -int check_is_local_address(const struct sockaddr_storage *peer, const struct sockaddr_storage *local); +static inline int ip_check_equal_v4 + (const struct sockaddr_storage *a, const struct sockaddr_storage *b) + { return IP_AS_V4(a, addr).s_addr == IP_AS_V4(b, addr).s_addr; } + +static inline int ip_check_equal_v6 + (const struct sockaddr_storage *a, const struct sockaddr_storage *b) + { return ((uint64_t *)IP_AS_V6(a, addr).s6_addr)[0] == ((uint64_t *)IP_AS_V6(b, addr).s6_addr)[0] && + ((uint64_t *)IP_AS_V6(a, addr).s6_addr)[1] == ((uint64_t *)IP_AS_V6(b, addr).s6_addr)[1]; } + +static inline int ip_check_equal + (const struct sockaddr_storage *a, const struct sockaddr_storage *b) + { return a->ss_family == b->ss_family && + a->ss_family == AF_INET ? ip_check_equal_v4(a, b) : + (a->ss_family == AF_INET6 ? ip_check_equal_v6(a, b) : 0); } + +static inline int ip_check_in_network_v4(const struct sockaddr_storage *network, + const struct sockaddr_storage *mask, + const struct sockaddr_storage *address) + { return (IP_AS_V4(address, addr).s_addr & IP_AS_V4(mask, addr).s_addr) == + (IP_AS_V4(network, addr).s_addr & IP_AS_V4(mask, addr).s_addr); } + +static inline int ip_check_in_network_v6(const struct sockaddr_storage *network, + const struct sockaddr_storage *mask, + const struct sockaddr_storage *address) + { return (((uint64_t *)IP_AS_V6(address, addr).s6_addr)[0] & ((uint64_t *)IP_AS_V6(mask, addr).s6_addr)[0]) == + (((uint64_t *)IP_AS_V6(network, addr).s6_addr)[0] & ((uint64_t *)IP_AS_V6(mask, addr).s6_addr)[0]) && + (((uint64_t *)IP_AS_V6(address, addr).s6_addr)[0] & ((uint64_t *)IP_AS_V6(mask, addr).s6_addr)[1]) == + (((uint64_t *)IP_AS_V6(network, addr).s6_addr)[1] & ((uint64_t *)IP_AS_V6(mask, addr).s6_addr)[1]); } + +static inline int ip_check_in_network(const struct sockaddr_storage *network, + const struct sockaddr_storage *mask, + const struct sockaddr_storage *address) + { return address->ss_family == AF_INET ? ip_check_in_network_v4(network, mask, address) : + (address->ss_family == AF_INET6 ? ip_check_in_network_v6(network, mask, address) : 0); } + +static inline int ip_check_is_any_v4(const struct sockaddr_storage *address) + { return IP_AS_V4(address, addr).s_addr == INADDR_ANY; } + +static inline int ip_check_is_any_v6(const struct sockaddr_storage *address) + { return ((uint64_t *)IP_AS_V6(address, addr).s6_addr)[0] == ((uint64_t *)(&in6addr_any.s6_addr))[0] && + ((uint64_t *)IP_AS_V6(address, addr).s6_addr)[1] == ((uint64_t *)(&in6addr_any.s6_addr))[1]; } + +static inline int ip_check_is_any(const struct sockaddr_storage *address) + { return address->ss_family == AF_INET ? ip_check_is_any_v4(address) : + (address->ss_family == AF_INET6 ? ip_check_is_any_v6(address) : 0); } + +int ip_check_is_local_address(const struct sockaddr_storage *peer, const struct sockaddr_storage *local); int socket_set_dscp(int sockfd, uint32_t dscp, char *errbuf, size_t errbufsize);