Mahamutha M
Mahamutha M

Reputation: 1287

C - How to convert the char to string to pass strcpy?

I need to fetch the active network interface of a device in c language using the system command and the system response has to be passed to get the mac address of the device and for the same, below is the sample which I have been using,

#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);
}
}

How to address this?

I can able to get the active interface as,

interface :: wlp1s0

Whereas, the same interface is passed to strcpy(s.ifr_name, interface) and for the same unable to get the address. Instead of strcpy(s.ifr_name, interface), if i use it as strcpy(s.ifr_name, "wlp1s0), the same returns the mac address without any issue.

Upvotes: 0

Views: 224

Answers (1)

m0hithreddy
m0hithreddy

Reputation: 1839

Yes, you can parse the output of ip addr show, but wait, what if the implementer changes the way ip addr show produces the output! It's output has not been standardized. Did you consider using getifaddrs()? The below code is from their man page:

#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);
}

Upvotes: 3

Related Questions