24
24
25
25
#include <sys/poll.h>
26
26
#include <sys/utsname.h>
27
+ #include <stdbool.h>
27
28
#include <stdio.h>
28
29
#include <stdlib.h>
29
30
#include <unistd.h>
@@ -677,6 +678,88 @@ static void kvp_process_ipconfig_file(char *cmd,
677
678
pclose (file );
678
679
}
679
680
681
+ static bool kvp_verify_ip_address (const void * address_string )
682
+ {
683
+ char verify_buf [sizeof (struct in6_addr )];
684
+
685
+ if (inet_pton (AF_INET , address_string , verify_buf ) == 1 )
686
+ return true;
687
+ if (inet_pton (AF_INET6 , address_string , verify_buf ) == 1 )
688
+ return true;
689
+ return false;
690
+ }
691
+
692
+ static void kvp_extract_routes (const char * line , void * * output , size_t * remaining )
693
+ {
694
+ static const char needle [] = "via " ;
695
+ const char * match , * haystack = line ;
696
+
697
+ while ((match = strstr (haystack , needle ))) {
698
+ const char * address , * next_char ;
699
+
700
+ /* Address starts after needle. */
701
+ address = match + strlen (needle );
702
+
703
+ /* The char following address is a space or end of line. */
704
+ next_char = strpbrk (address , " \t\\" );
705
+ if (!next_char )
706
+ next_char = address + strlen (address ) + 1 ;
707
+
708
+ /* Enough room for address and semicolon. */
709
+ if (* remaining >= (next_char - address ) + 1 ) {
710
+ memcpy (* output , address , next_char - address );
711
+ /* Terminate string for verification. */
712
+ memcpy (* output + (next_char - address ), "" , 1 );
713
+ if (kvp_verify_ip_address (* output )) {
714
+ /* Advance output buffer. */
715
+ * output += next_char - address ;
716
+ * remaining -= next_char - address ;
717
+
718
+ /* Each address needs a trailing semicolon. */
719
+ memcpy (* output , ";" , 1 );
720
+ * output += 1 ;
721
+ * remaining -= 1 ;
722
+ }
723
+ }
724
+ haystack = next_char ;
725
+ }
726
+ }
727
+
728
+ static void kvp_get_gateway (void * buffer , size_t buffer_len )
729
+ {
730
+ static const char needle [] = "default " ;
731
+ FILE * f ;
732
+ void * output = buffer ;
733
+ char * line = NULL ;
734
+ size_t alloc_size = 0 , remaining = buffer_len - 1 ;
735
+ ssize_t num_chars ;
736
+
737
+ /* Show route information in a single line, for each address family */
738
+ f = popen ("ip --oneline -4 route show;ip --oneline -6 route show" , "r" );
739
+ if (!f ) {
740
+ /* Convert buffer into C-String. */
741
+ memcpy (output , "" , 1 );
742
+ return ;
743
+ }
744
+ while ((num_chars = getline (& line , & alloc_size , f )) > 0 ) {
745
+ /* Skip short lines. */
746
+ if (num_chars <= strlen (needle ))
747
+ continue ;
748
+ /* Skip lines without default route. */
749
+ if (memcmp (line , needle , strlen (needle )))
750
+ continue ;
751
+ /* Remove trailing newline to simplify further parsing. */
752
+ if (line [num_chars - 1 ] == '\n' )
753
+ line [num_chars - 1 ] = '\0' ;
754
+ /* Search routes after match. */
755
+ kvp_extract_routes (line + strlen (needle ), & output , & remaining );
756
+ }
757
+ /* Convert buffer into C-String. */
758
+ memcpy (output , "" , 1 );
759
+ free (line );
760
+ pclose (f );
761
+ }
762
+
680
763
static void kvp_get_ipconfig_info (char * if_name ,
681
764
struct hv_kvp_ipaddr_value * buffer )
682
765
{
@@ -685,30 +768,7 @@ static void kvp_get_ipconfig_info(char *if_name,
685
768
char * p ;
686
769
FILE * file ;
687
770
688
- /*
689
- * Get the address of default gateway (ipv4).
690
- */
691
- sprintf (cmd , "%s %s" , "ip route show dev" , if_name );
692
- strcat (cmd , " | awk '/default/ {print $3 }'" );
693
-
694
- /*
695
- * Execute the command to gather gateway info.
696
- */
697
- kvp_process_ipconfig_file (cmd , (char * )buffer -> gate_way ,
698
- (MAX_GATEWAY_SIZE * 2 ), INET_ADDRSTRLEN , 0 );
699
-
700
- /*
701
- * Get the address of default gateway (ipv6).
702
- */
703
- sprintf (cmd , "%s %s" , "ip -f inet6 route show dev" , if_name );
704
- strcat (cmd , " | awk '/default/ {print $3 }'" );
705
-
706
- /*
707
- * Execute the command to gather gateway info (ipv6).
708
- */
709
- kvp_process_ipconfig_file (cmd , (char * )buffer -> gate_way ,
710
- (MAX_GATEWAY_SIZE * 2 ), INET6_ADDRSTRLEN , 1 );
711
-
771
+ kvp_get_gateway (buffer -> gate_way , sizeof (buffer -> gate_way ));
712
772
713
773
/*
714
774
* Gather the DNS state.
0 commit comments