2010-08-14 21:59:25 +04:00
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2010-01-19 04:56:37 +03:00
2010-02-03 15:03:47 +03:00
/***
This file is part of systemd .
Copyright 2010 Lennart Poettering
systemd is free software ; you can redistribute it and / or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
systemd 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
General Public License for more details .
You should have received a copy of the GNU General Public License
along with systemd ; If not , see < http : //www.gnu.org/licenses/>.
* * */
2010-01-19 04:56:37 +03:00
# include <assert.h>
# include <string.h>
# include <unistd.h>
# include <errno.h>
# include <stdlib.h>
# include <arpa/inet.h>
# include <stdio.h>
2010-01-23 05:35:54 +03:00
# include <net/if.h>
2010-02-12 04:02:14 +03:00
# include <sys/types.h>
# include <sys/stat.h>
2010-10-07 04:34:17 +04:00
# include <stddef.h>
# include <sys/ioctl.h>
2010-01-19 04:56:37 +03:00
# include "macro.h"
# include "util.h"
# include "socket-util.h"
2010-07-01 19:44:13 +04:00
# include "missing.h"
2010-08-12 00:58:34 +04:00
# include "label.h"
2010-01-19 04:56:37 +03:00
2010-01-23 05:35:54 +03:00
int socket_address_parse ( SocketAddress * a , const char * s ) {
2010-01-19 04:56:37 +03:00
int r ;
char * e , * n ;
unsigned u ;
assert ( a ) ;
assert ( s ) ;
2010-01-24 02:39:29 +03:00
zero ( * a ) ;
2010-01-23 05:35:54 +03:00
a - > type = SOCK_STREAM ;
2010-01-19 04:56:37 +03:00
if ( * s = = ' [ ' ) {
/* IPv6 in [x:.....:z]:p notation */
2010-09-20 23:33:14 +04:00
if ( ! socket_ipv6_is_supported ( ) ) {
log_warning ( " Binding to IPv6 address not available since kernel does not support IPv6. " ) ;
return - EAFNOSUPPORT ;
}
2010-01-19 04:56:37 +03:00
if ( ! ( e = strchr ( s + 1 , ' ] ' ) ) )
return - EINVAL ;
if ( ! ( n = strndup ( s + 1 , e - s - 1 ) ) )
return - ENOMEM ;
errno = 0 ;
if ( inet_pton ( AF_INET6 , n , & a - > sockaddr . in6 . sin6_addr ) < = 0 ) {
free ( n ) ;
return errno ! = 0 ? - errno : - EINVAL ;
}
free ( n ) ;
e + + ;
if ( * e ! = ' : ' )
return - EINVAL ;
e + + ;
if ( ( r = safe_atou ( e , & u ) ) < 0 )
return r ;
if ( u < = 0 | | u > 0xFFFF )
return - EINVAL ;
a - > sockaddr . in6 . sin6_family = AF_INET6 ;
a - > sockaddr . in6 . sin6_port = htons ( ( uint16_t ) u ) ;
a - > size = sizeof ( struct sockaddr_in6 ) ;
} else if ( * s = = ' / ' ) {
/* AF_UNIX socket */
size_t l ;
l = strlen ( s ) ;
if ( l > = sizeof ( a - > sockaddr . un . sun_path ) )
return - EINVAL ;
a - > sockaddr . un . sun_family = AF_UNIX ;
memcpy ( a - > sockaddr . un . sun_path , s , l ) ;
2010-10-07 04:34:17 +04:00
a - > size = offsetof ( struct sockaddr_un , sun_path ) + l + 1 ;
2010-01-19 04:56:37 +03:00
2010-01-28 06:50:28 +03:00
} else if ( * s = = ' @ ' ) {
2010-01-19 04:56:37 +03:00
/* Abstract AF_UNIX socket */
size_t l ;
l = strlen ( s + 1 ) ;
if ( l > = sizeof ( a - > sockaddr . un . sun_path ) - 1 )
return - EINVAL ;
a - > sockaddr . un . sun_family = AF_UNIX ;
memcpy ( a - > sockaddr . un . sun_path + 1 , s + 1 , l ) ;
2010-10-07 04:34:17 +04:00
a - > size = offsetof ( struct sockaddr_un , sun_path ) + 1 + l ;
2010-01-19 04:56:37 +03:00
} else {
if ( ( e = strchr ( s , ' : ' ) ) ) {
2010-01-23 05:35:54 +03:00
if ( ( r = safe_atou ( e + 1 , & u ) ) < 0 )
return r ;
if ( u < = 0 | | u > 0xFFFF )
return - EINVAL ;
2010-01-19 04:56:37 +03:00
if ( ! ( n = strndup ( s , e - s ) ) )
return - ENOMEM ;
2010-01-23 05:35:54 +03:00
/* IPv4 in w.x.y.z:p notation? */
if ( ( r = inet_pton ( AF_INET , n , & a - > sockaddr . in4 . sin_addr ) ) < 0 ) {
2010-01-19 04:56:37 +03:00
free ( n ) ;
2010-01-23 05:35:54 +03:00
return - errno ;
2010-01-19 04:56:37 +03:00
}
2010-01-23 05:35:54 +03:00
if ( r > 0 ) {
/* Gotcha, it's a traditional IPv4 address */
free ( n ) ;
2010-01-19 04:56:37 +03:00
2010-01-23 05:35:54 +03:00
a - > sockaddr . in4 . sin_family = AF_INET ;
a - > sockaddr . in4 . sin_port = htons ( ( uint16_t ) u ) ;
a - > size = sizeof ( struct sockaddr_in ) ;
} else {
unsigned idx ;
2010-01-19 04:56:37 +03:00
2010-01-27 06:31:52 +03:00
if ( strlen ( n ) > IF_NAMESIZE - 1 ) {
free ( n ) ;
return - EINVAL ;
}
2010-01-23 05:35:54 +03:00
/* Uh, our last resort, an interface name */
idx = if_nametoindex ( n ) ;
free ( n ) ;
2010-01-24 00:56:47 +03:00
if ( idx = = 0 )
2010-01-23 05:35:54 +03:00
return - EINVAL ;
2010-01-19 04:56:37 +03:00
2010-09-20 23:33:14 +04:00
if ( ! socket_ipv6_is_supported ( ) ) {
log_warning ( " Binding to interface is not available since kernel does not support IPv6. " ) ;
return - EAFNOSUPPORT ;
}
2010-01-23 05:35:54 +03:00
a - > sockaddr . in6 . sin6_family = AF_INET6 ;
a - > sockaddr . in6 . sin6_port = htons ( ( uint16_t ) u ) ;
a - > sockaddr . in6 . sin6_scope_id = idx ;
2010-01-24 00:56:47 +03:00
a - > sockaddr . in6 . sin6_addr = in6addr_any ;
2010-01-23 05:35:54 +03:00
a - > size = sizeof ( struct sockaddr_in6 ) ;
}
2010-01-19 04:56:37 +03:00
} else {
/* Just a port */
if ( ( r = safe_atou ( s , & u ) ) < 0 )
return r ;
if ( u < = 0 | | u > 0xFFFF )
return - EINVAL ;
2010-09-20 23:33:14 +04:00
if ( socket_ipv6_is_supported ( ) ) {
a - > sockaddr . in6 . sin6_family = AF_INET6 ;
a - > sockaddr . in6 . sin6_port = htons ( ( uint16_t ) u ) ;
a - > sockaddr . in6 . sin6_addr = in6addr_any ;
a - > size = sizeof ( struct sockaddr_in6 ) ;
} else {
a - > sockaddr . in4 . sin_family = AF_INET ;
a - > sockaddr . in4 . sin_port = htons ( ( uint16_t ) u ) ;
a - > sockaddr . in4 . sin_addr . s_addr = INADDR_ANY ;
a - > size = sizeof ( struct sockaddr_in ) ;
}
2010-01-19 04:56:37 +03:00
}
}
return 0 ;
}
2010-01-23 05:35:54 +03:00
int socket_address_verify ( const SocketAddress * a ) {
2010-01-19 04:56:37 +03:00
assert ( a ) ;
2010-01-23 05:35:54 +03:00
switch ( socket_address_family ( a ) ) {
2010-01-19 04:56:37 +03:00
case AF_INET :
if ( a - > size ! = sizeof ( struct sockaddr_in ) )
return - EINVAL ;
if ( a - > sockaddr . in4 . sin_port = = 0 )
return - EINVAL ;
return 0 ;
case AF_INET6 :
if ( a - > size ! = sizeof ( struct sockaddr_in6 ) )
return - EINVAL ;
if ( a - > sockaddr . in6 . sin6_port = = 0 )
return - EINVAL ;
return 0 ;
case AF_UNIX :
2010-10-07 04:34:17 +04:00
if ( a - > size < offsetof ( struct sockaddr_un , sun_path ) )
2010-01-19 04:56:37 +03:00
return - EINVAL ;
2010-10-07 04:34:17 +04:00
if ( a - > size > offsetof ( struct sockaddr_un , sun_path ) ) {
2010-01-19 04:56:37 +03:00
2010-07-11 04:23:11 +04:00
if ( a - > sockaddr . un . sun_path [ 0 ] ! = 0 ) {
2010-01-19 04:56:37 +03:00
char * e ;
/* path */
if ( ! ( e = memchr ( a - > sockaddr . un . sun_path , 0 , sizeof ( a - > sockaddr . un . sun_path ) ) ) )
return - EINVAL ;
2010-10-07 04:34:17 +04:00
if ( a - > size ! = offsetof ( struct sockaddr_un , sun_path ) + ( e - a - > sockaddr . un . sun_path ) + 1 )
2010-01-19 04:56:37 +03:00
return - EINVAL ;
}
}
return 0 ;
default :
return - EAFNOSUPPORT ;
}
}
2010-01-23 05:35:54 +03:00
int socket_address_print ( const SocketAddress * a , char * * p ) {
2010-01-19 04:56:37 +03:00
int r ;
assert ( a ) ;
assert ( p ) ;
2010-01-23 05:35:54 +03:00
if ( ( r = socket_address_verify ( a ) ) < 0 )
2010-01-19 04:56:37 +03:00
return r ;
2010-01-23 05:35:54 +03:00
switch ( socket_address_family ( a ) ) {
2010-01-19 04:56:37 +03:00
case AF_INET : {
char * ret ;
if ( ! ( ret = new ( char , INET_ADDRSTRLEN + 1 + 5 + 1 ) ) )
return - ENOMEM ;
if ( ! inet_ntop ( AF_INET , & a - > sockaddr . in4 . sin_addr , ret , INET_ADDRSTRLEN ) ) {
free ( ret ) ;
return - errno ;
}
sprintf ( strchr ( ret , 0 ) , " :%u " , ntohs ( a - > sockaddr . in4 . sin_port ) ) ;
* p = ret ;
return 0 ;
}
case AF_INET6 : {
char * ret ;
if ( ! ( ret = new ( char , 1 + INET6_ADDRSTRLEN + 2 + 5 + 1 ) ) )
return - ENOMEM ;
ret [ 0 ] = ' [ ' ;
if ( ! inet_ntop ( AF_INET6 , & a - > sockaddr . in6 . sin6_addr , ret + 1 , INET6_ADDRSTRLEN ) ) {
free ( ret ) ;
return - errno ;
}
sprintf ( strchr ( ret , 0 ) , " ]:%u " , ntohs ( a - > sockaddr . in6 . sin6_port ) ) ;
* p = ret ;
return 0 ;
}
case AF_UNIX : {
char * ret ;
2010-10-07 04:34:17 +04:00
if ( a - > size < = offsetof ( struct sockaddr_un , sun_path ) ) {
2010-01-19 04:56:37 +03:00
if ( ! ( ret = strdup ( " <unamed> " ) ) )
return - ENOMEM ;
} else if ( a - > sockaddr . un . sun_path [ 0 ] = = 0 ) {
/* abstract */
/* FIXME: We assume we can print the
* socket path here and that it hasn ' t
* more than one NUL byte . That is
* actually an invalid assumption */
if ( ! ( ret = new ( char , sizeof ( a - > sockaddr . un . sun_path ) + 1 ) ) )
return - ENOMEM ;
2010-01-28 06:50:28 +03:00
ret [ 0 ] = ' @ ' ;
2010-01-19 04:56:37 +03:00
memcpy ( ret + 1 , a - > sockaddr . un . sun_path + 1 , sizeof ( a - > sockaddr . un . sun_path ) - 1 ) ;
ret [ sizeof ( a - > sockaddr . un . sun_path ) ] = 0 ;
} else {
if ( ! ( ret = strdup ( a - > sockaddr . un . sun_path ) ) )
return - ENOMEM ;
}
* p = ret ;
return 0 ;
}
default :
return - EINVAL ;
}
}
2010-02-12 04:02:14 +03:00
int socket_address_listen (
const SocketAddress * a ,
int backlog ,
SocketAddressBindIPv6Only only ,
const char * bind_to_device ,
2010-07-01 02:29:17 +04:00
bool free_bind ,
2010-02-12 04:02:14 +03:00
mode_t directory_mode ,
mode_t socket_mode ,
Systemd is causing mislabeled devices to be created and then attempting to read them.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 07/28/2010 05:57 AM, Kay Sievers wrote:
> On Wed, Jul 28, 2010 at 11:43, Lennart Poettering
> <lennart@poettering.net> wrote:
>> On Mon, 26.07.10 16:42, Daniel J Walsh (dwalsh@redhat.com) wrote:
>>> tcontext=system_u:object_r:device_t:s0 tclass=chr_file
>>> type=1400 audit(1280174589.476:7): avc: denied { read } for pid=1
>>> comm="systemd" name="autofs" dev=devtmpfs ino=9482
>>> scontext=system_u:system_r:init_t:s0
>>> tcontext=system_u:object_r:device_t:s0 tclass=chr_file
>>> type=1400 audit(1280174589.476:8): avc: denied { read } for pid=1
>>> comm="systemd" name="autofs" dev=devtmpfs ino=9482
>>> scontext=system_u:system_r:init_t:s0
>>> tcontext=system_u:object_r:device_t:s0 tclass=chr_file
>>>
>>> Lennart, we talked about this earlier. I think this is caused by the
>>> modprobe calls to create /dev/autofs. Since udev is not created at the
>>> point that init loads the kernel modules, the devices get created with
>>> the wrong label. Once udev starts the labels get fixed.
>>>
>>> I can allow init_t to read device_t chr_files.
>>
>> Hmm, I think a cleaner fix would be to make systemd relabel this device
>> properly before accessing it? Given that this is only one device this
>> should not be a problem for us to maintain, I think? How would the
>> fixing of the label work? Would we have to spawn restorecon for this, or
>> can we actually do this in C without too much work?
>
> I guess we can just do what udev is doing, and call setfilecon(), with
> a context of an earlier matchpathcon().
>
> Kay
> _______________________________________________
> systemd-devel mailing list
> systemd-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Here is the updated patch with a fix for the labeling of /dev/autofs
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.14 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/
iEYEARECAAYFAkxQMyoACgkQrlYvE4MpobNviACfWgxsjW2xzz1qznFex8RVAQHf
gIEAmwRmRcLvGqYtwQaZ3WKIg8wmrwNk
=pC2e
2010-07-28 17:39:54 +04:00
const char * label ,
2010-02-12 04:02:14 +03:00
int * ret ) {
2010-01-27 06:31:52 +03:00
int r , fd , one ;
2010-01-19 04:56:37 +03:00
assert ( a ) ;
2010-01-24 00:56:47 +03:00
assert ( ret ) ;
2010-01-19 04:56:37 +03:00
2010-01-23 05:35:54 +03:00
if ( ( r = socket_address_verify ( a ) ) < 0 )
2010-01-19 04:56:37 +03:00
return r ;
2010-09-20 23:33:14 +04:00
if ( socket_address_family ( a ) = = AF_INET6 & & ! socket_ipv6_is_supported ( ) )
return - EAFNOSUPPORT ;
Systemd is causing mislabeled devices to be created and then attempting to read them.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 07/28/2010 05:57 AM, Kay Sievers wrote:
> On Wed, Jul 28, 2010 at 11:43, Lennart Poettering
> <lennart@poettering.net> wrote:
>> On Mon, 26.07.10 16:42, Daniel J Walsh (dwalsh@redhat.com) wrote:
>>> tcontext=system_u:object_r:device_t:s0 tclass=chr_file
>>> type=1400 audit(1280174589.476:7): avc: denied { read } for pid=1
>>> comm="systemd" name="autofs" dev=devtmpfs ino=9482
>>> scontext=system_u:system_r:init_t:s0
>>> tcontext=system_u:object_r:device_t:s0 tclass=chr_file
>>> type=1400 audit(1280174589.476:8): avc: denied { read } for pid=1
>>> comm="systemd" name="autofs" dev=devtmpfs ino=9482
>>> scontext=system_u:system_r:init_t:s0
>>> tcontext=system_u:object_r:device_t:s0 tclass=chr_file
>>>
>>> Lennart, we talked about this earlier. I think this is caused by the
>>> modprobe calls to create /dev/autofs. Since udev is not created at the
>>> point that init loads the kernel modules, the devices get created with
>>> the wrong label. Once udev starts the labels get fixed.
>>>
>>> I can allow init_t to read device_t chr_files.
>>
>> Hmm, I think a cleaner fix would be to make systemd relabel this device
>> properly before accessing it? Given that this is only one device this
>> should not be a problem for us to maintain, I think? How would the
>> fixing of the label work? Would we have to spawn restorecon for this, or
>> can we actually do this in C without too much work?
>
> I guess we can just do what udev is doing, and call setfilecon(), with
> a context of an earlier matchpathcon().
>
> Kay
> _______________________________________________
> systemd-devel mailing list
> systemd-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Here is the updated patch with a fix for the labeling of /dev/autofs
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.14 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/
iEYEARECAAYFAkxQMyoACgkQrlYvE4MpobNviACfWgxsjW2xzz1qznFex8RVAQHf
gIEAmwRmRcLvGqYtwQaZ3WKIg8wmrwNk
=pC2e
2010-07-28 17:39:54 +04:00
r = label_socket_set ( label ) ;
if ( r < 0 )
return r ;
2010-07-23 01:01:25 +04:00
fd = socket ( socket_address_family ( a ) , a - > type | SOCK_NONBLOCK | SOCK_CLOEXEC , 0 ) ;
r = fd < 0 ? - errno : 0 ;
2010-07-16 21:42:27 +04:00
Systemd is causing mislabeled devices to be created and then attempting to read them.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 07/28/2010 05:57 AM, Kay Sievers wrote:
> On Wed, Jul 28, 2010 at 11:43, Lennart Poettering
> <lennart@poettering.net> wrote:
>> On Mon, 26.07.10 16:42, Daniel J Walsh (dwalsh@redhat.com) wrote:
>>> tcontext=system_u:object_r:device_t:s0 tclass=chr_file
>>> type=1400 audit(1280174589.476:7): avc: denied { read } for pid=1
>>> comm="systemd" name="autofs" dev=devtmpfs ino=9482
>>> scontext=system_u:system_r:init_t:s0
>>> tcontext=system_u:object_r:device_t:s0 tclass=chr_file
>>> type=1400 audit(1280174589.476:8): avc: denied { read } for pid=1
>>> comm="systemd" name="autofs" dev=devtmpfs ino=9482
>>> scontext=system_u:system_r:init_t:s0
>>> tcontext=system_u:object_r:device_t:s0 tclass=chr_file
>>>
>>> Lennart, we talked about this earlier. I think this is caused by the
>>> modprobe calls to create /dev/autofs. Since udev is not created at the
>>> point that init loads the kernel modules, the devices get created with
>>> the wrong label. Once udev starts the labels get fixed.
>>>
>>> I can allow init_t to read device_t chr_files.
>>
>> Hmm, I think a cleaner fix would be to make systemd relabel this device
>> properly before accessing it? Given that this is only one device this
>> should not be a problem for us to maintain, I think? How would the
>> fixing of the label work? Would we have to spawn restorecon for this, or
>> can we actually do this in C without too much work?
>
> I guess we can just do what udev is doing, and call setfilecon(), with
> a context of an earlier matchpathcon().
>
> Kay
> _______________________________________________
> systemd-devel mailing list
> systemd-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/systemd-devel
Here is the updated patch with a fix for the labeling of /dev/autofs
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v2.0.14 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/
iEYEARECAAYFAkxQMyoACgkQrlYvE4MpobNviACfWgxsjW2xzz1qznFex8RVAQHf
gIEAmwRmRcLvGqYtwQaZ3WKIg8wmrwNk
=pC2e
2010-07-28 17:39:54 +04:00
label_socket_clear ( ) ;
2010-07-23 01:01:25 +04:00
if ( r < 0 )
return r ;
2010-01-19 04:56:37 +03:00
2010-01-23 05:35:54 +03:00
if ( socket_address_family ( a ) = = AF_INET6 & & only ! = SOCKET_ADDRESS_DEFAULT ) {
int flag = only = = SOCKET_ADDRESS_IPV6_ONLY ;
2010-01-27 06:31:52 +03:00
if ( setsockopt ( fd , IPPROTO_IPV6 , IPV6_V6ONLY , & flag , sizeof ( flag ) ) < 0 )
goto fail ;
2010-01-23 05:35:54 +03:00
}
2010-01-27 06:31:52 +03:00
if ( bind_to_device )
if ( setsockopt ( fd , SOL_SOCKET , SO_BINDTODEVICE , bind_to_device , strlen ( bind_to_device ) + 1 ) < 0 )
goto fail ;
2010-07-01 02:29:17 +04:00
if ( free_bind ) {
one = 1 ;
if ( setsockopt ( fd , IPPROTO_IP , IP_FREEBIND , & one , sizeof ( one ) ) < 0 )
log_warning ( " IP_FREEBIND failed: %m " ) ;
}
2010-01-27 06:31:52 +03:00
one = 1 ;
if ( setsockopt ( fd , SOL_SOCKET , SO_REUSEADDR , & one , sizeof ( one ) ) < 0 )
goto fail ;
2010-02-12 04:02:14 +03:00
if ( socket_address_family ( a ) = = AF_UNIX & & a - > sockaddr . un . sun_path [ 0 ] ! = 0 ) {
mode_t old_mask ;
/* Create parents */
mkdir_parents ( a - > sockaddr . un . sun_path , directory_mode ) ;
/* Enforce the right access mode for the socket*/
old_mask = umask ( ~ socket_mode ) ;
/* Include the original umask in our mask */
umask ( ~ socket_mode | old_mask ) ;
r = bind ( fd , & a - > sockaddr . sa , a - > size ) ;
if ( r < 0 & & errno = = EADDRINUSE ) {
/* Unlink and try again */
unlink ( a - > sockaddr . un . sun_path ) ;
r = bind ( fd , & a - > sockaddr . sa , a - > size ) ;
}
umask ( old_mask ) ;
} else
r = bind ( fd , & a - > sockaddr . sa , a - > size ) ;
if ( r < 0 )
2010-01-27 06:31:52 +03:00
goto fail ;
2010-01-19 04:56:37 +03:00
if ( a - > type = = SOCK_STREAM )
2010-01-27 06:31:52 +03:00
if ( listen ( fd , backlog ) < 0 )
goto fail ;
2010-01-19 04:56:37 +03:00
2010-01-24 00:56:47 +03:00
* ret = fd ;
2010-01-19 04:56:37 +03:00
return 0 ;
2010-01-27 06:31:52 +03:00
fail :
r = - errno ;
2010-04-21 05:27:44 +04:00
close_nointr_nofail ( fd ) ;
2010-01-27 06:31:52 +03:00
return r ;
2010-01-19 04:56:37 +03:00
}
2010-04-15 08:19:54 +04:00
bool socket_address_can_accept ( const SocketAddress * a ) {
assert ( a ) ;
return
a - > type = = SOCK_STREAM | |
a - > type = = SOCK_SEQPACKET ;
}
2010-04-21 05:27:44 +04:00
bool socket_address_equal ( const SocketAddress * a , const SocketAddress * b ) {
assert ( a ) ;
assert ( b ) ;
/* Invalid addresses are unequal to all */
if ( socket_address_verify ( a ) < 0 | |
socket_address_verify ( b ) < 0 )
return false ;
if ( a - > type ! = b - > type )
return false ;
if ( a - > size ! = b - > size )
return false ;
if ( socket_address_family ( a ) ! = socket_address_family ( b ) )
return false ;
switch ( socket_address_family ( a ) ) {
case AF_INET :
if ( a - > sockaddr . in4 . sin_addr . s_addr ! = b - > sockaddr . in4 . sin_addr . s_addr )
return false ;
if ( a - > sockaddr . in4 . sin_port ! = b - > sockaddr . in4 . sin_port )
return false ;
break ;
case AF_INET6 :
if ( memcmp ( & a - > sockaddr . in6 . sin6_addr , & b - > sockaddr . in6 . sin6_addr , sizeof ( a - > sockaddr . in6 . sin6_addr ) ) ! = 0 )
return false ;
if ( a - > sockaddr . in6 . sin6_port ! = b - > sockaddr . in6 . sin6_port )
return false ;
break ;
case AF_UNIX :
if ( ( a - > sockaddr . un . sun_path [ 0 ] = = 0 ) ! = ( b - > sockaddr . un . sun_path [ 0 ] = = 0 ) )
return false ;
if ( a - > sockaddr . un . sun_path [ 0 ] ) {
if ( strncmp ( a - > sockaddr . un . sun_path , b - > sockaddr . un . sun_path , sizeof ( a - > sockaddr . un . sun_path ) ) ! = 0 )
return false ;
} else {
2010-07-11 04:23:11 +04:00
if ( memcmp ( a - > sockaddr . un . sun_path , b - > sockaddr . un . sun_path , a - > size ) ! = 0 )
2010-04-21 05:27:44 +04:00
return false ;
}
break ;
default :
/* Cannot compare, so we assume the addresses are different */
return false ;
}
return true ;
}
2010-06-05 02:52:30 +04:00
bool socket_address_is ( const SocketAddress * a , const char * s , int type ) {
2010-04-21 05:27:44 +04:00
struct SocketAddress b ;
assert ( a ) ;
assert ( s ) ;
if ( socket_address_parse ( & b , s ) < 0 )
return false ;
2010-06-05 02:52:30 +04:00
b . type = type ;
2010-04-21 05:27:44 +04:00
return socket_address_equal ( a , & b ) ;
2010-05-13 05:07:16 +04:00
}
bool socket_address_needs_mount ( const SocketAddress * a , const char * prefix ) {
assert ( a ) ;
if ( socket_address_family ( a ) ! = AF_UNIX )
return false ;
if ( a - > sockaddr . un . sun_path [ 0 ] = = 0 )
return false ;
2010-04-21 05:27:44 +04:00
2010-05-13 05:07:16 +04:00
return path_startswith ( a - > sockaddr . un . sun_path , prefix ) ;
2010-04-21 05:27:44 +04:00
}
2010-05-22 01:41:25 +04:00
2010-09-20 23:33:14 +04:00
bool socket_ipv6_is_supported ( void ) {
2010-10-27 21:40:31 +04:00
char * l = 0 ;
bool enabled ;
if ( access ( " /sys/module/ipv6 " , F_OK ) ! = 0 )
return 0 ;
/* If we can't check "disable" parameter, assume enabled */
if ( read_one_line_file ( " /sys/module/ipv6/parameters/disable " , & l ) < 0 )
return 1 ;
/* If module was loaded with disable=1 no IPv6 available */
enabled = l [ 0 ] = = ' 0 ' ;
free ( l ) ;
return enabled ;
2010-09-20 23:33:14 +04:00
}
2010-05-22 01:41:25 +04:00
static const char * const socket_address_bind_ipv6_only_table [ _SOCKET_ADDRESS_BIND_IPV6_ONLY_MAX ] = {
[ SOCKET_ADDRESS_DEFAULT ] = " default " ,
[ SOCKET_ADDRESS_BOTH ] = " both " ,
[ SOCKET_ADDRESS_IPV6_ONLY ] = " ipv6-only "
} ;
DEFINE_STRING_TABLE_LOOKUP ( socket_address_bind_ipv6_only , SocketAddressBindIPv6Only ) ;