2424
2525#include <sys/poll.h>
2626#include <sys/utsname.h>
27+ #include <stdbool.h>
2728#include <stdio.h>
2829#include <stdlib.h>
2930#include <unistd.h>
@@ -677,6 +678,88 @@ static void kvp_process_ipconfig_file(char *cmd,
677678 pclose (file );
678679}
679680
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+
680763static void kvp_get_ipconfig_info (char * if_name ,
681764 struct hv_kvp_ipaddr_value * buffer )
682765{
@@ -685,30 +768,7 @@ static void kvp_get_ipconfig_info(char *if_name,
685768 char * p ;
686769 FILE * file ;
687770
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 ));
712772
713773 /*
714774 * Gather the DNS state.
0 commit comments