C - Как преобразовать символ в строку для передачи strcpy? - PullRequest
0 голосов
/ 19 июня 2020

Мне нужно получить активный сетевой интерфейс устройства на языке c с помощью системной команды, и должен быть передан ответ системы, чтобы получить адрес ma c устройства, и для того же самого ниже приведен образец, который я использовал,

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/if.h>
#include <netdb.h>

char interface[100];
char reader_mac[13] = {00};

int main()
{
  FILE *f = popen("ip addr show | awk '/inet.*brd/{print $NF}'", "r");
  while (fgets(interface, 100, f) != NULL) {
  }
  printf( "interface :: %s\n", interface );
  pclose(f);  

  struct ifreq s;    
  int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);  
  // strcpy(s.ifr_name, "eth0");
  strcpy(s.ifr_name, interface);
  if (0 == ioctl(fd, SIOCGIFHWADDR, &s)) {
  int i;

  for (i = 0; i < 6; ++i){
    unsigned char data  =  s.ifr_addr.sa_data[i];
    // printf("ddd:::%02x\n", data );
    sprintf(reader_mac+(i*2), "%02x", data);
  }
  reader_mac[12] = '\0';
  printf("reader_mac ::: %s\n",reader_mac);
}
}

Как решить эту проблему?

Я могу получить активный интерфейс как,

interface :: wlp1s0

Тогда как то же самое интерфейс передается в strcpy (s.ifr_name, interface) и для того же не может получить адрес. Вместо strcpy (s.ifr_name, interface), если я использую его как strcpy (s.ifr_name, "wlp1s0), он без проблем возвращает адрес ma c.

1 Ответ

2 голосов
/ 19 июня 2020

Да, вы можете анализировать вывод ip addr show, но подождите, что, если разработчик изменит способ, которым ip addr show производит вывод! Его вывод не стандартизирован. Вы рассматривали возможность использования getifaddrs()? Приведенный ниже код взят из их справочной страницы:

#define _GNU_SOURCE     /* To get defns of NI_MAXSERV and NI_MAXHOST */
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netdb.h>
#include <ifaddrs.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/if_link.h>

int main(int argc, char *argv[])
{
   struct ifaddrs *ifaddr, *ifa;
   int family, s;
   char host[NI_MAXHOST];

   if (getifaddrs(&ifaddr) == -1) {
       perror("getifaddrs");
       exit(EXIT_FAILURE);
   }

   /* Walk through linked list, maintaining head pointer so we
      can free list later */

   for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
       if (ifa->ifa_addr == NULL)
           continue;

       family = ifa->ifa_addr->sa_family;

       /* Display interface name and family (including symbolic
          form of the latter for the common families) */

       printf("%-8s %s (%d)\n",
              ifa->ifa_name,
              (family == AF_PACKET) ? "AF_PACKET" :
              (family == AF_INET) ? "AF_INET" :
              (family == AF_INET6) ? "AF_INET6" : "???",
              family);

       /* For an AF_INET* interface address, display the address */

       if (family == AF_INET || family == AF_INET6) {
           s = getnameinfo(ifa->ifa_addr,
                   (family == AF_INET) ? sizeof(struct sockaddr_in) :
                                         sizeof(struct sockaddr_in6),
                   host, NI_MAXHOST,
                   NULL, 0, NI_NUMERICHOST);
           if (s != 0) {
               printf("getnameinfo() failed: %s\n", gai_strerror(s));
               exit(EXIT_FAILURE);
           }

           printf("\t\taddress: <%s>\n", host);

       } else if (family == AF_PACKET && ifa->ifa_data != NULL) {
           struct rtnl_link_stats *stats = ifa->ifa_data;

           printf("\t\ttx_packets = %10u; rx_packets = %10u\n"
                  "\t\ttx_bytes   = %10u; rx_bytes   = %10u\n",
                  stats->tx_packets, stats->rx_packets,
                  stats->tx_bytes, stats->rx_bytes);
       }
   }

   freeifaddrs(ifaddr);
   exit(EXIT_SUCCESS);
}
...