10

How do you convert a MAC address within an int array to string in C? For example, I am using the following array to store a MAC address:

int array[6] = {0x00, 0x0d, 0x3f, 0xcd, 0x02, 0x5f};

How do I convert this to a string, like "00:0d:3f:cd:02:5f"?

mpontillo
  • 13,559
  • 7
  • 62
  • 90
user2131316
  • 3,111
  • 12
  • 39
  • 53

7 Answers7

15

You could do this:

char macStr[18];
int array[6] = {0x00, 0x0d, 0x3f, 0xcd, 0x02, 0x5f};

snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
         array[0], array[1], array[2], array[3], array[4], array[5]);

If you want an uppercase string, use uppercase 'X':

snprintf(macStr, sizeof(macStr), "%02X:%02X:%02X:%02X:%02X:%02X",
         array[0], array[1], array[2], array[3], array[4], array[5]);
user2233706
  • 6,148
  • 5
  • 44
  • 86
  • 1
    On my MVSC build, this actually yielded 3FFFFFFF for the thrid parameter. The format "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx" fixes this – Arnout Dec 14 '18 at 09:41
  • Is there an easy way to make the string all upper-case while constructing it or is that a separate step?I know of `strupr()` but it only works on strings. – Frak May 16 '19 at 16:53
3
unsigned char array[6] = {0x00, 0x0d, 0x3f, 0xcd, 0x02, 0x5f};//or BYTE

char str[19];
sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",array[0], 
        array[1], array[2], array[3], array[4],array[5]);
diwatu
  • 5,641
  • 5
  • 38
  • 61
  • you are right, thanks i noticed that, and i am gonna change it. – diwatu May 14 '13 at 20:27
  • 1
    -1 because this overflows `str` if the `int`s in the array are too large. – mpontillo May 14 '13 at 20:44
  • The array only needs to be of size 18. As long as the the array is of type _unsigned_ char, it cannot possibly overflow. (BTW, I always to use snprintf just to be sure). Also, for those looking at this for reference, gcc also allows a %02hhx format specifier which handles negative numbers in the case of signed char arrays. – John Jul 28 '14 at 13:25
  • You have an extra ":%02x" in your format string which will certainly overflow your char array. – Craig B Feb 16 '22 at 22:01
  • @CraigB you are absolutely correct. Thanks – diwatu Feb 16 '22 at 22:25
1

whithout using snprintf, but that's just for fun....

#define MAC_LEN 6

static const char _mac[MAC_LEN] = { 0xBC, 0xDD, 0xC2, 0xF0, 0x2E, 0x06 };

int main(void){

char mac[MAC_LEN*2 + 1] = {0}; // added null char

int j = 0;
for( int i = 0;  i < sizeof(_mac) ; i++ )
{
    j = i * 2;
    mac[j] = (((_mac[i] & 0xF0)>>4)&0xF) ;
    mac[j] += (mac[j] <= 9) ? '0' : ('A' - 10);
    j++;
    mac[j] = (_mac[i] & 0x0F);
    mac[j] += (mac[j] <= 9) ? '0' : ('A' -10);
}

printf("Hello World!, my mac address : %s\n", mac);

fflush(stdout);

return 0;
}
0

