]>
code.delx.au - pulseaudio/blob - src/pulsecore/ipacl.c
2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as
9 published by the Free Software Foundation; either version 2.1 of the
10 License, or (at your option) any later version.
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
27 #include <sys/types.h>
28 #include <sys/types.h>
31 #ifdef HAVE_NETINET_IN_H
32 #include <netinet/in.h>
34 #ifdef HAVE_NETINET_IN_SYSTM_H
35 #include <netinet/in_systm.h>
37 #ifdef HAVE_NETINET_IP_H
38 #include <netinet/ip.h>
40 #ifdef HAVE_ARPA_INET_H
41 #include <arpa/inet.h>
44 #include <pulse/xmalloc.h>
46 #include <pulsecore/core-util.h>
47 #include <pulsecore/llist.h>
48 #include <pulsecore/log.h>
49 #include <pulsecore/macro.h>
50 #include <pulsecore/socket.h>
52 #ifndef HAVE_INET_PTON
53 #include <pulsecore/inet_pton.h>
59 PA_LLIST_FIELDS(struct acl_entry
);
61 struct in_addr address_ipv4
;
63 struct in6_addr address_ipv6
;
69 PA_LLIST_HEAD(struct acl_entry
, entries
);
72 pa_ip_acl
* pa_ip_acl_new(const char *s
) {
73 const char *state
= NULL
;
79 acl
= pa_xnew(pa_ip_acl
, 1);
80 PA_LLIST_HEAD_INIT(struct acl_entry
, acl
->entries
);
82 while ((a
= pa_split(s
, ";", &state
))) {
84 struct acl_entry e
, *n
;
87 if ((slash
= strchr(a
, '/'))) {
90 if (pa_atou(slash
, &bits
) < 0) {
91 pa_log_warn("Failed to parse number of bits: %s", slash
);
97 if (inet_pton(AF_INET
, a
, &e
.address_ipv4
) > 0) {
99 e
.bits
= bits
== (uint32_t) -1 ? 32 : (int) bits
;
102 pa_log_warn("Number of bits out of range: %i", e
.bits
);
108 if (e
.bits
< 32 && (uint32_t) (ntohl(e
.address_ipv4
.s_addr
) << e
.bits
) != 0)
109 pa_log_warn("Host part of ACL entry '%s/%u' is not zero!", a
, e
.bits
);
112 } else if (inet_pton(AF_INET6
, a
, &e
.address_ipv6
) > 0) {
114 e
.bits
= bits
== (uint32_t) -1 ? 128 : (int) bits
;
117 pa_log_warn("Number of bits out of range: %i", e
.bits
);
125 for (i
= 0, bits
= (uint32_t) e
.bits
; i
< 16; i
++) {
130 if ((uint8_t) ((e
.address_ipv6
.s6_addr
[i
]) << bits
) != 0) {
139 pa_log_warn("Host part of ACL entry '%s/%u' is not zero!", a
, e
.bits
);
144 pa_log_warn("Failed to parse address: %s", a
);
148 n
= pa_xmemdup(&e
, sizeof(struct acl_entry
));
149 PA_LLIST_PREPEND(struct acl_entry
, acl
->entries
, n
);
163 void pa_ip_acl_free(pa_ip_acl
*acl
) {
166 while (acl
->entries
) {
167 struct acl_entry
*e
= acl
->entries
;
168 PA_LLIST_REMOVE(struct acl_entry
, acl
->entries
, e
);
175 int pa_ip_acl_check(pa_ip_acl
*acl
, int fd
) {
176 struct sockaddr_storage sa
;
184 if (getpeername(fd
, (struct sockaddr
*) &sa
, &salen
) < 0)
188 if (sa
.ss_family
!= AF_INET
&& sa
.ss_family
!= AF_INET6
)
190 if (sa
.ss_family
!= AF_INET
)
194 if (sa
.ss_family
== AF_INET
&& salen
!= sizeof(struct sockaddr_in
))
198 if (sa
.ss_family
== AF_INET6
&& salen
!= sizeof(struct sockaddr_in6
))
202 for (e
= acl
->entries
; e
; e
= e
->next
) {
204 if (e
->family
!= sa
.ss_family
)
207 if (e
->family
== AF_INET
) {
208 struct sockaddr_in
*sai
= (struct sockaddr_in
*) &sa
;
210 if (e
->bits
== 0 || /* this needs special handling because >> takes the right-hand side modulo 32 */
211 (ntohl(sai
->sin_addr
.s_addr
^ e
->address_ipv4
.s_addr
) >> (32 - e
->bits
)) == 0)
214 } else if (e
->family
== AF_INET6
) {
216 struct sockaddr_in6
*sai
= (struct sockaddr_in6
*) &sa
;
219 return memcmp(&sai
->sin6_addr
, &e
->address_ipv6
, 16) == 0;
224 for (i
= 0, bits
= e
->bits
; i
< 16; i
++) {
227 if (sai
->sin6_addr
.s6_addr
[i
] != e
->address_ipv6
.s6_addr
[i
])
232 if ((sai
->sin6_addr
.s6_addr
[i
] ^ e
->address_ipv6
.s6_addr
[i
]) >> (8 - bits
) != 0)