xref: /dpdk/lib/cmdline/cmdline_parse_ipaddr.c (revision 99a2dd955fba6e4cc23b77d590a033650ced9c45)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2010-2014 Intel Corporation.
3  * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
4  * All rights reserved.
5  */
6 
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <errno.h>
11 
12 #include <rte_string_fns.h>
13 
14 #include "cmdline_parse.h"
15 #include "cmdline_parse_ipaddr.h"
16 
17 struct cmdline_token_ops cmdline_token_ipaddr_ops = {
18 	.parse = cmdline_parse_ipaddr,
19 	.complete_get_nb = NULL,
20 	.complete_get_elt = NULL,
21 	.get_help = cmdline_get_help_ipaddr,
22 };
23 
24 #define PREFIXMAX 128
25 #define V4PREFIXMAX 32
26 
27 int
cmdline_parse_ipaddr(cmdline_parse_token_hdr_t * tk,const char * buf,void * res,unsigned ressize)28 cmdline_parse_ipaddr(cmdline_parse_token_hdr_t *tk, const char *buf, void *res,
29 	unsigned ressize)
30 {
31 	struct cmdline_token_ipaddr *tk2;
32 	unsigned int token_len = 0;
33 	char ip_str[INET6_ADDRSTRLEN+4+1]; /* '+4' is for prefixlen (if any) */
34 	cmdline_ipaddr_t ipaddr;
35 	char *prefix, *prefix_end;
36 	long prefixlen = 0;
37 
38 	if (res && ressize < sizeof(cmdline_ipaddr_t))
39 		return -1;
40 
41 	if (!buf || !tk || ! *buf)
42 		return -1;
43 
44 	tk2 = (struct cmdline_token_ipaddr *)tk;
45 
46 	while (!cmdline_isendoftoken(buf[token_len]))
47 		token_len++;
48 
49 	/* if token is too big... */
50 	if (token_len >= INET6_ADDRSTRLEN+4)
51 		return -1;
52 
53 	strlcpy(ip_str, buf, token_len + 1);
54 
55 	/* convert the network prefix */
56 	if (tk2->ipaddr_data.flags & CMDLINE_IPADDR_NETWORK) {
57 		prefix = strrchr(ip_str, '/');
58 		if (prefix == NULL)
59 			return -1;
60 		*prefix = '\0';
61 		prefix ++;
62 		errno = 0;
63 		prefixlen = strtol(prefix, &prefix_end, 10);
64 		if (errno || (*prefix_end != '\0')
65 			|| prefixlen < 0 || prefixlen > PREFIXMAX)
66 			return -1;
67 		ipaddr.prefixlen = prefixlen;
68 	}
69 	else {
70 		ipaddr.prefixlen = 0;
71 	}
72 
73 	/* convert the IP addr */
74 	if ((tk2->ipaddr_data.flags & CMDLINE_IPADDR_V4) &&
75 	    inet_pton(AF_INET, ip_str, &ipaddr.addr.ipv4) == 1 &&
76 		prefixlen <= V4PREFIXMAX) {
77 		ipaddr.family = AF_INET;
78 		if (res)
79 			memcpy(res, &ipaddr, sizeof(ipaddr));
80 		return token_len;
81 	}
82 	if ((tk2->ipaddr_data.flags & CMDLINE_IPADDR_V6) &&
83 	    inet_pton(AF_INET6, ip_str, &ipaddr.addr.ipv6) == 1) {
84 		ipaddr.family = AF_INET6;
85 		if (res)
86 			memcpy(res, &ipaddr, sizeof(ipaddr));
87 		return token_len;
88 	}
89 	return -1;
90 
91 }
92 
cmdline_get_help_ipaddr(cmdline_parse_token_hdr_t * tk,char * dstbuf,unsigned int size)93 int cmdline_get_help_ipaddr(cmdline_parse_token_hdr_t *tk, char *dstbuf,
94 			    unsigned int size)
95 {
96 	struct cmdline_token_ipaddr *tk2;
97 
98 	if (!tk || !dstbuf)
99 		return -1;
100 
101 	tk2 = (struct cmdline_token_ipaddr *)tk;
102 
103 	switch (tk2->ipaddr_data.flags) {
104 	case CMDLINE_IPADDR_V4:
105 		snprintf(dstbuf, size, "IPv4");
106 		break;
107 	case CMDLINE_IPADDR_V6:
108 		snprintf(dstbuf, size, "IPv6");
109 		break;
110 	case CMDLINE_IPADDR_V4|CMDLINE_IPADDR_V6:
111 		snprintf(dstbuf, size, "IPv4/IPv6");
112 		break;
113 	case CMDLINE_IPADDR_NETWORK|CMDLINE_IPADDR_V4:
114 		snprintf(dstbuf, size, "IPv4 network");
115 		break;
116 	case CMDLINE_IPADDR_NETWORK|CMDLINE_IPADDR_V6:
117 		snprintf(dstbuf, size, "IPv6 network");
118 		break;
119 	case CMDLINE_IPADDR_NETWORK|CMDLINE_IPADDR_V4|CMDLINE_IPADDR_V6:
120 		snprintf(dstbuf, size, "IPv4/IPv6 network");
121 		break;
122 	default:
123 		snprintf(dstbuf, size, "IPaddr (bad flags)");
124 		break;
125 	}
126 	return 0;
127 }
128