summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Heidelberg <david@ixit.cz>2017-07-17 11:59:17 +0200
committerDavid Heidelberg <david@ixit.cz>2017-07-31 18:49:10 +0200
commit5832ec8dbd02aeaf1ee596697645c528df9daba1 (patch)
tree6e6a2be9e817a6d0b13d943dffe34117c104a194
parent25290b6d897ffeb3972013ae9538fae0a5bb1957 (diff)
downloadiputils-5832ec8dbd02aeaf1ee596697645c528df9daba1.tar.gz
ping: flowinfo: fixup checks for flowinfo and also add decimal numbers support
Signed-off-by: David Heidelberg <david@ixit.cz>
-rw-r--r--ping.c35
-rw-r--r--ping.h1
-rw-r--r--ping6_common.c21
3 files changed, 30 insertions, 27 deletions
diff --git a/ping.c b/ping.c
index e585390..c4584ee 100644
--- a/ping.c
+++ b/ping.c
@@ -97,6 +97,7 @@ static void usage(void) __attribute__((noreturn));
static unsigned short in_cksum(const unsigned short *addr, int len, unsigned short salt);
static void pr_icmph(__u8 type, __u8 code, __u32 info, struct icmphdr *icp);
static int parsetos(char *str);
+static int parseflow(char *str);
static struct {
struct cmsghdr cm;
@@ -267,11 +268,7 @@ main(int argc, char **argv)
hints.ai_family = AF_INET6;
break;
case 'F':
- flowlabel = hextoui(optarg);
- if (errno || (flowlabel & ~IPV6_FLOWINFO_FLOWLABEL)) {
- fprintf(stderr, "ping: Invalid flowinfo %s\n", optarg);
- exit(2);
- }
+ flowlabel = parseflow(optarg);
options |= F_FLOWINFO;
break;
case 'N':
@@ -1629,6 +1626,34 @@ int parsetos(char *str)
return(tos);
}
+int parseflow(char *str)
+{
+ const char *cp;
+ unsigned long val;
+ char *ep;
+
+ /* handle both hex and decimal values */
+ if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) {
+ cp = str + 2;
+ val = (int)strtoul(cp, &ep, 16);
+ } else
+ val = (int)strtoul(str, &ep, 10);
+
+ /* doesn't look like decimal or hex, eh? */
+ if (*ep != '\0') {
+ fprintf(stderr, "ping: \"%s\" bad value for flowinfo\n", str);
+ exit(2);
+ }
+
+ if (val & ~IPV6_FLOWINFO_FLOWLABEL) { /* Flow is 20 bit value */
+ fprintf(stderr, "ping: \"%s\" value is greater than 20 bits.\n", str);
+ exit(2);
+ }
+ return(val);
+}
+
+
+
void ping4_install_filter(socket_st *sock)
{
static int once;
diff --git a/ping.h b/ping.h
index 78e3853..b7a28f1 100644
--- a/ping.h
+++ b/ping.h
@@ -342,7 +342,6 @@ void ping6_install_filter(socket_st *sockets);
extern ping_func_set_st ping6_func_set;
int niquery_option_handler(const char *opt_arg);
-int hextoui(const char *str);
extern __u32 tclass;
extern __u32 flowlabel;
diff --git a/ping6_common.c b/ping6_common.c
index f5c81fd..45f39cc 100644
--- a/ping6_common.c
+++ b/ping6_common.c
@@ -610,27 +610,6 @@ int niquery_option_handler(const char *opt_arg)
return ret;
}
-int hextoui(const char *str)
-{
- unsigned long val;
- char *ep;
-
- errno = 0;
- val = strtoul(str, &ep, 16);
- if (*ep) {
- if (!errno)
- errno = EINVAL;
- return -1;
- }
-
- if (val > UINT_MAX) {
- errno = ERANGE;
- return UINT_MAX;
- }
-
- return val;
-}
-
int ping6_run(int argc, char **argv, struct addrinfo *ai, struct socket_st *sock)
{
static const struct addrinfo hints = { .ai_family = AF_INET6, .ai_flags = getaddrinfo_flags };