util/nvmutil: more granular MAC parsing errors

tell the user exactly what they got wrong, instead
of simply printing "bad mac address", which is not
very helpful to the user

Signed-off-by: Leah Rowe <leah@libreboot.org>
master
Leah Rowe 2025-01-24 16:58:51 +00:00
parent dc376cca14
commit 11eb4df755
1 changed files with 16 additions and 12 deletions

View File

@ -15,10 +15,10 @@
#include <unistd.h> #include <unistd.h>
void cmd_setchecksum(void), cmd_brick(void), swap(int partnum), writeGbe(void), void cmd_setchecksum(void), cmd_brick(void), swap(int partnum), writeGbe(void),
cmd_dump(void), cmd_setmac(void), readGbe(void), cmd_copy(void), cmd_dump(void), cmd_setmac(void), readGbe(void), checkdir(const char *path),
macf(int partnum), hexdump(int partnum), openFiles(const char *path), macf(int partnum), hexdump(int partnum), openFiles(const char *path),
checkdir(const char *path); cmd_copy(void), parseMacString(const char *strMac, uint16_t *mac);
int macAddress(const char *strMac, uint16_t *mac), goodChecksum(int partnum); int goodChecksum(int partnum);
uint8_t hextonum(char chs), rhex(void); uint8_t hextonum(char chs), rhex(void);
#define COMMAND argv[2] #define COMMAND argv[2]
@ -205,8 +205,7 @@ readGbe(void)
void void
cmd_setmac(void) cmd_setmac(void)
{ {
if (macAddress(strMac, mac)) parseMacString(strMac, mac);
err(errno = ECANCELED, "Bad MAC address");
for (int partnum = 0; partnum < 2; partnum++) { for (int partnum = 0; partnum < 2; partnum++) {
if (!goodChecksum(part = partnum)) if (!goodChecksum(part = partnum))
@ -220,24 +219,27 @@ cmd_setmac(void)
} }
/* parse MAC string, write to char buffer */ /* parse MAC string, write to char buffer */
int void
macAddress(const char *strMac, uint16_t *mac) parseMacString(const char *strMac, uint16_t *mac)
{ {
uint64_t total = 0; uint64_t total = 0;
if (strnlen(strMac, 20) != 17) if (strnlen(strMac, 20) != 17)
return 1; /* 1 means error */ err(errno = EINVAL, "Invalid MAC address string length");
for (uint8_t h, i = 0; i < 16; i += 3) { for (uint8_t h, i = 0; i < 16; i += 3) {
if (i != 15) if (i != 15)
if (strMac[i + 2] != ':') if (strMac[i + 2] != ':')
return 1; err(errno = EINVAL,
"Invalid MAC address separator '%c'",
strMac[i + 2]);
int byte = i / 3; int byte = i / 3;
/* Update MAC buffer per-nibble from a given string */ /* Update MAC buffer per-nibble from a given string */
for (int nib = 0; nib < 2; nib++, total += h) { for (int nib = 0; nib < 2; nib++, total += h) {
if ((h = hextonum(strMac[i + nib])) > 15) if ((h = hextonum(strMac[i + nib])) > 15)
return 1; /* invalid character, MAC string */ err(errno = EINVAL, "Invalid character '%c'",
strMac[i + nib]);
/* if random: ensure local-only, unicast MAC */ /* if random: ensure local-only, unicast MAC */
if ((byte == 0) && (nib == 1)) /* unicast/local nib */ if ((byte == 0) && (nib == 1)) /* unicast/local nib */
@ -249,8 +251,10 @@ macAddress(const char *strMac, uint16_t *mac)
} }
} }
/* do not permit multicast/all-zero MAC: */ if (total == 0)
return ((total == 0) || (mac[0] & 1)) ? 1 : 0; err(errno = EINVAL, "Invalid MAC (all-zero MAC address)");
if (mac[0] & 1)
err(errno = EINVAL, "Invalid MAC (multicast bit set)");
} }
/* convert hex char to char value (0-15) */ /* convert hex char to char value (0-15) */