2013-10-28 23:59:56 +04:00
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd .
Copyright ( C ) 2013 Tom Gundersen < teg @ jklm . no >
systemd 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 .
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
Lesser General Public License for more details .
You should have received a copy of the GNU Lesser General Public License
along with systemd ; If not , see < http : //www.gnu.org/licenses/>.
* * */
# include <netinet/ether.h>
2013-11-25 04:33:04 +04:00
# include <linux/if.h>
2013-11-10 01:19:42 +04:00
# include <arpa/inet.h>
2013-10-28 23:59:56 +04:00
2013-11-02 05:13:48 +04:00
# include "net-util.h"
# include "log.h"
2013-10-28 23:59:56 +04:00
# include "utf8.h"
2013-10-29 18:59:45 +04:00
# include "util.h"
2013-10-28 23:59:56 +04:00
# include "conf-parser.h"
2014-02-20 22:39:49 +04:00
# include "condition.h"
2013-10-28 23:59:56 +04:00
2013-11-02 05:13:48 +04:00
bool net_match_config ( const struct ether_addr * match_mac ,
const char * match_path ,
const char * match_driver ,
const char * match_type ,
const char * match_name ,
2014-02-20 22:39:49 +04:00
Condition * match_host ,
Condition * match_virt ,
Condition * match_kernel ,
2013-11-05 04:35:26 +04:00
const char * dev_mac ,
const char * dev_path ,
const char * dev_driver ,
const char * dev_type ,
const char * dev_name ) {
2013-11-02 05:13:48 +04:00
2014-02-20 22:39:49 +04:00
if ( match_host & & ! condition_test_host ( match_host ) )
return 0 ;
if ( match_virt & & ! condition_test_virtualization ( match_virt ) )
return 0 ;
if ( match_kernel & & ! condition_test_kernel_command_line ( match_kernel ) )
return 0 ;
2014-01-02 18:30:46 +04:00
if ( match_mac & & ( ! dev_mac | | memcmp ( match_mac , ether_aton ( dev_mac ) , ETH_ALEN ) ) )
return 0 ;
2013-11-02 05:13:48 +04:00
2014-01-02 18:30:46 +04:00
if ( match_path & & ! streq_ptr ( match_path , dev_path ) )
return 0 ;
2013-11-02 05:13:48 +04:00
2014-01-02 18:30:46 +04:00
if ( match_driver & & ! streq_ptr ( match_driver , dev_driver ) )
return 0 ;
2013-10-28 23:59:56 +04:00
2014-01-04 07:22:06 +04:00
if ( match_type & & ! streq_ptr ( match_type , dev_type ) )
2014-01-02 18:30:46 +04:00
return 0 ;
2013-10-28 23:59:56 +04:00
2014-01-02 18:30:46 +04:00
if ( match_name & & ! streq_ptr ( match_name , dev_name ) )
return 0 ;
2013-10-28 23:59:56 +04:00
2013-11-02 05:13:48 +04:00
return 1 ;
}
2013-10-28 23:59:56 +04:00
2014-01-29 02:23:31 +04:00
unsigned net_netmask_to_prefixlen ( const struct in_addr * addr ) {
assert ( addr ) ;
2014-01-30 20:23:34 +04:00
return 32 - u32ctz ( be32toh ( addr - > s_addr ) ) ;
2014-01-29 02:23:31 +04:00
}
2014-02-20 22:39:49 +04:00
int config_parse_net_condition ( const char * unit ,
const char * filename ,
unsigned line ,
const char * section ,
unsigned section_line ,
const char * lvalue ,
int ltype ,
const char * rvalue ,
void * data ,
void * userdata ) {
ConditionType cond = ltype ;
Condition * * ret = data ;
bool negate ;
Condition * c ;
_cleanup_free_ char * s = NULL ;
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
negate = rvalue [ 0 ] = = ' ! ' ;
if ( negate )
rvalue + + ;
s = strdup ( rvalue ) ;
if ( ! s )
return log_oom ( ) ;
c = condition_new ( cond , s , false , negate ) ;
if ( ! c )
return log_oom ( ) ;
if ( * ret )
condition_free ( * ret ) ;
* ret = c ;
return 0 ;
}
2013-10-28 23:59:56 +04:00
int config_parse_ifname ( const char * unit ,
const char * filename ,
unsigned line ,
const char * section ,
2013-11-19 19:17:55 +04:00
unsigned section_line ,
2013-10-28 23:59:56 +04:00
const char * lvalue ,
int ltype ,
const char * rvalue ,
void * data ,
void * userdata ) {
char * * s = data ;
char * n ;
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
n = strdup ( rvalue ) ;
if ( ! n )
return log_oom ( ) ;
if ( ! ascii_is_valid ( n ) | | strlen ( n ) > = IFNAMSIZ ) {
log_syntax ( unit , LOG_ERR , filename , line , EINVAL ,
" Interface name is not ASCII clean or is too long, ignoring assignment: %s " , rvalue ) ;
free ( n ) ;
return 0 ;
}
free ( * s ) ;
if ( * n )
* s = n ;
else {
free ( n ) ;
* s = NULL ;
}
return 0 ;
}
2013-11-25 04:33:04 +04:00
int config_parse_ifalias ( const char * unit ,
const char * filename ,
unsigned line ,
const char * section ,
2013-11-19 19:17:55 +04:00
unsigned section_line ,
2013-11-25 04:33:04 +04:00
const char * lvalue ,
int ltype ,
const char * rvalue ,
void * data ,
void * userdata ) {
char * * s = data ;
char * n ;
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
n = strdup ( rvalue ) ;
if ( ! n )
return log_oom ( ) ;
if ( ! ascii_is_valid ( n ) | | strlen ( n ) > = IFALIASZ ) {
log_syntax ( unit , LOG_ERR , filename , line , EINVAL ,
" Interface alias is not ASCII clean or is too long, ignoring assignment: %s " , rvalue ) ;
free ( n ) ;
return 0 ;
}
free ( * s ) ;
if ( * n )
* s = n ;
else {
free ( n ) ;
* s = NULL ;
}
return 0 ;
}
2013-10-28 23:59:56 +04:00
int config_parse_hwaddr ( const char * unit ,
const char * filename ,
unsigned line ,
const char * section ,
2013-11-19 19:17:55 +04:00
unsigned section_line ,
2013-10-28 23:59:56 +04:00
const char * lvalue ,
int ltype ,
const char * rvalue ,
void * data ,
void * userdata ) {
struct ether_addr * * hwaddr = data ;
struct ether_addr * n ;
int r ;
assert ( filename ) ;
assert ( lvalue ) ;
assert ( rvalue ) ;
assert ( data ) ;
2013-10-29 18:59:45 +04:00
n = new0 ( struct ether_addr , 1 ) ;
2013-10-28 23:59:56 +04:00
if ( ! n )
return log_oom ( ) ;
r = sscanf ( rvalue , " %02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx " ,
& n - > ether_addr_octet [ 0 ] ,
& n - > ether_addr_octet [ 1 ] ,
& n - > ether_addr_octet [ 2 ] ,
& n - > ether_addr_octet [ 3 ] ,
& n - > ether_addr_octet [ 4 ] ,
& n - > ether_addr_octet [ 5 ] ) ;
if ( r ! = 6 ) {
log_syntax ( unit , LOG_ERR , filename , line , EINVAL ,
" Not a valid MAC address, ignoring assignment: %s " , rvalue ) ;
free ( n ) ;
return 0 ;
}
free ( * hwaddr ) ;
* hwaddr = n ;
return 0 ;
}
2013-11-10 01:19:42 +04:00
int net_parse_inaddr ( const char * address , unsigned char * family , void * dst ) {
int r ;
assert ( address ) ;
assert ( family ) ;
assert ( dst ) ;
/* IPv4 */
r = inet_pton ( AF_INET , address , dst ) ;
2014-01-28 23:00:47 +04:00
if ( r > 0 ) {
/* succsefully parsed IPv4 address */
if ( * family = = AF_UNSPEC )
* family = AF_INET ;
else if ( * family ! = AF_INET )
return - EINVAL ;
} else if ( r < 0 )
2013-11-10 01:19:42 +04:00
return - errno ;
else {
/* not an IPv4 address, so let's try IPv6 */
r = inet_pton ( AF_INET6 , address , dst ) ;
2014-01-28 23:00:47 +04:00
if ( r > 0 ) {
/* successfully parsed IPv6 address */
if ( * family = = AF_UNSPEC )
* family = AF_INET6 ;
else if ( * family ! = AF_INET6 )
return - EINVAL ;
} else if ( r < 0 )
2013-11-10 01:19:42 +04:00
return - errno ;
else
return - EINVAL ;
}
return 0 ;
}