* [PATCH] net: add mac_pton() for parsing MAC address
@ 2011-05-04 6:15 Alexey Dobriyan
2011-05-04 15:12 ` Stephen Hemminger
0 siblings, 1 reply; 3+ messages in thread
From: Alexey Dobriyan @ 2011-05-04 6:15 UTC (permalink / raw)
To: davem; +Cc: netdev
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>
---
drivers/net/netconsole.c | 18 +++------------
include/linux/if_ether.h | 1
net/core/netpoll.c | 26 -----------------------
net/core/pktgen.c | 53 +++++++----------------------------------------
net/core/utils.c | 24 +++++++++++++++++++++
5 files changed, 38 insertions(+), 84 deletions(-)
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -473,23 +473,13 @@ static ssize_t store_remote_mac(struct netconsole_target *nt,
return -EINVAL;
}
- for (i = 0; i < ETH_ALEN - 1; i++) {
- remote_mac[i] = simple_strtoul(p, &p, 16);
- if (*p != ':')
- goto invalid;
- p++;
- }
- remote_mac[ETH_ALEN - 1] = simple_strtoul(p, &p, 16);
- if (*p && (*p != '\n'))
- goto invalid;
-
+ if (!mac_pton(buf, remote_mac))
+ return -EINVAL;
+ if (buf[3 * ETH_ALEN - 1] && buf[3 * ETH_ALEN - 1] != '\n')
+ return -EINVAL;
memcpy(nt->np.remote_mac, remote_mac, ETH_ALEN);
return strnlen(buf, count);
-
-invalid:
- printk(KERN_ERR "netconsole: invalid input\n");
- return -EINVAL;
}
/*
--- 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);
extern struct ctl_table ether_table[];
#endif
+int mac_pton(const char *s, u8 *mac);
extern ssize_t sysfs_format_mac(char *buf, const unsigned char *addr, int len);
#endif
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -698,32 +698,8 @@ int netpoll_parse_options(struct netpoll *np, char *opt)
if (*cur != 0) {
/* MAC address */
- if ((delim = strchr(cur, ':')) == NULL)
+ if (!mac_pton(cur, np->remote_mac))
goto parse_failed;
- *delim = 0;
- np->remote_mac[0] = simple_strtol(cur, NULL, 16);
- cur = delim + 1;
- if ((delim = strchr(cur, ':')) == NULL)
- goto parse_failed;
- *delim = 0;
- np->remote_mac[1] = simple_strtol(cur, NULL, 16);
- cur = delim + 1;
- if ((delim = strchr(cur, ':')) == NULL)
- goto parse_failed;
- *delim = 0;
- np->remote_mac[2] = simple_strtol(cur, NULL, 16);
- cur = delim + 1;
- if ((delim = strchr(cur, ':')) == NULL)
- goto parse_failed;
- *delim = 0;
- np->remote_mac[3] = simple_strtol(cur, NULL, 16);
- cur = delim + 1;
- if ((delim = strchr(cur, ':')) == NULL)
- goto parse_failed;
- *delim = 0;
- np->remote_mac[4] = simple_strtol(cur, NULL, 16);
- cur = delim + 1;
- np->remote_mac[5] = simple_strtol(cur, NULL, 16);
}
netpoll_print_options(np);
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -1420,11 +1420,6 @@ static ssize_t pktgen_if_write(struct file *file,
return count;
}
if (!strcmp(name, "dst_mac")) {
- char *v = valstr;
- unsigned char old_dmac[ETH_ALEN];
- unsigned char *m = pkt_dev->dst_mac;
- memcpy(old_dmac, pkt_dev->dst_mac, ETH_ALEN);
-
len = strn_len(&user_buffer[i], sizeof(valstr) - 1);
if (len < 0)
return len;
@@ -1432,35 +1427,16 @@ static ssize_t pktgen_if_write(struct file *file,
memset(valstr, 0, sizeof(valstr));
if (copy_from_user(valstr, &user_buffer[i], len))
return -EFAULT;
- i += len;
-
- for (*m = 0; *v && m < pkt_dev->dst_mac + 6; v++) {
- int value;
-
- value = hex_to_bin(*v);
- if (value >= 0)
- *m = *m * 16 + value;
-
- if (*v == ':') {
- m++;
- *m = 0;
- }
- }
+ if (!mac_pton(valstr, pkt_dev->dst_mac))
+ return -EINVAL;
/* Set up Dest MAC */
- if (compare_ether_addr(old_dmac, pkt_dev->dst_mac))
- memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, ETH_ALEN);
+ memcpy(&pkt_dev->hh[0], pkt_dev->dst_mac, ETH_ALEN);
- sprintf(pg_result, "OK: dstmac");
+ sprintf(pg_result, "OK: dstmac %pM", pkt_dev->dst_mac);
return count;
}
if (!strcmp(name, "src_mac")) {
- char *v = valstr;
- unsigned char old_smac[ETH_ALEN];
- unsigned char *m = pkt_dev->src_mac;
-
- memcpy(old_smac, pkt_dev->src_mac, ETH_ALEN);
-
len = strn_len(&user_buffer[i], sizeof(valstr) - 1);
if (len < 0)
return len;
@@ -1468,26 +1444,13 @@ static ssize_t pktgen_if_write(struct file *file,
memset(valstr, 0, sizeof(valstr));
if (copy_from_user(valstr, &user_buffer[i], len))
return -EFAULT;
- i += len;
-
- for (*m = 0; *v && m < pkt_dev->src_mac + 6; v++) {
- int value;
-
- value = hex_to_bin(*v);
- if (value >= 0)
- *m = *m * 16 + value;
-
- if (*v == ':') {
- m++;
- *m = 0;
- }
- }
+ if (!mac_pton(valstr, pkt_dev->src_mac))
+ return -EINVAL;
/* Set up Src MAC */
- if (compare_ether_addr(old_smac, pkt_dev->src_mac))
- memcpy(&(pkt_dev->hh[6]), pkt_dev->src_mac, ETH_ALEN);
+ memcpy(&pkt_dev->hh[6], pkt_dev->src_mac, ETH_ALEN);
- sprintf(pg_result, "OK: srcmac");
+ sprintf(pg_result, "OK: srcmac %pM", pkt_dev->src_mac);
return count;
}
--- 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,
csum_unfold(*sum)));
}
EXPORT_SYMBOL(inet_proto_csum_replace4);
+
+int mac_pton(const char *s, u8 *mac)
+{
+ int i;
+
+ /* XX:XX:XX:XX:XX:XX */
+ if (strlen(s) < 3 * ETH_ALEN - 1)
+ return 0;
+
+ /* Don't half dirty result. */
+ for (i = 0; i < ETH_ALEN; i++) {
+ if (!strchr("0123456789abcdefABCDEF", s[i * 3]))
+ return 0;
+ if (!strchr("0123456789abcdefABCDEF", s[i * 3 + 1]))
+ return 0;
+ if (i != ETH_ALEN - 1 && s[i * 3 + 2] != ':')
+ return 0;
+ }
+ for (i = 0; i < ETH_ALEN; i++) {
+ mac[i] = (hex_to_bin(s[i * 3]) << 4) | hex_to_bin(s[i * 3 + 1]);
+ }
+ return 1;
+}
+EXPORT_SYMBOL(mac_pton);
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] net: add mac_pton() for parsing MAC address
2011-05-04 6:15 [PATCH] net: add mac_pton() for parsing MAC address Alexey Dobriyan
@ 2011-05-04 15:12 ` Stephen Hemminger
2011-05-04 17:39 ` Alexey Dobriyan
0 siblings, 1 reply; 3+ messages in thread
From: Stephen Hemminger @ 2011-05-04 15:12 UTC (permalink / raw)
To: Alexey Dobriyan; +Cc: davem, netdev
On Wed, 4 May 2011 09:15:51 +0300
Alexey Dobriyan <adobriyan@gmail.com> wrote:
> +int mac_pton(const char *s, u8 *mac)
> +{
> + int i;
> +
> + /* XX:XX:XX:XX:XX:XX */
> + if (strlen(s) < 3 * ETH_ALEN - 1)
> + return 0;
> +
> + /* Don't half dirty result. */
Shouldn't this be "Don't allow dirty result."?
> + for (i = 0; i < ETH_ALEN; i++) {
> + if (!strchr("0123456789abcdefABCDEF", s[i * 3]))
> + return 0;
> + if (!strchr("0123456789abcdefABCDEF", s[i * 3 + 1]))
> + return 0;
if (!isxdigit(s[i*3]) || !isxdigit(s[i*3+1]))
return 0;
> + if (i != ETH_ALEN - 1 && s[i * 3 + 2] != ':')
> + return 0;
> + }
> + for (i = 0; i < ETH_ALEN; i++) {
> + mac[i] = (hex_to_bin(s[i * 3]) << 4) | hex_to_bin(s[i * 3 + 1]);
hex2bin(&mac[i], &s[i*3], 1);
> + }
> + return 1;
> +}
> +EXPORT_SYMBOL(mac_pton);
Also don't need two loops, okay to parse partial result.
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] net: add mac_pton() for parsing MAC address
2011-05-04 15:12 ` Stephen Hemminger
@ 2011-05-04 17:39 ` Alexey Dobriyan
0 siblings, 0 replies; 3+ messages in thread
From: Alexey Dobriyan @ 2011-05-04 17:39 UTC (permalink / raw)
To: Stephen Hemminger; +Cc: davem, netdev
On Wed, May 04, 2011 at 08:12:25AM -0700, Stephen Hemminger wrote:
> On Wed, 4 May 2011 09:15:51 +0300
> Alexey Dobriyan <adobriyan@gmail.com> wrote:
>
> > +int mac_pton(const char *s, u8 *mac)
> > +{
> > + int i;
> > +
> > + /* XX:XX:XX:XX:XX:XX */
> > + if (strlen(s) < 3 * ETH_ALEN - 1)
> > + return 0;
> > +
> > + /* Don't half dirty result. */
> Shouldn't this be "Don't allow dirty result."?
Maybe.
It means "only dirty result, if everything is OK." like inet_pton(3).
> > + for (i = 0; i < ETH_ALEN; i++) {
> > + if (!strchr("0123456789abcdefABCDEF", s[i * 3]))
> > + return 0;
> > + if (!strchr("0123456789abcdefABCDEF", s[i * 3 + 1]))
> > + return 0;
>
> if (!isxdigit(s[i*3]) || !isxdigit(s[i*3+1]))
> return 0;
>
> > + if (i != ETH_ALEN - 1 && s[i * 3 + 2] != ':')
> > + return 0;
> > + }
> > + for (i = 0; i < ETH_ALEN; i++) {
> > + mac[i] = (hex_to_bin(s[i * 3]) << 4) | hex_to_bin(s[i * 3 + 1]);
> hex2bin(&mac[i], &s[i*3], 1);
> > + }
> > + return 1;
> > +}
> > +EXPORT_SYMBOL(mac_pton);
>
> Also don't need two loops, okay to parse partial result.
You need two loops if code is written as sent.
Otherwise, caller need temporary buffer to not corrupt possibly important
previous MAC value.
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2011-05-04 17:40 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-05-04 6:15 [PATCH] net: add mac_pton() for parsing MAC address Alexey Dobriyan
2011-05-04 15:12 ` Stephen Hemminger
2011-05-04 17:39 ` Alexey Dobriyan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).