15129044dSC.J. Collier/*-
25129044dSC.J. Collier *   BSD LICENSE
35129044dSC.J. Collier *
45129044dSC.J. Collier *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
55129044dSC.J. Collier *   All rights reserved.
65129044dSC.J. Collier *
75129044dSC.J. Collier *   Redistribution and use in source and binary forms, with or without
85129044dSC.J. Collier *   modification, are permitted provided that the following conditions
95129044dSC.J. Collier *   are met:
105129044dSC.J. Collier *
115129044dSC.J. Collier *     * Redistributions of source code must retain the above copyright
125129044dSC.J. Collier *       notice, this list of conditions and the following disclaimer.
135129044dSC.J. Collier *     * Redistributions in binary form must reproduce the above copyright
145129044dSC.J. Collier *       notice, this list of conditions and the following disclaimer in
155129044dSC.J. Collier *       the documentation and/or other materials provided with the
165129044dSC.J. Collier *       distribution.
175129044dSC.J. Collier *     * Neither the name of Intel Corporation nor the names of its
185129044dSC.J. Collier *       contributors may be used to endorse or promote products derived
195129044dSC.J. Collier *       from this software without specific prior written permission.
205129044dSC.J. Collier *
215129044dSC.J. Collier *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
225129044dSC.J. Collier *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
235129044dSC.J. Collier *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
245129044dSC.J. Collier *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
255129044dSC.J. Collier *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
265129044dSC.J. Collier *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
275129044dSC.J. Collier *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
285129044dSC.J. Collier *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
295129044dSC.J. Collier *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
305129044dSC.J. Collier *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
315129044dSC.J. Collier *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
325129044dSC.J. Collier */
335129044dSC.J. Collier
345129044dSC.J. Collier/*
355129044dSC.J. Collier * Copyright (c) 2009, Olivier MATZ <zer0@droids-corp.org>
365129044dSC.J. Collier * All rights reserved.
375129044dSC.J. Collier * Redistribution and use in source and binary forms, with or without
385129044dSC.J. Collier * modification, are permitted provided that the following conditions are met:
395129044dSC.J. Collier *
405129044dSC.J. Collier *     * Redistributions of source code must retain the above copyright
415129044dSC.J. Collier *       notice, this list of conditions and the following disclaimer.
425129044dSC.J. Collier *     * Redistributions in binary form must reproduce the above copyright
435129044dSC.J. Collier *       notice, this list of conditions and the following disclaimer in the
445129044dSC.J. Collier *       documentation and/or other materials provided with the distribution.
455129044dSC.J. Collier *     * Neither the name of the University of California, Berkeley nor the
465129044dSC.J. Collier *       names of its contributors may be used to endorse or promote products
475129044dSC.J. Collier *       derived from this software without specific prior written permission.
485129044dSC.J. Collier *
495129044dSC.J. Collier * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
505129044dSC.J. Collier * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
515129044dSC.J. Collier * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
525129044dSC.J. Collier * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
535129044dSC.J. Collier * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
545129044dSC.J. Collier * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
555129044dSC.J. Collier * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
565129044dSC.J. Collier * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
575129044dSC.J. Collier * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
585129044dSC.J. Collier * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
595129044dSC.J. Collier */
605129044dSC.J. Collier
615129044dSC.J. Collier/*
625129044dSC.J. Collier * For inet_ntop() functions:
635129044dSC.J. Collier *
645129044dSC.J. Collier * Copyright (c) 1996 by Internet Software Consortium.
655129044dSC.J. Collier *
665129044dSC.J. Collier * Permission to use, copy, modify, and distribute this software for any
675129044dSC.J. Collier * purpose with or without fee is hereby granted, provided that the above
685129044dSC.J. Collier * copyright notice and this permission notice appear in all copies.
695129044dSC.J. Collier *
705129044dSC.J. Collier * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
715129044dSC.J. Collier * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
725129044dSC.J. Collier * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
735129044dSC.J. Collier * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
745129044dSC.J. Collier * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
755129044dSC.J. Collier * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
765129044dSC.J. Collier * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
775129044dSC.J. Collier * SOFTWARE.
785129044dSC.J. Collier */
795129044dSC.J. Collier
805129044dSC.J. Collier
815129044dSC.J. Collier#include <stdio.h>
825129044dSC.J. Collier#include <stdlib.h>
835129044dSC.J. Collier#include <stdarg.h>
845129044dSC.J. Collier#include <inttypes.h>
855129044dSC.J. Collier#include <ctype.h>
865129044dSC.J. Collier#include <string.h>
875129044dSC.J. Collier#include <errno.h>
885129044dSC.J. Collier#include <netinet/in.h>
895129044dSC.J. Collier#ifndef __linux__
905129044dSC.J. Collier#ifndef __FreeBSD__
915129044dSC.J. Collier#include <net/socket.h>
925129044dSC.J. Collier#else
935129044dSC.J. Collier#include <sys/socket.h>
945129044dSC.J. Collier#endif
955129044dSC.J. Collier#endif
965129044dSC.J. Collier
975129044dSC.J. Collier#include <rte_string_fns.h>
985129044dSC.J. Collier
995129044dSC.J. Collier#include "cmdline_parse.h"
1005129044dSC.J. Collier#include "cmdline_parse_ipaddr.h"
1015129044dSC.J. Collier
1025129044dSC.J. Collierstruct cmdline_token_ops cmdline_token_ipaddr_ops = {
1035129044dSC.J. Collier	.parse = cmdline_parse_ipaddr,
1045129044dSC.J. Collier	.complete_get_nb = NULL,
1055129044dSC.J. Collier	.complete_get_elt = NULL,
1065129044dSC.J. Collier	.get_help = cmdline_get_help_ipaddr,
1075129044dSC.J. Collier};
1085129044dSC.J. Collier
1095129044dSC.J. Collier#define INADDRSZ 4
1105129044dSC.J. Collier#define IN6ADDRSZ 16
1115129044dSC.J. Collier#define PREFIXMAX 128
1125129044dSC.J. Collier#define V4PREFIXMAX 32
1135129044dSC.J. Collier
1145129044dSC.J. Collier/*
1155129044dSC.J. Collier * WARNING: Don't even consider trying to compile this on a system where
1165129044dSC.J. Collier * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
1175129044dSC.J. Collier */
1185129044dSC.J. Collier
1195129044dSC.J. Collierstatic int inet_pton4(const char *src, unsigned char *dst);
1205129044dSC.J. Collierstatic int inet_pton6(const char *src, unsigned char *dst);
1215129044dSC.J. Collier
1225129044dSC.J. Collier/* int
1235129044dSC.J. Collier * inet_pton(af, src, dst)
1245129044dSC.J. Collier *      convert from presentation format (which usually means ASCII printable)
1255129044dSC.J. Collier *      to network format (which is usually some kind of binary format).
1265129044dSC.J. Collier * return:
1275129044dSC.J. Collier *      1 if the address was valid for the specified address family
1285129044dSC.J. Collier *      0 if the address wasn't valid (`dst' is untouched in this case)
1295129044dSC.J. Collier *      -1 if some other error occurred (`dst' is untouched in this case, too)
1305129044dSC.J. Collier * author:
1315129044dSC.J. Collier *      Paul Vixie, 1996.
1325129044dSC.J. Collier */
1335129044dSC.J. Collierstatic int
1345129044dSC.J. Colliermy_inet_pton(int af, const char *src, void *dst)
1355129044dSC.J. Collier{
1365129044dSC.J. Collier	switch (af) {
1375129044dSC.J. Collier		case AF_INET:
1385129044dSC.J. Collier			return inet_pton4(src, dst);
1395129044dSC.J. Collier		case AF_INET6:
1405129044dSC.J. Collier			return inet_pton6(src, dst);
1415129044dSC.J. Collier		default:
1425129044dSC.J. Collier			errno = EAFNOSUPPORT;
1435129044dSC.J. Collier			return -1;
1445129044dSC.J. Collier	}
1455129044dSC.J. Collier	/* NOTREACHED */
1465129044dSC.J. Collier}
1475129044dSC.J. Collier
1485129044dSC.J. Collier/* int
1495129044dSC.J. Collier * inet_pton4(src, dst)
1505129044dSC.J. Collier *      like inet_aton() but without all the hexadecimal and shorthand.
1515129044dSC.J. Collier * return:
1525129044dSC.J. Collier *      1 if `src' is a valid dotted quad, else 0.
1535129044dSC.J. Collier * notice:
1545129044dSC.J. Collier *      does not touch `dst' unless it's returning 1.
1555129044dSC.J. Collier * author:
1565129044dSC.J. Collier *      Paul Vixie, 1996.
1575129044dSC.J. Collier */
1585129044dSC.J. Collierstatic int
1595129044dSC.J. Collierinet_pton4(const char *src, unsigned char *dst)
1605129044dSC.J. Collier{
1615129044dSC.J. Collier	static const char digits[] = "0123456789";
1625129044dSC.J. Collier	int saw_digit, octets, ch;
1635129044dSC.J. Collier	unsigned char tmp[INADDRSZ], *tp;
1645129044dSC.J. Collier
1655129044dSC.J. Collier	saw_digit = 0;
1665129044dSC.J. Collier	octets = 0;
1675129044dSC.J. Collier	*(tp = tmp) = 0;
1685129044dSC.J. Collier	while ((ch = *src++) != '\0') {
1695129044dSC.J. Collier		const char *pch;
1705129044dSC.J. Collier
1715129044dSC.J. Collier		if ((pch = strchr(digits, ch)) != NULL) {
1725129044dSC.J. Collier			unsigned int new = *tp * 10 + (pch - digits);
1735129044dSC.J. Collier
1745129044dSC.J. Collier			if (new > 255)
1755129044dSC.J. Collier				return 0;
1765129044dSC.J. Collier			if (! saw_digit) {
1775129044dSC.J. Collier				if (++octets > 4)
1785129044dSC.J. Collier					return 0;
1795129044dSC.J. Collier				saw_digit = 1;
1805129044dSC.J. Collier			}
1815129044dSC.J. Collier			*tp = (unsigned char)new;
1825129044dSC.J. Collier		} else if (ch == '.' && saw_digit) {
1835129044dSC.J. Collier			if (octets == 4)
1845129044dSC.J. Collier				return 0;
1855129044dSC.J. Collier			*++tp = 0;
1865129044dSC.J. Collier			saw_digit = 0;
1875129044dSC.J. Collier		} else
1885129044dSC.J. Collier			return 0;
1895129044dSC.J. Collier	}
1905129044dSC.J. Collier	if (octets < 4)
1915129044dSC.J. Collier		return 0;
1925129044dSC.J. Collier
1935129044dSC.J. Collier	memcpy(dst, tmp, INADDRSZ);
1945129044dSC.J. Collier	return 1;
1955129044dSC.J. Collier}
1965129044dSC.J. Collier
1975129044dSC.J. Collier/* int
1985129044dSC.J. Collier * inet_pton6(src, dst)
1995129044dSC.J. Collier *      convert presentation level address to network order binary form.
2005129044dSC.J. Collier * return:
2015129044dSC.J. Collier *      1 if `src' is a valid [RFC1884 2.2] address, else 0.
2025129044dSC.J. Collier * notice:
2035129044dSC.J. Collier *      (1) does not touch `dst' unless it's returning 1.
2045129044dSC.J. Collier *      (2) :: in a full address is silently ignored.
2055129044dSC.J. Collier * credit:
2065129044dSC.J. Collier *      inspired by Mark Andrews.
2075129044dSC.J. Collier * author:
2085129044dSC.J. Collier *      Paul Vixie, 1996.
2095129044dSC.J. Collier */
2105129044dSC.J. Collierstatic int
2115129044dSC.J. Collierinet_pton6(const char *src, unsigned char *dst)
2125129044dSC.J. Collier{
2135129044dSC.J. Collier	static const char xdigits_l[] = "0123456789abcdef",
2145129044dSC.J. Collier		xdigits_u[] = "0123456789ABCDEF";
2155129044dSC.J. Collier	unsigned char tmp[IN6ADDRSZ], *tp = 0, *endp = 0, *colonp = 0;
2165129044dSC.J. Collier	const char *xdigits = 0, *curtok = 0;
2175129044dSC.J. Collier	int ch = 0, saw_xdigit = 0, count_xdigit = 0;
2185129044dSC.J. Collier	unsigned int val = 0;
2195129044dSC.J. Collier	unsigned dbloct_count = 0;
2205129044dSC.J. Collier
2215129044dSC.J. Collier	memset((tp = tmp), '\0', IN6ADDRSZ);
2225129044dSC.J. Collier	endp = tp + IN6ADDRSZ;
2235129044dSC.J. Collier	colonp = NULL;
2245129044dSC.J. Collier	/* Leading :: requires some special handling. */
2255129044dSC.J. Collier	if (*src == ':')
2265129044dSC.J. Collier		if (*++src != ':')
2275129044dSC.J. Collier			return 0;
2285129044dSC.J. Collier	curtok = src;
2295129044dSC.J. Collier	saw_xdigit = count_xdigit = 0;
2305129044dSC.J. Collier	val = 0;
2315129044dSC.J. Collier
2325129044dSC.J. Collier	while ((ch = *src++) != '\0') {
2335129044dSC.J. Collier		const char *pch;
2345129044dSC.J. Collier
2355129044dSC.J. Collier		if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
2365129044dSC.J. Collier			pch = strchr((xdigits = xdigits_u), ch);
2375129044dSC.J. Collier		if (pch != NULL) {
2385129044dSC.J. Collier			if (count_xdigit >= 4)
2395129044dSC.J. Collier				return 0;
2405129044dSC.J. Collier			val <<= 4;
2415129044dSC.J. Collier			val |= (pch - xdigits);
2425129044dSC.J. Collier			if (val > 0xffff)
2435129044dSC.J. Collier				return 0;
2445129044dSC.J. Collier			saw_xdigit = 1;
2455129044dSC.J. Collier			count_xdigit++;
2465129044dSC.J. Collier			continue;
2475129044dSC.J. Collier		}
2485129044dSC.J. Collier		if (ch == ':') {
2495129044dSC.J. Collier			curtok = src;
2505129044dSC.J. Collier			if (!saw_xdigit) {
2515129044dSC.J. Collier				if (colonp)
2525129044dSC.J. Collier					return 0;
2535129044dSC.J. Collier				colonp = tp;
2545129044dSC.J. Collier				continue;
2555129044dSC.J. Collier			} else if (*src == '\0') {
2565129044dSC.J. Collier				return 0;
2575129044dSC.J. Collier			}
2585129044dSC.J. Collier			if (tp + sizeof(int16_t) > endp)
2595129044dSC.J. Collier				return 0;
2605129044dSC.J. Collier			*tp++ = (unsigned char) ((val >> 8) & 0xff);
2615129044dSC.J. Collier			*tp++ = (unsigned char) (val & 0xff);
2625129044dSC.J. Collier			saw_xdigit = 0;
2635129044dSC.J. Collier			count_xdigit = 0;
2645129044dSC.J. Collier			val = 0;
2655129044dSC.J. Collier			dbloct_count++;
2665129044dSC.J. Collier			continue;
2675129044dSC.J. Collier		}
2685129044dSC.J. Collier		if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
2695129044dSC.J. Collier		    inet_pton4(curtok, tp) > 0) {
2705129044dSC.J. Collier			tp += INADDRSZ;
2715129044dSC.J. Collier			saw_xdigit = 0;
2725129044dSC.J. Collier			dbloct_count += 2;
2735129044dSC.J. Collier			break;  /* '\0' was seen by inet_pton4(). */
2745129044dSC.J. Collier		}
2755129044dSC.J. Collier		return 0;
2765129044dSC.J. Collier	}
2775129044dSC.J. Collier	if (saw_xdigit) {
2785129044dSC.J. Collier		if (tp + sizeof(int16_t) > endp)
2795129044dSC.J. Collier			return 0;
2805129044dSC.J. Collier		*tp++ = (unsigned char) ((val >> 8) & 0xff);
2815129044dSC.J. Collier		*tp++ = (unsigned char) (val & 0xff);
2825129044dSC.J. Collier		dbloct_count++;
2835129044dSC.J. Collier	}
2845129044dSC.J. Collier	if (colonp != NULL) {
2855129044dSC.J. Collier		/* if we already have 8 double octets, having a colon means error */
2865129044dSC.J. Collier		if (dbloct_count == 8)
2875129044dSC.J. Collier			return 0;
2885129044dSC.J. Collier
2895129044dSC.J. Collier		/*
2905129044dSC.J. Collier		 * Since some memmove()'s erroneously fail to handle
2915129044dSC.J. Collier		 * overlapping regions, we'll do the shift by hand.
2925129044dSC.J. Collier		 */
2935129044dSC.J. Collier		const int n = tp - colonp;
2945129044dSC.J. Collier		int i;
2955129044dSC.J. Collier
2965129044dSC.J. Collier		for (i = 1; i <= n; i++) {
2975129044dSC.J. Collier			endp[- i] = colonp[n - i];
2985129044dSC.J. Collier			colonp[n - i] = 0;
2995129044dSC.J. Collier		}
3005129044dSC.J. Collier		tp = endp;
3015129044dSC.J. Collier	}
3025129044dSC.J. Collier	if (tp != endp)
3035129044dSC.J. Collier		return 0;
3045129044dSC.J. Collier	memcpy(dst, tmp, IN6ADDRSZ);
3055129044dSC.J. Collier	return 1;
3065129044dSC.J. Collier}
3075129044dSC.J. Collier
3085129044dSC.J. Collierint
3095129044dSC.J. Colliercmdline_parse_ipaddr(cmdline_parse_token_hdr_t *tk, const char *buf, void *res,
3105129044dSC.J. Collier	unsigned ressize)
3115129044dSC.J. Collier{
3125129044dSC.J. Collier	struct cmdline_token_ipaddr *tk2;
3135129044dSC.J. Collier	unsigned int token_len = 0;
3145129044dSC.J. Collier	char ip_str[INET6_ADDRSTRLEN+4+1]; /* '+4' is for prefixlen (if any) */
3155129044dSC.J. Collier	cmdline_ipaddr_t ipaddr;
3165129044dSC.J. Collier	char *prefix, *prefix_end;
3175129044dSC.J. Collier	long prefixlen = 0;
3185129044dSC.J. Collier
3195129044dSC.J. Collier	if (res && ressize < sizeof(cmdline_ipaddr_t))
3205129044dSC.J. Collier		return -1;
3215129044dSC.J. Collier
3225129044dSC.J. Collier	if (!buf || !tk || ! *buf)
3235129044dSC.J. Collier		return -1;
3245129044dSC.J. Collier
3255129044dSC.J. Collier	tk2 = (struct cmdline_token_ipaddr *)tk;
3265129044dSC.J. Collier
3275129044dSC.J. Collier	while (!cmdline_isendoftoken(buf[token_len]))
3285129044dSC.J. Collier		token_len++;
3295129044dSC.J. Collier
3305129044dSC.J. Collier	/* if token is too big... */
3315129044dSC.J. Collier	if (token_len >= INET6_ADDRSTRLEN+4)
3325129044dSC.J. Collier		return -1;
3335129044dSC.J. Collier
3345129044dSC.J. Collier	snprintf(ip_str, token_len+1, "%s", buf);
3355129044dSC.J. Collier
3365129044dSC.J. Collier	/* convert the network prefix */
3375129044dSC.J. Collier	if (tk2->ipaddr_data.flags & CMDLINE_IPADDR_NETWORK) {
3385129044dSC.J. Collier		prefix = strrchr(ip_str, '/');
3395129044dSC.J. Collier		if (prefix == NULL)
3405129044dSC.J. Collier			return -1;
3415129044dSC.J. Collier		*prefix = '\0';
3425129044dSC.J. Collier		prefix ++;
3435129044dSC.J. Collier		errno = 0;
3445129044dSC.J. Collier		prefixlen = strtol(prefix, &prefix_end, 10);
3455129044dSC.J. Collier		if (errno || (*prefix_end != '\0')
3465129044dSC.J. Collier			|| prefixlen < 0 || prefixlen > PREFIXMAX)
3475129044dSC.J. Collier			return -1;
3485129044dSC.J. Collier		ipaddr.prefixlen = prefixlen;
3495129044dSC.J. Collier	}
3505129044dSC.J. Collier	else {
3515129044dSC.J. Collier		ipaddr.prefixlen = 0;
3525129044dSC.J. Collier	}
3535129044dSC.J. Collier
3545129044dSC.J. Collier	/* convert the IP addr */
3555129044dSC.J. Collier	if ((tk2->ipaddr_data.flags & CMDLINE_IPADDR_V4) &&
3565129044dSC.J. Collier	    my_inet_pton(AF_INET, ip_str, &ipaddr.addr.ipv4) == 1 &&
3575129044dSC.J. Collier		prefixlen <= V4PREFIXMAX) {
3585129044dSC.J. Collier		ipaddr.family = AF_INET;
3595129044dSC.J. Collier		if (res)
3605129044dSC.J. Collier			memcpy(res, &ipaddr, sizeof(ipaddr));
3615129044dSC.J. Collier		return token_len;
3625129044dSC.J. Collier	}
3635129044dSC.J. Collier	if ((tk2->ipaddr_data.flags & CMDLINE_IPADDR_V6) &&
3645129044dSC.J. Collier	    my_inet_pton(AF_INET6, ip_str, &ipaddr.addr.ipv6) == 1) {
3655129044dSC.J. Collier		ipaddr.family = AF_INET6;
3665129044dSC.J. Collier		if (res)
3675129044dSC.J. Collier			memcpy(res, &ipaddr, sizeof(ipaddr));
3685129044dSC.J. Collier		return token_len;
3695129044dSC.J. Collier	}
3705129044dSC.J. Collier	return -1;
3715129044dSC.J. Collier
3725129044dSC.J. Collier}
3735129044dSC.J. Collier
3745129044dSC.J. Collierint cmdline_get_help_ipaddr(cmdline_parse_token_hdr_t *tk, char *dstbuf,
3755129044dSC.J. Collier			    unsigned int size)
3765129044dSC.J. Collier{
3775129044dSC.J. Collier	struct cmdline_token_ipaddr *tk2;
3785129044dSC.J. Collier
3795129044dSC.J. Collier	if (!tk || !dstbuf)
3805129044dSC.J. Collier		return -1;
3815129044dSC.J. Collier
3825129044dSC.J. Collier	tk2 = (struct cmdline_token_ipaddr *)tk;
3835129044dSC.J. Collier
3845129044dSC.J. Collier	switch (tk2->ipaddr_data.flags) {
3855129044dSC.J. Collier	case CMDLINE_IPADDR_V4:
3865129044dSC.J. Collier		snprintf(dstbuf, size, "IPv4");
3875129044dSC.J. Collier		break;
3885129044dSC.J. Collier	case CMDLINE_IPADDR_V6:
3895129044dSC.J. Collier		snprintf(dstbuf, size, "IPv6");
3905129044dSC.J. Collier		break;
3915129044dSC.J. Collier	case CMDLINE_IPADDR_V4|CMDLINE_IPADDR_V6:
3925129044dSC.J. Collier		snprintf(dstbuf, size, "IPv4/IPv6");
3935129044dSC.J. Collier		break;
3945129044dSC.J. Collier	case CMDLINE_IPADDR_NETWORK|CMDLINE_IPADDR_V4:
3955129044dSC.J. Collier		snprintf(dstbuf, size, "IPv4 network");
3965129044dSC.J. Collier		break;
3975129044dSC.J. Collier	case CMDLINE_IPADDR_NETWORK|CMDLINE_IPADDR_V6:
3985129044dSC.J. Collier		snprintf(dstbuf, size, "IPv6 network");
3995129044dSC.J. Collier		break;
4005129044dSC.J. Collier	case CMDLINE_IPADDR_NETWORK|CMDLINE_IPADDR_V4|CMDLINE_IPADDR_V6:
4015129044dSC.J. Collier		snprintf(dstbuf, size, "IPv4/IPv6 network");
4025129044dSC.J. Collier		break;
4035129044dSC.J. Collier	default:
4045129044dSC.J. Collier		snprintf(dstbuf, size, "IPaddr (bad flags)");
4055129044dSC.J. Collier		break;
4065129044dSC.J. Collier	}
4075129044dSC.J. Collier	return 0;
4085129044dSC.J. Collier}
409