cmdline: replace FreeBSD ifdef for IP address parsing
[dpdk.git] / lib / librte_cmdline / cmdline_parse_ipaddr.c
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 <stdarg.h>
10 #include <inttypes.h>
11 #include <ctype.h>
12 #include <string.h>
13 #include <errno.h>
14 #include <arpa/inet.h>
15 #include <netinet/in.h>
16 #ifdef RTE_EXEC_ENV_FREEBSD
17 #include <sys/socket.h>
18 #endif
19
20 #include <rte_string_fns.h>
21
22 #include "cmdline_parse.h"
23 #include "cmdline_parse_ipaddr.h"
24
25 struct cmdline_token_ops cmdline_token_ipaddr_ops = {
26         .parse = cmdline_parse_ipaddr,
27         .complete_get_nb = NULL,
28         .complete_get_elt = NULL,
29         .get_help = cmdline_get_help_ipaddr,
30 };
31
32 #define PREFIXMAX 128
33 #define V4PREFIXMAX 32
34
35 int
36 cmdline_parse_ipaddr(cmdline_parse_token_hdr_t *tk, const char *buf, void *res,
37         unsigned ressize)
38 {
39         struct cmdline_token_ipaddr *tk2;
40         unsigned int token_len = 0;
41         char ip_str[INET6_ADDRSTRLEN+4+1]; /* '+4' is for prefixlen (if any) */
42         cmdline_ipaddr_t ipaddr;
43         char *prefix, *prefix_end;
44         long prefixlen = 0;
45
46         if (res && ressize < sizeof(cmdline_ipaddr_t))
47                 return -1;
48
49         if (!buf || !tk || ! *buf)
50                 return -1;
51
52         tk2 = (struct cmdline_token_ipaddr *)tk;
53
54         while (!cmdline_isendoftoken(buf[token_len]))
55                 token_len++;
56
57         /* if token is too big... */
58         if (token_len >= INET6_ADDRSTRLEN+4)
59                 return -1;
60
61         strlcpy(ip_str, buf, token_len + 1);
62
63         /* convert the network prefix */
64         if (tk2->ipaddr_data.flags & CMDLINE_IPADDR_NETWORK) {
65                 prefix = strrchr(ip_str, '/');
66                 if (prefix == NULL)
67                         return -1;
68                 *prefix = '\0';
69                 prefix ++;
70                 errno = 0;
71                 prefixlen = strtol(prefix, &prefix_end, 10);
72                 if (errno || (*prefix_end != '\0')
73                         || prefixlen < 0 || prefixlen > PREFIXMAX)
74                         return -1;
75                 ipaddr.prefixlen = prefixlen;
76         }
77         else {
78                 ipaddr.prefixlen = 0;
79         }
80
81         /* convert the IP addr */
82         if ((tk2->ipaddr_data.flags & CMDLINE_IPADDR_V4) &&
83             inet_pton(AF_INET, ip_str, &ipaddr.addr.ipv4) == 1 &&
84                 prefixlen <= V4PREFIXMAX) {
85                 ipaddr.family = AF_INET;
86                 if (res)
87                         memcpy(res, &ipaddr, sizeof(ipaddr));
88                 return token_len;
89         }
90         if ((tk2->ipaddr_data.flags & CMDLINE_IPADDR_V6) &&
91             inet_pton(AF_INET6, ip_str, &ipaddr.addr.ipv6) == 1) {
92                 ipaddr.family = AF_INET6;
93                 if (res)
94                         memcpy(res, &ipaddr, sizeof(ipaddr));
95                 return token_len;
96         }
97         return -1;
98
99 }
100
101 int cmdline_get_help_ipaddr(cmdline_parse_token_hdr_t *tk, char *dstbuf,
102                             unsigned int size)
103 {
104         struct cmdline_token_ipaddr *tk2;
105
106         if (!tk || !dstbuf)
107                 return -1;
108
109         tk2 = (struct cmdline_token_ipaddr *)tk;
110
111         switch (tk2->ipaddr_data.flags) {
112         case CMDLINE_IPADDR_V4:
113                 snprintf(dstbuf, size, "IPv4");
114                 break;
115         case CMDLINE_IPADDR_V6:
116                 snprintf(dstbuf, size, "IPv6");
117                 break;
118         case CMDLINE_IPADDR_V4|CMDLINE_IPADDR_V6:
119                 snprintf(dstbuf, size, "IPv4/IPv6");
120                 break;
121         case CMDLINE_IPADDR_NETWORK|CMDLINE_IPADDR_V4:
122                 snprintf(dstbuf, size, "IPv4 network");
123                 break;
124         case CMDLINE_IPADDR_NETWORK|CMDLINE_IPADDR_V6:
125                 snprintf(dstbuf, size, "IPv6 network");
126                 break;
127         case CMDLINE_IPADDR_NETWORK|CMDLINE_IPADDR_V4|CMDLINE_IPADDR_V6:
128                 snprintf(dstbuf, size, "IPv4/IPv6 network");
129                 break;
130         default:
131                 snprintf(dstbuf, size, "IPaddr (bad flags)");
132                 break;
133         }
134         return 0;
135 }