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