How do you validate that a string is a valid MAC address in C?
example:
12:45:ff:ab:a开发者_运维知识库a:cd is valid 45:jj:jj:kk:ui>cd is not valid
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:
- that the input string
mac
contains exactly 12 hexadecimal digits. - that, if a separator colon
:
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 inmac
, is initialized to 0.- The
while
loops over every character in the input string until either the string ends, or 12 hex digits have been detected.- If the current character (
*mac
) is a valid hex digit, theni
is incremented, and the loop examines the next character. - Otherwise, the loop checks if the current character is a separator (colon or a dash); if so, it verifies that there is one separator for every pair of hex digits. Otherwise, the loop is aborted.
- If the current character (
- After the loop finishes, the function checks if 12 hex digits have been found, and zero or exactly five separators, and returns the result.
If you don't want to accept separators, simply change the return statement to:
return (i == 12 && s == 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;
}
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]));
}
精彩评论