aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Dobriyan <adobriyan@gmail.com>2011-05-07 19:00:07 -0400
committerDavid S. Miller <davem@davemloft.net>2011-05-09 15:10:49 -0400
commit4940fc889e1e63667a15243028ddcd84d471cd8e (patch)
treec52bb193d0ad4f13e0f617748ed1db297261f521
parent99f823f98fb981b55c663a3783c3d2293958ece4 (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.c20
-rw-r--r--include/linux/if_ether.h1
-rw-r--r--net/core/netpoll.c26
-rw-r--r--net/core/pktgen.c53
-rw-r--r--net/core/utils.c24
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
456invalid:
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);
136extern struct ctl_table ether_table[]; 136extern struct ctl_table ether_table[];
137#endif 137#endif
138 138
139int mac_pton(const char *s, u8 *mac);
139extern ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len); 140extern 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}
298EXPORT_SYMBOL(inet_proto_csum_replace4); 298EXPORT_SYMBOL(inet_proto_csum_replace4);
299
300int 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}
322EXPORT_SYMBOL(mac_pton);