15

I want to take MAC address from command line, so I got it as string...how do I can convert this 17 byte MAC string like "00:0d:3f:cd:02:5f" to 6 byte MAC Address in C

user1727270
  • 303
  • 1
  • 3
  • 10

3 Answers3

28

On a C99-conformant implementation, this should work

unsigned char mac[6];

sscanf(macStr, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5]);

Otherwise, you'll need:

unsigned int iMac[6];
unsigned char mac[6];
int i;

sscanf(macStr, "%x:%x:%x:%x:%x:%x", &iMac[0], &iMac[1], &iMac[2], &iMac[3], &iMac[4], &iMac[5]);
for(i=0;i<6;i++)
    mac[i] = (unsigned char)iMac[i];
Random832
  • 37,415
  • 3
  • 44
  • 63
CrazyCasta
  • 26,917
  • 4
  • 45
  • 72
  • It's a c99 thing, so it may not work with microsoft C, I'm not sure. – Random832 Oct 07 '12 at 20:49
  • Thanks. The first solution worked. Could you tell me how to convert the mac string to binary bytes. – user1727270 Oct 11 '12 at 00:41
  • I'm a little confused what you're asking for because I thought that's what you asked the first time and we answered. Are you asking to convert the binary mac bytes to a hex mac? – CrazyCasta Oct 11 '12 at 02:32
  • I meant, when I print the address, it should be in binary format of 6 bytes, like 11000011 11110000 ...up to 48 bits – user1727270 Oct 11 '12 at 06:52
  • Oh, you mean a mac string to binary bits. See this post for outputting in binary http://stackoverflow.com/questions/111928/is-there-a-printf-converter-to-print-in-binary-format – CrazyCasta Oct 11 '12 at 20:16
  • unsigned char iMac[6];sscanf(macStr, "%x:%x:%x:%x:%x:%x", &iMac[0], &iMac[1], &iMac[2], &iMac[3], &iMac[4], &iMac[5]); Will it not work? – Nayan Apr 22 '20 at 12:05
  • @Nayan You have a very good question and it is a very good example to learn from. Why don't you post at https://codereview.stackexchange.com/ and post a link here. I'll go answer it if no one else has. Also, as a hint to the problem, extend iMac by one byte, set that last byte to something non-zero and check the value before and after sscanf. I do think it would still be worth posting though, because it's a good teaching example. – CrazyCasta Apr 23 '20 at 17:35
2

Without built-in functions and error handling simply:

unsigned char mac[6];
for( uint idx = 0; idx < sizeof(mac)/sizeof(mac[0]); ++idx )
{
    mac[idx]  = hex_digit( mac_str[     3 * idx ] ) << 4;
    mac[idx] |= hex_digit( mac_str[ 1 + 3 * idx ] );
}

Input is actually 3*6 bytes with \0.

unsigned char hex_digit( char ch )
{
    if(             ( '0' <= ch ) && ( ch <= '9' ) ) { ch -= '0'; }
    else
    {
        if(         ( 'a' <= ch ) && ( ch <= 'f' ) ) { ch += 10 - 'a'; }
        else
        {
            if(     ( 'A' <= ch ) && ( ch <= 'F' ) ) { ch += 10 - 'A'; }
            else                                     { ch = 16; }
        }
    }
    return ch;
}
IKavanagh
  • 6,089
  • 11
  • 42
  • 47
renonsz
  • 571
  • 1
  • 4
  • 17
1

There's standard c library funtion do this

  #include <netinet/ether.h>

  char *ether_ntoa(const struct ether_addr *addr);
  struct ether_addr *ether_aton(const char *asc);

The structure ether_addr is defined in <net/ethernet.h> as:

  struct ether_addr {
        uint8_t ether_addr_octet[6];
  }
yuanjianpeng
  • 318
  • 2
  • 11
  • Only problem is `ether_ntoa()` *omits leaning zeros* -- so you will not get the original 17-character string back after a call to `ether_aton()` if any octet contains a leading zero, e.g. `0c:03:...`. – David C. Rankin Jul 20 '23 at 09:15