Reputation: 1287
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
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