example:
12:45:ff:ab:aa:cd is valid 45:jj:jj:kk:ui>cd is not valid
You can rely on the sscanf to check the format and content of the provided MAC address, something like
bool checkMacAddr(const char * mac) noexcept
{
if(nullptr == mac) return false;
printf("[%s] strlen(%s)=%lu\n", __func__, mac, strlen(mac));
if(strlen(mac) != 17) return false;
uint32_t bytes[6]={0};
return (6 == sscanf(mac, "%02X:%02X:%02X:%02X:%02X:%02X"
, &bytes[5]
, &bytes[4]
, &bytes[3]
, &bytes[2]
, &bytes[1]
, &bytes[0]));
}
I needed to both validate and parse MAC address in ANSI C, so here's the function. It returns 1 in case the mac address has been validated (it will accept 12 hex characters, lower case or upper case, with or without colons, including partially correct input like b3:0a:23:48fad3
). It does the job for me in an embedded application on a cortex m3 controller.
The function will also accept direct input from a web page (that's actually how i use it), and therefore it will accept colons as %3A
characters.
The result is a six byte array. You will have to #include <cctype>
for this one.
The input string (*mac
) must be zero-terminated for the function to work.
int parse_mac_address(char* mac, unsigned char *mac_address) {
int index=0;
char temp_mac[12]={0,0,0,0,0,0,0,0,0,0,0,0};
memset(mac_address, 0, 6); // Clear the 6 needed bytes in target array (which should be defined as "unsigned char mac_address[6]")
while(*mac) { // Repeat while we have something in the string
if(index>11) { // The string may be longer than our 12 digits
return 0; // If it has too many digits, break out and return an error (zero)
}
if(isxdigit(*mac)) { // If this is a hex digit
if(isdigit(*mac)) { // If the digit is 0 to 9
temp_mac[index]=*mac-0x30; // Convert to a number
}
else { // If the digit is A to F
temp_mac[index]=toupper(*mac)-0x37; // Make sure it is an upper case letter and convert to a number
}
++mac; // Go further on the mac string
++index; // Promote the index to the next value in our array
}
else {
if(!(index%2) && *mac==':') { // If it was not a digit, it can be a colon, but only on an odd locations in the array
++mac;
}
else {
if(!(index%2) && *mac=='%' && *(mac+1)=='3' && toupper(*(mac+2))=='A') { // In case of web colon sign we receive '%3A' instead, so we have to jump 3 characters to the next digit
mac+=3;
}
else { // If we discovered anything else, this is not a valid mac address - break out and return an error (zero)
return 0;
}
}
}
}
if(index!=11) { // Last check - the index must be exactly 11, to indicate we have filled in 12 digits
return 0; // If not - return with error (zero)
}
for(index=0;index<6;index++) { // Now, when we have 12 digits in an array, we will convert them in to two-digit bytes
*(mac_address+5-index)=temp_mac[index*2+1]+temp_mac[index*2]*0x10; // Taking pairs of digits and converting them in to a byte
// This operation will make mac_address[0] the LSB and mac_address[5] the MSB
// If you need it the other way round, replace *(mac_address+5-index) with *(mac_address+index)
}
return 1; // Return OK (one)
}
Here is another simple function to check sanity of MAC address
#include <stdio.h>
#include <string.h>
typedef unsigned char byte;
#define ETH_ADDR_LEN 6
#define FALSE 0
#define TRUE 1
#define MAC_STR_LEN 18
#define SEPERATOR ':'
int isMacValid(char *MacAddress) {
char mac_part[3] = {0};
byte mac_byte = 0;
byte mac_idx = 0;
while(MacAddress[mac_idx] != 0 && mac_idx < MAC_STR_LEN){
if(mac_idx != 15 && MacAddress[mac_idx + 2] != SEPERATOR)
return FALSE;
strncpy(mac_part, MacAddress+mac_idx,2);
mac_byte = (byte)strtol(mac_part, NULL, 16);
if(mac_byte == 0 && strcmp(mac_part,"00"))
return FALSE;
mac_idx += 3;
}
if(mac_idx == MAC_STR_LEN)
return TRUE;
return FALSE;
}
The following code checks for valid MAC addresses (with or w/o the ":" separator):
#include <ctype.h>
int isValidMacAddress(const char* mac) {
int i = 0;
int s = 0;
while (*mac) {
if (isxdigit(*mac)) {
i++;
}
else if (*mac == ':' || *mac == '-') {
if (i == 0 || i / 2 - 1 != s)
break;
++s;
}
else {
s = -1;
}
++mac;
}
return (i == 12 && (s == 5 || s == 0));
}
The code checks the following:
mac
contains exactly 12 hexadecimal digits.:
appears in the input string, it only appears after an even number of hex digits.It works like this:
i
,which is the number of hex digits in mac
, is initialized to 0.while
loops over every character in the input string until either the string ends, or 12 hex digits have been detected.
*mac
) is a valid hex digit, then i
is incremented, and the loop examines the next character.If you don't want to accept separators, simply change the return statement to:
return (i == 12 && s == 0);