First, you probably want to adjust the type you use to store the MAC address. I think unsigned char is better in this case. Next, I recommend you create a function to write the MAC addresses, so you aren't copying and pasting the same printf() statement everywhere in your code and adjusting the array you're indexing. (also, it allows the compiler to check the type you're using against the function parameter to ensure it is correct.)

Here's both a non-reentrant solution similar to inet_ntoa(), and a re-entrant solution similar to inet_ntoa_r():

#include <stdio.h>

unsigned char mac[6] = {0x00, 0x0d, 0x3f, 0xcd, 0x02, 0x5f};

char* MACADDR_toString(unsigned char* addr)
{
    static char str[18];

    if(addr == NULL) return "";

    snprintf(str, sizeof(str), "%02x:%02x:%02x:%02x:%02x:%02x", 
             addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);

    return str;
}

char* MACADDR_toString_r(unsigned char* addr, char* str, size_t size)
{
    if(addr == NULL || str == NULL || size < 18) return NULL;

    snprintf(str, size, "%02x:%02x:%02x:%02x:%02x:%02x", 
             addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);

    return str;
}

int main(int argc, char* argv[])
{
    char str[18];
    printf("%s\n", MACADDR_toString(mac));
    printf("%s\n", MACADDR_toString_r(mac, str, sizeof(str)));
    return 0;
}
mpontillo
  • 13,559
  • 7
  • 62
  • 90
0

If you are working on low level Kernel or driver stuff where the stdlib features cannot be used then it can be converted as follows-

#include <stdio.h>

struct ether_addr{
    int ether_addr_octet[6];
};

const char* ntoa(struct ether_addr ea)
{
    static char mstr[13];
    int j=11;
    for (int i=5;i>=0;i--)
    {
        int val = ea.ether_addr_octet[i];
        while (val)
        {
            int k = val%16;
            if (k==10)
                mstr[j--] = 'A';
            if (k==11)
                mstr[j--] = 'B';
            if (k==12)
                mstr[j--] = 'C';
            if (k==13)
                mstr[j--] = 'D';
            if (k==14)
                mstr[j--] = 'E';
            if (k==15)
                mstr[j--] = 'F';
            if (k<10)
                mstr[j--] = k + '0';
            val = val/16;
        }
    }
    mstr[12] = '\0';
    char *parr = mstr;
    printf("%6s\n",mstr);
    return mstr;
}

int main(void) {
    // your code goes here
    struct ether_addr ue;
    ue.ether_addr_octet[0] = 255;
    ue.ether_addr_octet[1] = 255;
    ue.ether_addr_octet[2] = 255;
    ue.ether_addr_octet[3] = 255;
    ue.ether_addr_octet[4] = 255;
    ue.ether_addr_octet[5] = 255;
    char *s = ntoa(ue);
    printf("%s",s);
    return 0;
}
Sandeep K V
  • 97
  • 2
  • 3
0

Gisway gave best answer, for me anyways ... adding extra stuff

...

#include<netinet/in.h>
#include<errno.h>
#include<netdb.h>
#include<stdio.h>   //For standard things
#include<stdlib.h>  //malloc
#include<string.h>  //strlen
#include<netinet/tcp.h> //Provides declarations for tcp header
#include<netinet/ip.h>  //Provides declarations for ip header
#include<netinet/if_ether.h>    //For ETH_P_ALL
#include<net/ethernet.h>    //For ether_header
#include<sys/socket.h>
#include<arpa/inet.h>
#include<sys/ioctl.h>
#include<sys/time.h>
#include<sys/types.h>
#include<unistd.h>

int main()
{

    int saddr_size , data_size;
    struct sockaddr saddr;
        
    unsigned char *buffer = (unsigned char *) malloc(65536); //Its Big!
    
    printf("Starting...\n");
    
    int sock_raw = socket( AF_PACKET , SOCK_RAW , htons(ETH_P_ALL)) ;
    setsockopt(sock_raw , SOL_SOCKET , SO_BINDTODEVICE , ifce , strlen(ifce)+ 1 );
    
    if(sock_raw < 0)
    {
        //Print the error with proper message
        perror("Socket Error");
        return 1;
    }
    while(1)
    {
        saddr_size = sizeof saddr;
        //Receive a packet
        data_size = recvfrom(sock_raw , buffer , 65536 , 0 , &saddr , (socklen_t*)&saddr_size);
        if(data_size <0 )
        {
            printf("Recvfrom error , failed to get packets\n");
            return 1;
        }
        //Now process the packet
        ProcessPacket(buffer , data_size);
    }
    close(sock_raw);
    printf("Finished");
    return 0;
}


void ProcessPacket(buffer , data_size)
{
    struct ethhdr *eth = (struct ethhdr *)Buffer;
    
    char src_mac[19];
    sprintf(src_mac, "%02x:%02x:%02x:%02x:%02x:%02x",eth->h_source[0] , eth->h_source[1] , eth->h_source[2] , eth->h_source[3] , eth->h_source[4] , eth->h_source[5]);
    printf("Mac address: %s\n",src_mac);
}
ART_W
  • 11
  • 2
-1

Call sprintf() in a loop ^_^:

#include <stdio.h>

int array[6] = {0x00, 0x0d, 0x3f, 0xcd, 0x02, 0x5f};

void macaddress_str(int a[], char *buf)
{
    int i;
    for (i = 0; i < 5; i++, buf += 3)
        sprintf(buf, "%02X:", a[i]);
    sprintf(buf, "%02X", a[i]);
}

int main()
{
    char buf[100];
    macaddress_str(array, buf);
    printf("%s\n", buf);
    return 0;
}
scottt
  • 7,008
  • 27
  • 37