3636#include "sysctl_probe.h"
3737
3838#if defined(OS_FREEBSD )
39+ #include <ctype.h>
3940#include <stdio.h>
4041#include <stdlib.h>
4142#include <limits.h>
4546
4647#define SYSCTL_CMD "/sbin/sysctl -ae"
4748#elif defined(OS_APPLE )
49+ #include <ctype.h>
4850#include <stdio.h>
4951#include <stdlib.h>
5052#include <limits.h>
@@ -317,6 +319,85 @@ int sysctl_probe_main(probe_ctx *ctx, void *probe_arg)
317319
318320#elif defined(OS_FREEBSD ) || defined(OS_APPLE )
319321
322+ static int sysctl_name_char (int ch )
323+ {
324+ return isalnum ((unsigned char ) ch ) || ch == '.' || ch == '_' ||
325+ ch == '%' || ch == '-' ;
326+ }
327+
328+ static int sysctl_parse_line (char * line , char * * mib , char * * sysval )
329+ {
330+ char * sep ;
331+ size_t i , mib_len ;
332+
333+ sep = strchr (line , '=' );
334+ if (sep == NULL )
335+ return 0 ;
336+
337+ mib_len = (size_t )(sep - line );
338+ if (mib_len == 0 || !isalpha ((unsigned char ) line [0 ]))
339+ return 0 ;
340+
341+ for (i = 0 ; i < mib_len ; ++ i ) {
342+ if (!sysctl_name_char (line [i ]))
343+ return 0 ;
344+ }
345+
346+ * sep = '\0' ;
347+ * mib = line ;
348+ * sysval = sep + 1 ;
349+ return 1 ;
350+ }
351+
352+ static int sysctl_append_value (char * * value , size_t * value_len , const char * line )
353+ {
354+ size_t line_len , new_len ;
355+ char * new_value ;
356+
357+ line_len = strlen (line );
358+ new_len = * value_len + line_len + (* value_len > 0 ? 1 : 0 ) + 1 ;
359+ new_value = realloc (* value , new_len );
360+ if (new_value == NULL )
361+ return -1 ;
362+
363+ * value = new_value ;
364+ if (* value_len > 0 )
365+ new_value [(* value_len )++ ] = '\n' ;
366+
367+ memcpy (new_value + * value_len , line , line_len + 1 );
368+ * value_len += line_len ;
369+ return 0 ;
370+ }
371+
372+ static int sysctl_collect_item (probe_ctx * ctx , SEXP_t * name_entity ,
373+ const char * mib , const char * sysval )
374+ {
375+ SEXP_t * item , * se_mib ;
376+
377+ se_mib = SEXP_string_new (mib , strlen (mib ));
378+ if (!se_mib ) {
379+ dE ("Failed to allocate new SEXP_string for se_mib" );
380+ return PROBE_ENOENT ;
381+ }
382+
383+ if (probe_entobj_cmp (name_entity , se_mib ) == OVAL_RESULT_TRUE ) {
384+ item = probe_item_create (OVAL_UNIX_SYSCTL , NULL ,
385+ "name" , OVAL_DATATYPE_SEXP , se_mib ,
386+ "value" , OVAL_DATATYPE_STRING , sysval ,
387+ NULL );
388+ if (!item ) {
389+ dE ("probe_item_create() returned a null item" );
390+ SEXP_free (se_mib );
391+ return PROBE_ENOENT ;
392+ }
393+
394+ probe_item_collect (ctx , item );
395+ }
396+
397+ SEXP_free (se_mib );
398+ return 0 ;
399+ }
400+
320401int sysctl_probe_offline_mode_supported (void )
321402{
322403 return PROBE_OFFLINE_NONE ;
@@ -326,11 +407,11 @@ int sysctl_probe_main(probe_ctx *ctx, void *probe_arg)
326407{
327408 FILE * fp ;
328409 char output [LINE_MAX ];
329- const char * SEP = "=" ;
330- char * mib ;
331- char * sysval ;
332- SEXP_t * se_mib ;
333410 SEXP_t * name_entity , * probe_in ;
411+ int ret = 0 ;
412+ char * current_mib = NULL ;
413+ char * current_value = NULL ;
414+ size_t current_value_len = 0 ;
334415
335416 probe_in = probe_ctx_getobject (ctx );
336417 name_entity = probe_obj_getent (probe_in , "name" , 1 );
@@ -354,50 +435,59 @@ int sysctl_probe_main(probe_ctx *ctx, void *probe_arg)
354435 }
355436
356437 while (fgets (output , sizeof (output ), fp )) {
357- char * strp ;
358- mib = strtok_r (output , SEP , & strp );
359- sysval = strtok_r (NULL , SEP , & strp );
360-
361- if (!mib )
362- continue ;
363-
364- if (!sysval )
365- continue ;
366-
367- se_mib = SEXP_string_new (mib , strlen (mib ));
368-
369- if (!se_mib ) {
370- dE ("Failed to allocate new SEXP_string for se_mib" );
371- pclose (fp );
372- return (PROBE_ENOENT );
373- }
374-
375- /* Remove newline */
376- sysval [strlen (sysval )- 1 ] = '\0' ;
377-
378- if (probe_entobj_cmp (name_entity , se_mib ) == OVAL_RESULT_TRUE ) {
379- SEXP_t * item ;
380-
381- item = probe_item_create (OVAL_UNIX_SYSCTL , NULL ,
382- "name" , OVAL_DATATYPE_SEXP , se_mib ,
383- "value" , OVAL_DATATYPE_STRING , sysval ,
384- NULL );
385-
386- if (!item ) {
387- dE ("probe_item_create() returned a null item" );
388- pclose (fp );
389- SEXP_free (se_mib );
390- return (PROBE_ENOENT );
391- }
392-
393- probe_item_collect (ctx , item );
394- }
395-
396- SEXP_free (se_mib );
438+ char * mib , * sysval , * newline ;
439+
440+ newline = strchr (output , '\n' );
441+ if (newline != NULL )
442+ * newline = '\0' ;
443+
444+ if (sysctl_parse_line (output , & mib , & sysval )) {
445+ if (current_mib != NULL ) {
446+ ret = sysctl_collect_item (ctx , name_entity , current_mib ,
447+ current_value != NULL ? current_value : "" );
448+ if (ret != 0 )
449+ goto cleanup ;
450+ }
451+
452+ free (current_mib );
453+ free (current_value );
454+ current_mib = strdup (mib );
455+ current_value = NULL ;
456+ current_value_len = 0 ;
457+ if (current_mib == NULL ) {
458+ dE ("Failed to allocate new sysctl name buffer" );
459+ ret = PROBE_ENOENT ;
460+ goto cleanup ;
461+ }
462+
463+ if (sysctl_append_value (& current_value , & current_value_len , sysval ) != 0 ) {
464+ dE ("Failed to append sysctl value" );
465+ ret = PROBE_ENOENT ;
466+ goto cleanup ;
467+ }
468+
469+ continue ;
470+ }
471+
472+ if (current_mib == NULL )
473+ continue ;
474+
475+ if (sysctl_append_value (& current_value , & current_value_len , output ) != 0 ) {
476+ dE ("Failed to append sysctl continuation value" );
477+ ret = PROBE_ENOENT ;
478+ goto cleanup ;
479+ }
397480 }
398481
482+ if (current_mib != NULL )
483+ ret = sysctl_collect_item (ctx , name_entity , current_mib ,
484+ current_value != NULL ? current_value : "" );
485+
486+ cleanup :
487+ free (current_mib );
488+ free (current_value );
399489 pclose (fp );
400- return ( 0 ) ;
490+ return ret ;
401491}
402492
403493#else
0 commit comments