2019-07-31 10:40:39 +01:00
/*
* libvirt_nss_macs . c : Name Service Switch plugin MAC file parser
*
* Copyright ( C ) 2019 Red Hat , Inc .
*
* This library 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 .
*
* This library 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 this library . If not , see
* < http : //www.gnu.org/licenses/>.
*/
# include <config.h>
# include <unistd.h>
# include <string.h>
# include <stdlib.h>
# include <fcntl.h>
2024-08-14 17:50:38 +02:00
# include <json.h>
2019-07-31 10:40:39 +01:00
# include "libvirt_nss_macs.h"
2019-07-31 10:40:39 +01:00
# include "libvirt_nss.h"
2019-07-31 10:40:39 +01:00
2024-08-14 17:50:38 +02:00
/**
* findMACsFromJSON
*
* @ jobj : JSON object containing the leases
* @ name : requested hostname
* @ macs : returned array of MAC addresses leased to the hostname
* @ nmacs : size of the returned array
*/
2019-07-31 10:40:39 +01:00
static int
2024-08-14 17:50:38 +02:00
findMACsFromJSON ( json_object * jobj ,
const char * name ,
char * * * macs ,
size_t * nmacs )
2019-07-31 10:40:39 +01:00
{
2024-08-14 17:50:38 +02:00
size_t i ;
int len ;
2019-07-31 10:40:39 +01:00
2024-08-14 17:50:38 +02:00
if ( ! json_object_is_type ( jobj , json_type_array ) ) {
ERROR ( " parsed JSON does not contain the leases array " ) ;
return - 1 ;
2019-07-31 10:40:39 +01:00
}
2024-08-14 17:50:38 +02:00
len = json_object_array_length ( jobj ) ;
DEBUG ( " Found an array of length: %zu " , len ) ;
for ( i = 0 ; i < len ; i + + ) {
json_object * entry = NULL ;
json_object * domain = NULL ;
const char * domainName ;
char * * tmpMacs = NULL ;
size_t newmacs = 0 ;
json_object * macsArray = NULL ;
size_t j ;
2019-07-31 10:40:39 +01:00
2024-08-14 17:50:38 +02:00
entry = json_object_array_get_idx ( jobj , i ) ;
if ( ! entry )
continue ;
2019-07-31 10:40:39 +01:00
2024-08-14 17:50:38 +02:00
DEBUG ( " Processing item %zu " , i ) ;
2019-07-31 10:40:39 +01:00
2024-08-14 17:50:38 +02:00
domain = json_object_object_get ( entry , " domain " ) ;
if ( ! domain )
continue ;
2019-07-31 10:40:39 +01:00
2024-08-14 17:50:38 +02:00
domainName = json_object_get_string ( domain ) ;
if ( ! domainName )
continue ;
2019-07-31 10:40:39 +01:00
2024-08-14 17:50:38 +02:00
DEBUG ( " Processing domain %s " , domainName ) ;
2019-07-31 10:40:39 +01:00
2024-08-14 17:50:38 +02:00
if ( strcasecmp ( domainName , name ) )
continue ;
2019-07-31 10:40:39 +01:00
2024-08-14 17:50:38 +02:00
macsArray = json_object_object_get ( entry , " macs " ) ;
if ( ! macsArray )
continue ;
2019-07-31 10:40:39 +01:00
2024-08-14 17:50:38 +02:00
newmacs = json_object_array_length ( macsArray ) ;
DEBUG ( " Found %zu MAC addresses " , newmacs ) ;
2019-07-31 10:40:39 +01:00
2024-08-14 17:50:38 +02:00
tmpMacs = realloc ( * macs , sizeof ( char * ) * ( * nmacs + newmacs + 1 ) ) ;
if ( ! tmpMacs )
return - 1 ;
2019-07-31 10:40:39 +01:00
2024-08-14 17:50:38 +02:00
* macs = tmpMacs ;
2019-07-31 10:40:39 +01:00
2024-08-14 17:50:38 +02:00
for ( j = 0 ; j < newmacs ; j + + ) {
json_object * macobj = NULL ;
char * macstr ;
2019-07-31 10:40:39 +01:00
2024-08-14 17:50:38 +02:00
macobj = json_object_array_get_idx ( macsArray , j ) ;
macstr = strdup ( json_object_get_string ( macobj ) ) ;
if ( ! macstr )
return - 1 ;
( * macs ) [ ( * nmacs ) + + ] = macstr ;
}
2019-07-31 10:40:39 +01:00
}
2024-08-14 17:50:38 +02:00
return 0 ;
2019-07-31 10:40:39 +01:00
}
int
findMACs ( const char * file ,
const char * name ,
char * * * macs ,
size_t * nmacs )
{
int fd = - 1 ;
int ret = - 1 ;
char line [ 1024 ] ;
2024-08-14 17:50:38 +02:00
json_object * jobj = NULL ;
json_tokener * tok = NULL ;
enum json_tokener_error jerr ;
int jsonflags = JSON_TOKENER_STRICT | JSON_TOKENER_VALIDATE_UTF8 ;
ssize_t nreadTotal = 0 ;
2019-07-31 10:40:39 +01:00
int rv ;
2024-08-14 17:50:38 +02:00
size_t i ;
2019-07-31 10:40:39 +01:00
if ( ( fd = open ( file , O_RDONLY ) ) < 0 ) {
ERROR ( " Cannot open %s " , file ) ;
goto cleanup ;
}
2024-08-14 17:50:38 +02:00
tok = json_tokener_new ( ) ;
2024-11-04 08:24:39 +01:00
if ( ! tok ) {
ERROR ( " failed to create JSON tokener " ) ;
goto cleanup ;
}
2024-08-14 17:50:38 +02:00
json_tokener_set_flags ( tok , jsonflags ) ;
2019-07-31 10:40:39 +01:00
2024-08-14 17:50:38 +02:00
do {
2019-07-31 10:40:39 +01:00
rv = read ( fd , line , sizeof ( line ) ) ;
if ( rv < 0 )
goto cleanup ;
if ( rv = = 0 )
break ;
2024-08-14 17:50:38 +02:00
nreadTotal + = rv ;
2019-07-31 10:40:39 +01:00
2024-08-14 17:50:38 +02:00
jobj = json_tokener_parse_ex ( tok , line , rv ) ;
jerr = json_tokener_get_error ( tok ) ;
} while ( jerr = = json_tokener_continue ) ;
if ( jerr = = json_tokener_continue ) {
ERROR ( " Cannot parse %s: incomplete json found " , file ) ;
goto cleanup ;
2019-07-31 10:40:39 +01:00
}
2024-08-14 17:50:38 +02:00
if ( nreadTotal > 0 & & jerr ! = json_tokener_success ) {
ERROR ( " Cannot parse %s: %s " , file , json_tokener_error_desc ( jerr ) ) ;
2019-07-31 10:40:39 +01:00
goto cleanup ;
}
2024-08-14 17:50:38 +02:00
ret = findMACsFromJSON ( jobj , name , macs , nmacs ) ;
2019-07-31 10:40:39 +01:00
cleanup :
2024-08-14 17:50:38 +02:00
json_object_put ( jobj ) ;
2024-11-04 08:24:39 +01:00
if ( tok )
json_tokener_free ( tok ) ;
2019-07-31 10:40:39 +01:00
if ( ret ! = 0 ) {
for ( i = 0 ; i < * nmacs ; i + + ) {
char * mac = ( * macs ) [ i ] ;
free ( mac ) ;
}
free ( * macs ) ;
* macs = NULL ;
* nmacs = 0 ;
}
if ( fd ! = - 1 )
close ( fd ) ;
return ret ;
}