diff options
Diffstat (limited to 'src/pulsecore/ipacl.c')
| -rw-r--r-- | src/pulsecore/ipacl.c | 100 |
1 files changed, 62 insertions, 38 deletions
diff --git a/src/pulsecore/ipacl.c b/src/pulsecore/ipacl.c index 06be0a28..5455d0e8 100644 --- a/src/pulsecore/ipacl.c +++ b/src/pulsecore/ipacl.c @@ -1,18 +1,19 @@ -/* $Id$ */ - /*** This file is part of PulseAudio. - + + Copyright 2004-2006 Lennart Poettering + Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB + PulseAudio is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + PulseAudio is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with PulseAudio; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -23,25 +24,38 @@ #include <config.h> #endif -#include <sys/socket.h> -#include <netinet/in.h> -#include <netinet/ip.h> #include <sys/types.h> -#include <arpa/inet.h> +#include <sys/types.h> #include <string.h> +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#ifdef HAVE_NETINET_IN_SYSTM_H +#include <netinet/in_systm.h> +#endif +#ifdef HAVE_NETINET_IP_H +#include <netinet/ip.h> +#endif + +#include <pulse/xmalloc.h> + #include <pulsecore/core-util.h> #include <pulsecore/llist.h> #include <pulsecore/log.h> -#include <pulse/xmalloc.h> +#include <pulsecore/macro.h> +#include <pulsecore/socket.h> +#include <pulsecore/arpa-inet.h> #include "ipacl.h" struct acl_entry { PA_LLIST_FIELDS(struct acl_entry); - int family; + int family; struct in_addr address_ipv4; +#ifdef HAVE_IPV6 struct in6_addr address_ipv6; +#endif int bits; }; @@ -54,11 +68,11 @@ pa_ip_acl* pa_ip_acl_new(const char *s) { char *a; pa_ip_acl *acl; - assert(s); - + pa_assert(s); + acl = pa_xnew(pa_ip_acl, 1); PA_LLIST_HEAD_INIT(struct acl_entry, acl->entries); - + while ((a = pa_split(s, ";", &state))) { char *slash; struct acl_entry e, *n; @@ -68,7 +82,7 @@ pa_ip_acl* pa_ip_acl_new(const char *s) { *slash = 0; slash++; if (pa_atou(slash, &bits) < 0) { - pa_log(__FILE__": failed to parse number of bits: %s", slash); + pa_log_warn("Failed to parse number of bits: %s", slash); goto fail; } } else @@ -77,23 +91,24 @@ pa_ip_acl* pa_ip_acl_new(const char *s) { if (inet_pton(AF_INET, a, &e.address_ipv4) > 0) { e.bits = bits == (uint32_t) -1 ? 32 : (int) bits; - + if (e.bits > 32) { - pa_log(__FILE__": number of bits out of range: %i", e.bits); + pa_log_warn("Number of bits out of range: %i", e.bits); goto fail; } e.family = AF_INET; if (e.bits < 32 && (uint32_t) (ntohl(e.address_ipv4.s_addr) << e.bits) != 0) - pa_log_warn(__FILE__": WARNING: Host part of ACL entry '%s/%u' is not zero!", a, e.bits); - + pa_log_warn("Host part of ACL entry '%s/%u' is not zero!", a, e.bits); + +#ifdef HAVE_IPV6 } else if (inet_pton(AF_INET6, a, &e.address_ipv6) > 0) { e.bits = bits == (uint32_t) -1 ? 128 : (int) bits; if (e.bits > 128) { - pa_log(__FILE__": number of bits out of range: %i", e.bits); + pa_log_warn("Number of bits out of range: %i", e.bits); goto fail; } e.family = AF_INET6; @@ -101,9 +116,9 @@ pa_ip_acl* pa_ip_acl_new(const char *s) { if (e.bits < 128) { int t = 0, i; - for (i = 0, bits = e.bits; i < 16; i++) { + for (i = 0, bits = (uint32_t) e.bits; i < 16; i++) { - if (bits >= 8) + if (bits >= 8) bits -= 8; else { if ((uint8_t) ((e.address_ipv6.s6_addr[i]) << bits) != 0) { @@ -115,62 +130,69 @@ pa_ip_acl* pa_ip_acl_new(const char *s) { } if (t) - pa_log_warn(__FILE__": WARNING: Host part of ACL entry '%s/%u' is not zero!", a, e.bits); + pa_log_warn("Host part of ACL entry '%s/%u' is not zero!", a, e.bits); } - +#endif + } else { - pa_log(__FILE__": failed to parse address: %s", a); + pa_log_warn("Failed to parse address: %s", a); goto fail; } n = pa_xmemdup(&e, sizeof(struct acl_entry)); PA_LLIST_PREPEND(struct acl_entry, acl->entries, n); - + pa_xfree(a); } return acl; - + fail: pa_xfree(a); pa_ip_acl_free(acl); - + return NULL; } void pa_ip_acl_free(pa_ip_acl *acl) { - assert(acl); + pa_assert(acl); while (acl->entries) { struct acl_entry *e = acl->entries; PA_LLIST_REMOVE(struct acl_entry, acl->entries, e); pa_xfree(e); } - + pa_xfree(acl); } int pa_ip_acl_check(pa_ip_acl *acl, int fd) { struct sockaddr_storage sa; struct acl_entry *e; - socklen_t salen; - - assert(acl); - assert(fd >= 0); + socklen_t salen; + + pa_assert(acl); + pa_assert(fd >= 0); salen = sizeof(sa); if (getpeername(fd, (struct sockaddr*) &sa, &salen) < 0) return -1; +#ifdef HAVE_IPV6 if (sa.ss_family != AF_INET && sa.ss_family != AF_INET6) +#else + if (sa.ss_family != AF_INET) +#endif return -1; if (sa.ss_family == AF_INET && salen != sizeof(struct sockaddr_in)) return -1; +#ifdef HAVE_IPV6 if (sa.ss_family == AF_INET6 && salen != sizeof(struct sockaddr_in6)) return -1; - +#endif + for (e = acl->entries; e; e = e->next) { if (e->family != sa.ss_family) @@ -178,12 +200,13 @@ int pa_ip_acl_check(pa_ip_acl *acl, int fd) { if (e->family == AF_INET) { struct sockaddr_in *sai = (struct sockaddr_in*) &sa; - + if (e->bits == 0 || /* this needs special handling because >> takes the right-hand side modulo 32 */ (ntohl(sai->sin_addr.s_addr ^ e->address_ipv4.s_addr) >> (32 - e->bits)) == 0) return 1; +#ifdef HAVE_IPV6 } else if (e->family == AF_INET6) { - int i, bits ; + int i, bits; struct sockaddr_in6 *sai = (struct sockaddr_in6*) &sa; if (e->bits == 128) @@ -191,7 +214,7 @@ int pa_ip_acl_check(pa_ip_acl *acl, int fd) { if (e->bits == 0) return 1; - + for (i = 0, bits = e->bits; i < 16; i++) { if (bits >= 8) { @@ -209,6 +232,7 @@ int pa_ip_acl_check(pa_ip_acl *acl, int fd) { if (bits == 0) return 1; } +#endif } } |
