black black - 2 months ago 17
C Question

Issues printing a MAC address

A MAC address is parsed into an array of bytes (

macaddr
). The bytes are
printed with
printf()
one after another. The bytes are supposed to look as
pairs of hexadecimal characters. But some of them are padded with
f

characters.

For example, for
macaddr[3]
it prints
'ffffffcc'
rather than
'cc'
, i.e.
4 bytes instead of single byte. The rest of the array items are printed
correctly (
macaddr[0]
=
00
,
macaddr[1]
=
AA
,
macaddr[2]
=
BB
,
etc.)

What's the problem?
Please help me to figure out what's wrong with the program.

#include <stdio.h>
#include <net/if.h> // struct ifconf
#include <errno.h>
#include <libnet.h>
#include <pcap.h>
#include <stdlib.h>
#include <unistd.h>

int getmacaddr() ;

int main(int argc, char *argv[])
{
getmacaddr();
}

int getmacaddr()
{
struct ifconf ifc;
struct ifreq *ifr;
int sfd;
int i;
int devnums;
char macaddr[ETHER_ADDR_LEN];

ifc.ifc_req = NULL;

sfd = socket(AF_INET,SOCK_DGRAM,0);
if(sfd == -1)
{
perror("socket : ");
return -1;
}

// get ifc.ifc_len
if(ioctl(sfd,SIOCGIFCONF,&ifc) == -1)
{
perror("ioctl - SIOCGIFCONF : ");
return -1;
}
devnums = ifc.ifc_len / sizeof(struct ifreq);

// malloc ifc.ifc_buf and get IFCONF list
ifc.ifc_buf = malloc(ifc.ifc_len);
memset(ifc.ifc_buf,0x0,ifc.ifc_len);

if(ioctl(sfd,SIOCGIFCONF,&ifc) == -1)
{
perror("ioctl - SIOCGIFCONF : ");
return -1;
}


for(i = 0; i < devnums; i++,ifc.ifc_req++)
{
// idfy dev
if( strcmp(ifc.ifc_req->ifr_ifrn.ifrn_name,"lo") && ifc.ifc_req->ifr_ifrn.ifrn_name != 0)
{
ifr = ifc.ifc_req;

// IP address
struct sockaddr_in *a = (struct sockaddr_in *) &ifr->ifr_addr;
printf("%s",inet_ntoa(a->sin_addr));
printf("\n");

//get IFHWADDR
if(ioctl(sfd,SIOCGIFHWADDR,ifr) == -1)
{
perror("ioctl - SIOCGIFHWADDR : ");
return -1;
}
}
}

memcpy(macaddr,ifr->ifr_hwaddr.sa_data,sizeof(macaddr));
for(i = 0; i < ETHER_ADDR_LEN; i++)
{
printf("%02x ",macaddr[i]);
}
printf("\n");

close(sfd);
// free(ifc.ifc_buf); <- ?? error

return 0;
}


EDIT

I've replaced the following line:

printf("%02x ",macaddr[i]);


with

printf("%02x ", (macaddr[i] & 0xff));

Answer

Try this:

printf("%02x ", (unsigned char)macaddr[i] & 0xff);

We specify the minimum field width in the format string. So to make sure that the value will look exactly as a single byte, you can leave only the first 16 bits by applying a bit mask.