diff options
author | Alexey Dobriyan <adobriyan@gmail.com> | 2011-05-07 19:00:07 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-05-09 15:10:49 -0400 |
commit | 4940fc889e1e63667a15243028ddcd84d471cd8e (patch) | |
tree | c52bb193d0ad4f13e0f617748ed1db297261f521 | |
parent | 99f823f98fb981b55c663a3783c3d2293958ece4 (diff) |
net: add mac_pton() for parsing MAC address
mac_pton() parses MAC address in form XX:XX:XX:XX:XX:XX and only in that form.
mac_pton() doesn't dirty result until it's sure string representation is valid.
mac_pton() doesn't care about characters _after_ last octet,
it's up to caller to deal with it.
mac_pton() diverges from 0/-E return value convention.
Target usage:
if (!mac_pton(str, whatever->mac))
return -EINVAL;
/* ->mac being u8 [ETH_ALEN] is filled at this point. */
/* optionally check str[3 * ETH_ALEN - 1] for termination */
Use mac_pton() in pktgen and netconsole for start.
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/netconsole.c | 20 | ||||
-rw-r--r-- | include/linux/if_ether.h | 1 | ||||
-rw-r--r-- | net/core/netpoll.c | 26 | ||||
-rw-r--r-- | net/core/pktgen.c | 53 | ||||
-rw-r--r-- | net/core/utils.c | 24 |
5 files changed, 38 insertions, 86 deletions
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 62fdbaa1fb60..a83e101440fd 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c | |||
@@ -429,8 +429,6 @@ static ssize_t store_remote_mac(struct netconsole_target *nt, | |||
429 | size_t count) | 429 | size_t count) |
430 | { | 430 | { |
431 | u8 remote_mac[ETH_ALEN]; | 431 | u8 remote_mac[ETH_ALEN]; |
432 | char *p = (char *) buf; | ||
433 | int i; | ||
434 | 432 | ||
435 | if (nt->enabled) { | 433 | if (nt->enabled) { |
436 | printk(KERN_ERR "netconsole: target (%s) is enabled, " | 434 | printk(KERN_ERR "netconsole: target (%s) is enabled, " |
@@ -439,23 +437,13 @@ static ssize_t store_remote_mac(struct netconsole_target *nt, | |||
439 | return -EINVAL; | 437 | return -EINVAL; |
440 | } | 438 | } |
441 | 439 | ||
442 | for (i = 0; i < ETH_ALEN - 1; i++) { | 440 | if (!mac_pton(buf, remote_mac)) |
443 | remote_mac[i] = simple_strtoul(p, &p, 16); | 441 | return -EINVAL; |
444 | if (*p != ':') | 442 | if (buf[3 * ETH_ALEN - 1] && buf[3 * ETH_ALEN - 1] != '\n') |
445 | goto invalid; | 443 | return -EINVAL; |
446 | p++; | ||
447 | } | ||
448 | remote_mac[ETH_ALEN - 1] = simple_strtoul(p, &p, 16); | ||
449 | if (*p && (*p != '\n')) | ||
450 | goto invalid; | ||
451 | |||
452 | memcpy(nt->np.remote_mac, remote_mac, ETH_ALEN); | 444 | memcpy(nt->np.remote_mac, remote_mac, ETH_ALEN); |
453 | 445 | ||
454 | return strnlen(buf, count); | 446 | return strnlen(buf, count); |
455 | |||
456 | invalid: | ||
457 | printk(KERN_ERR "netconsole: invalid input\n"); | ||
458 | return -EINVAL; | ||
459 | } | 447 | } |
460 | 448 | ||
461 | /* | 449 | /* |
diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h index be69043d2896..0f1325d98295 100644 --- a/include/linux/if_ether.h +++ b/include/linux/if_ether.h | |||
@@ -136,6 +136,7 @@ int eth_header_parse(const struct sk_buff *skb, unsigned char *haddr); | |||
136 | extern struct ctl_table ether_table[]; | 136 | extern struct ctl_table ether_table[]; |
137 | #endif | 137 | #endif |
138 | 138 | ||
139 | int mac_pton(const char *s, u8 *mac); | ||
139 | extern ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len); | 140 | extern ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len); |
140 | 141 | ||
141 | #endif | 142 | #endif |
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 46d9c3a4de2f..2d7d6d473781 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
@@ -698,32 +698,8 @@ int netpoll_parse_options(struct netpoll *np, char *opt) | |||
698 | 698 | ||
699 | if (*cur != 0) { | 699 | if (*cur != 0) { |
700 | /* MAC address */ | 700 | /* MAC address */ |
701 | if ((delim = strchr(cur, ':')) == NULL) | 701 | if (!mac_pton(cur, np->remote_mac)) |
702 | goto parse_failed; | 702 | goto parse_failed; |
703 | *delim = 0; | ||
704 | np->remote_mac[0] = simple_strtol(cur, NULL, 16); | ||
705 | cur = delim + 1; | ||
706 | if ((delim = strchr(cur, ':')) == NULL) | ||
707 | goto parse_failed; | ||
708 | *delim = 0; | ||
709 | np->remote_mac[1] = simple_strtol(cur, NULL, 16); | ||
710 | cur = delim + 1; | ||
711 | if ((delim = strchr(cur, ':')) == NULL) | ||
712 | goto parse_failed; | ||
713 | *delim = 0; | ||
714 | np->remote_mac[2] = simple_strtol(cur, NULL, 16); | ||
715 | cur = delim + 1; | ||
716 | if ((delim = strchr(cur, ':')) == NULL) | ||
717 | goto parse_failed; | ||
718 | *delim = 0; | ||
719 | np->remote_mac[3] = simple_strtol(cur, NULL, 16); | ||
720 | cur = delim + 1; | ||
721 | if ((delim = strchr(cur, ':')) == NULL) | ||
722 | goto parse_failed; | ||
723 | *delim = 0; | ||
724 | np->remote_mac[4] = simple_strtol(cur, NULL, 16); | ||
725 | cur = delim + 1; | ||
726 | np->remote_mac[5] = simple_strtol(cur, NULL, 16); | ||
727 | } | 703 | } |
728 | 704 | ||
729 | netpoll_print_options(np); | 705 | netpoll_print_options(np); |
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index d41d88b53e18..379270f14771 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
@@ -1420,11 +1420,6 @@ static ssize_t pktgen_if_write(struct file *file, | |||
1420 | return count; | 1420 | return count; |
1421 | } | 1421 | } |
1422 | if (!strcmp(name, "dst_mac")) { | 1422 | if (!strcmp(name, "dst_mac")) { |
1423 | char *v = valstr; | ||
1424 | unsigned char old_dmac[ETH_ALEN]; | ||
1425 | unsigned char *m = pkt_dev->dst_mac; | ||
1426 | memcpy(old_dmac, pkt_dev->dst_mac, ETH_ALEN); | ||
1427 | |||
1428 | len = strn_len(&user_buffer[i], sizeof(valstr) - 1); | 1423 | len = strn_len(&user_buffer[i], sizeof(valstr) - 1); |
1429 | if (len < 0) | 1424 | if (len < 0) |
1430 | return len; | 1425 | return len; |
@@ -1432,35 +1427,16 @@ static ssize_t pktgen_if_write(struct file *file, | |||
1432 | memset(valstr, 0, sizeof(valstr)); | 1427 | memset(valstr, 0, sizeof(valstr)); |
1433 | if (copy_from_user(valstr, &user_buffer[i], len)) | 1428 | if (copy_from_user(valstr, &user_buffer[i], len)) |
1434 | return -EFAULT; | 1429 | return -EFAULT; |
1435 | i += len; | ||
1436 | |||
1437 | for (*m = 0; *v && m < pkt_dev->dst_mac + 6; v++) { | ||
1438 | int value; | ||
1439 | |||
1440 | value = hex_to_bin(*v); | ||
1441 | if (value >= 0) | ||
1442 | *m = *m * 16 + value; | ||
1443 | |||
1444 | if (*v == ':') { | ||
1445 | m++; | ||
1446 | *m = 0; | ||
1447 | } | ||
1448 | } | ||
1449 | 1430 | ||
1431 | if (!mac_pton(valstr, pkt_dev->dst_mac)) | ||
1432 | return -EINVAL; | ||
1450 | /* Set up Dest MAC */ | 1433 | /* Set up Dest MAC */ |
1451 | if (compare_ether_addr(old_dmac, pkt_dev->dst_mac)) | 1434 | memcpy(&pkt_dev->hh[0], pkt_dev->dst_mac, ETH_ALEN); |
1452 | memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, ETH_ALEN); | ||
1453 | 1435 | ||
1454 | sprintf(pg_result, "OK: dstmac"); | 1436 | sprintf(pg_result, "OK: dstmac %pM", pkt_dev->dst_mac); |
1455 | return count; | 1437 | return count; |
1456 | } | 1438 | } |
1457 | if (!strcmp(name, "src_mac")) { | 1439 | if (!strcmp(name, "src_mac")) { |
1458 | char *v = valstr; | ||
1459 | unsigned char old_smac[ETH_ALEN]; | ||
1460 | unsigned char *m = pkt_dev->src_mac; | ||
1461 | |||
1462 | memcpy(old_smac, pkt_dev->src_mac, ETH_ALEN); | ||
1463 | |||
1464 | len = strn_len(&user_buffer[i], sizeof(valstr) - 1); | 1440 | len = strn_len(&user_buffer[i], sizeof(valstr) - 1); |
1465 | if (len < 0) | 1441 | if (len < 0) |
1466 | return len; | 1442 | return len; |
@@ -1468,26 +1444,13 @@ static ssize_t pktgen_if_write(struct file *file, | |||
1468 | memset(valstr, 0, sizeof(valstr)); | 1444 | memset(valstr, 0, sizeof(valstr)); |
1469 | if (copy_from_user(valstr, &user_buffer[i], len)) | 1445 | if (copy_from_user(valstr, &user_buffer[i], len)) |
1470 | return -EFAULT; | 1446 | return -EFAULT; |
1471 | i += len; | ||
1472 | |||
1473 | for (*m = 0; *v && m < pkt_dev->src_mac + 6; v++) { | ||
1474 | int value; | ||
1475 | |||
1476 | value = hex_to_bin(*v); | ||
1477 | if (value >= 0) | ||
1478 | *m = *m * 16 + value; | ||
1479 | |||
1480 | if (*v == ':') { | ||
1481 | m++; | ||
1482 | *m = 0; | ||
1483 | } | ||
1484 | } | ||
1485 | 1447 | ||
1448 | if (!mac_pton(valstr, pkt_dev->src_mac)) | ||
1449 | return -EINVAL; | ||
1486 | /* Set up Src MAC */ | 1450 | /* Set up Src MAC */ |
1487 | if (compare_ether_addr(old_smac, pkt_dev->src_mac)) | 1451 | memcpy(&pkt_dev->hh[6], pkt_dev->src_mac, ETH_ALEN); |
1488 | memcpy(&(pkt_dev->hh[6]), pkt_dev->src_mac, ETH_ALEN); | ||
1489 | 1452 | ||
1490 | sprintf(pg_result, "OK: srcmac"); | 1453 | sprintf(pg_result, "OK: srcmac %pM", pkt_dev->src_mac); |
1491 | return count; | 1454 | return count; |
1492 | } | 1455 | } |
1493 | 1456 | ||
diff --git a/net/core/utils.c b/net/core/utils.c index 5fea0ab21902..2012bc797f9c 100644 --- a/net/core/utils.c +++ b/net/core/utils.c | |||
@@ -296,3 +296,27 @@ void inet_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb, | |||
296 | csum_unfold(*sum))); | 296 | csum_unfold(*sum))); |
297 | } | 297 | } |
298 | EXPORT_SYMBOL(inet_proto_csum_replace4); | 298 | EXPORT_SYMBOL(inet_proto_csum_replace4); |
299 | |||
300 | int mac_pton(const char *s, u8 *mac) | ||
301 | { | ||
302 | int i; | ||
303 | |||
304 | /* XX:XX:XX:XX:XX:XX */ | ||
305 | if (strlen(s) < 3 * ETH_ALEN - 1) | ||
306 | return 0; | ||
307 | |||
308 | /* Don't dirty result unless string is valid MAC. */ | ||
309 | for (i = 0; i < ETH_ALEN; i++) { | ||
310 | if (!strchr("0123456789abcdefABCDEF", s[i * 3])) | ||
311 | return 0; | ||
312 | if (!strchr("0123456789abcdefABCDEF", s[i * 3 + 1])) | ||
313 | return 0; | ||
314 | if (i != ETH_ALEN - 1 && s[i * 3 + 2] != ':') | ||
315 | return 0; | ||
316 | } | ||
317 | for (i = 0; i < ETH_ALEN; i++) { | ||
318 | mac[i] = (hex_to_bin(s[i * 3]) << 4) | hex_to_bin(s[i * 3 + 1]); | ||
319 | } | ||
320 | return 1; | ||
321 | } | ||
322 | EXPORT_SYMBOL(mac_pton); | ||