]>
code.delx.au - pulseaudio/blob - src/pulsecore/ipacl.c
4 This file is part of PulseAudio.
6 PulseAudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as
8 published by the Free Software Foundation; either version 2.1 of the
9 License, or (at your option) any later version.
11 PulseAudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with PulseAudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
26 #include <sys/socket.h>
27 #include <netinet/in.h>
28 #include <netinet/ip.h>
29 #include <sys/types.h>
30 #include <arpa/inet.h>
33 #include <pulsecore/core-util.h>
34 #include <pulsecore/llist.h>
35 #include <pulsecore/log.h>
36 #include <pulse/xmalloc.h>
41 PA_LLIST_FIELDS(struct acl_entry
);
43 struct in_addr address_ipv4
;
44 struct in6_addr address_ipv6
;
49 PA_LLIST_HEAD(struct acl_entry
, entries
);
52 pa_ip_acl
* pa_ip_acl_new(const char *s
) {
53 const char *state
= NULL
;
59 acl
= pa_xnew(pa_ip_acl
, 1);
60 PA_LLIST_HEAD_INIT(struct acl_entry
, acl
->entries
);
62 while ((a
= pa_split(s
, ";", &state
))) {
64 struct acl_entry e
, *n
;
67 if ((slash
= strchr(a
, '/'))) {
70 if (pa_atou(slash
, &bits
) < 0) {
71 pa_log(__FILE__
": failed to parse number of bits: %s", slash
);
77 if (inet_pton(AF_INET
, a
, &e
.address_ipv4
) > 0) {
79 e
.bits
= bits
== (uint32_t) -1 ? 32 : (int) bits
;
82 pa_log(__FILE__
": number of bits out of range: %i", e
.bits
);
88 if (e
.bits
< 32 && (uint32_t) (ntohl(e
.address_ipv4
.s_addr
) << e
.bits
) != 0)
89 pa_log_warn(__FILE__
": WARNING: Host part of ACL entry '%s/%u' is not zero!", a
, e
.bits
);
91 } else if (inet_pton(AF_INET6
, a
, &e
.address_ipv6
) > 0) {
93 e
.bits
= bits
== (uint32_t) -1 ? 128 : (int) bits
;
96 pa_log(__FILE__
": number of bits out of range: %i", e
.bits
);
104 for (i
= 0, bits
= e
.bits
; i
< 16; i
++) {
109 if ((uint8_t) ((e
.address_ipv6
.s6_addr
[i
]) << bits
) != 0) {
118 pa_log_warn(__FILE__
": WARNING: Host part of ACL entry '%s/%u' is not zero!", a
, e
.bits
);
122 pa_log(__FILE__
": failed to parse address: %s", a
);
126 n
= pa_xmemdup(&e
, sizeof(struct acl_entry
));
127 PA_LLIST_PREPEND(struct acl_entry
, acl
->entries
, n
);
141 void pa_ip_acl_free(pa_ip_acl
*acl
) {
144 while (acl
->entries
) {
145 struct acl_entry
*e
= acl
->entries
;
146 PA_LLIST_REMOVE(struct acl_entry
, acl
->entries
, e
);
153 int pa_ip_acl_check(pa_ip_acl
*acl
, int fd
) {
154 struct sockaddr_storage sa
;
162 if (getpeername(fd
, (struct sockaddr
*) &sa
, &salen
) < 0)
165 if (sa
.ss_family
!= AF_INET
&& sa
.ss_family
!= AF_INET6
)
168 if (sa
.ss_family
== AF_INET
&& salen
!= sizeof(struct sockaddr_in
))
171 if (sa
.ss_family
== AF_INET6
&& salen
!= sizeof(struct sockaddr_in6
))
174 for (e
= acl
->entries
; e
; e
= e
->next
) {
176 if (e
->family
!= sa
.ss_family
)
179 if (e
->family
== AF_INET
) {
180 struct sockaddr_in
*sai
= (struct sockaddr_in
*) &sa
;
182 if (e
->bits
== 0 || /* this needs special handling because >> takes the right-hand side modulo 32 */
183 (ntohl(sai
->sin_addr
.s_addr
^ e
->address_ipv4
.s_addr
) >> (32 - e
->bits
)) == 0)
185 } else if (e
->family
== AF_INET6
) {
187 struct sockaddr_in6
*sai
= (struct sockaddr_in6
*) &sa
;
190 return memcmp(&sai
->sin6_addr
, &e
->address_ipv6
, 16) == 0;
195 for (i
= 0, bits
= e
->bits
; i
< 16; i
++) {
198 if (sai
->sin6_addr
.s6_addr
[i
] != e
->address_ipv6
.s6_addr
[i
])
203 if ((sai
->sin6_addr
.s6_addr
[i
] ^ e
->address_ipv6
.s6_addr
[i
]) >> (8 - bits
) != 0)