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>
This commit is contained in:
parent
99f823f98f
commit
4940fc889e
|
@ -429,8 +429,6 @@ static ssize_t store_remote_mac(struct netconsole_target *nt,
|
|||
size_t count)
|
||||
{
|
||||
u8 remote_mac[ETH_ALEN];
|
||||
char *p = (char *) buf;
|
||||
int i;
|
||||
|
||||
if (nt->enabled) {
|
||||
printk(KERN_ERR "netconsole: target (%s) is enabled, "
|
||||
|
@ -439,23 +437,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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 dirty result unless string is valid MAC. */
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue