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 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 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