176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @file
376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This is the IPv4 address tools implementation.
476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/*
876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Copyright (c) 2001-2004 Swedish Institute of Computer Science.
976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * All rights reserved.
1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Redistribution and use in source and binary forms, with or without modification,
1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * are permitted provided that the following conditions are met:
1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 1. Redistributions of source code must retain the above copyright notice,
1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *    this list of conditions and the following disclaimer.
1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 2. Redistributions in binary form must reproduce the above copyright notice,
1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *    this list of conditions and the following disclaimer in the documentation
1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *    and/or other materials provided with the distribution.
1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 3. The name of the author may not be used to endorse or promote products
2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *    derived from this software without specific prior written permission.
2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * OF SUCH DAMAGE.
3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This file is part of the lwIP TCP/IP stack.
3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Author: Adam Dunkels <adam@sics.se>
3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "lwip/opt.h"
4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "lwip/ip_addr.h"
4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include "lwip/netif.h"
4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* used by IP_ADDR_ANY and IP_ADDR_BROADCAST in ip_addr.h */
4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanconst ip_addr_t ip_addr_any = { IPADDR_ANY };
4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanconst ip_addr_t ip_addr_broadcast = { IPADDR_BROADCAST };
4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Determine if an address is a broadcast address on a network interface
4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @param addr address to be checked
5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @param netif the network interface against which the address is checked
5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @return returns non-zero if the address is a broadcast address
5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanu8_t
5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanip4_addr_isbroadcast(u32_t addr, const struct netif *netif)
5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ip_addr_t ipaddr;
5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ip4_addr_set_u32(&ipaddr, addr);
5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /* all ones (broadcast) or all zeroes (old skool broadcast) */
6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if ((~addr == IPADDR_ANY) ||
6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      (addr == IPADDR_ANY)) {
6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return 1;
6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /* no broadcast support on this network interface? */
6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  } else if ((netif->flags & NETIF_FLAG_BROADCAST) == 0) {
6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* the given address cannot be a broadcast address
6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     * nor can we check against any broadcast addresses */
6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return 0;
6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /* address matches network interface address exactly? => no broadcast */
7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  } else if (addr == ip4_addr_get_u32(&netif->ip_addr)) {
7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return 0;
7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /*  on the same (sub) network... */
7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  } else if (ip_addr_netcmp(&ipaddr, &(netif->ip_addr), &(netif->netmask))
7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman         /* ...and host identifier bits are all ones? =>... */
7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman          && ((addr & ~ip4_addr_get_u32(&netif->netmask)) ==
7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman           (IPADDR_BROADCAST & ~ip4_addr_get_u32(&netif->netmask)))) {
7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /* => network broadcast address */
7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return 1;
7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  } else {
8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return 0;
8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** Checks if a netmask is valid (starting with ones, then only zeros)
8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @param netmask the IPv4 netmask to check (in network byte order!)
8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @return 1 if the netmask is valid, 0 if it is not
8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanu8_t
9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanip4_addr_netmask_valid(u32_t netmask)
9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u32_t mask;
9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u32_t nm_hostorder = lwip_htonl(netmask);
9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /* first, check for the first zero */
9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  for (mask = 1UL << 31 ; mask != 0; mask >>= 1) {
9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if ((nm_hostorder & mask) == 0) {
9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      break;
9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /* then check that there is no one */
10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  for (; mask != 0; mask >>= 1) {
10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if ((nm_hostorder & mask) != 0) {
10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /* there is a one after the first zero -> invalid */
10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return 0;
10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /* no one after the first zero -> valid */
10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return 1;
11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Here for now until needed in other places in lwIP */
11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#ifndef isprint
11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define in_range(c, lo, up)  ((u8_t)c >= lo && (u8_t)c <= up)
11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define isprint(c)           in_range(c, 0x20, 0x7f)
11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define isdigit(c)           in_range(c, '0', '9')
11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define isxdigit(c)          (isdigit(c) || in_range(c, 'a', 'f') || in_range(c, 'A', 'F'))
11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define islower(c)           in_range(c, 'a', 'z')
11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define isspace(c)           (c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == '\v')
12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#endif
12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Ascii internet address interpretation routine.
12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * The value returned is in network order.
12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @param cp IP address in ascii represenation (e.g. "127.0.0.1")
12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @return ip address in network order
12876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
12976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanu32_t
13076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanipaddr_addr(const char *cp)
13176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
13276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ip_addr_t val;
13376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
13476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (ipaddr_aton(cp, &val)) {
13576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return ip4_addr_get_u32(&val);
13676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
13776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return (IPADDR_NONE);
13876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
13976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
14076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
14176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Check whether "cp" is a valid ascii representation
14276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * of an Internet address and convert to a binary address.
14376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Returns 1 if the address is valid, 0 if not.
14476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This replaces inet_addr, the return value from which
14576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * cannot distinguish between failure and a local broadcast address.
14676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
14776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @param cp IP address in ascii represenation (e.g. "127.0.0.1")
14876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @param addr pointer to which to save the ip address in network order
14976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @return 1 if cp could be converted to addr, 0 on failure
15076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
15176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint
15276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanipaddr_aton(const char *cp, ip_addr_t *addr)
15376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
15476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u32_t val;
15576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u8_t base;
15676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  char c;
15776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u32_t parts[4];
15876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u32_t *pp = parts;
15976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
16076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  c = *cp;
16176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  for (;;) {
16276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    /*
16376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     * Collect number up to ``.''.
16476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     * Values are specified as for C:
16576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     * 0x=hex, 0=octal, 1-9=decimal.
16676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman     */
16776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (!isdigit(c))
16876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return (0);
16976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    val = 0;
17076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    base = 10;
17176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (c == '0') {
17276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      c = *++cp;
17376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (c == 'x' || c == 'X') {
17476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        base = 16;
17576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        c = *++cp;
17676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      } else
17776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        base = 8;
17876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
17976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    for (;;) {
18076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (isdigit(c)) {
18176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        val = (val * base) + (int)(c - '0');
18276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        c = *++cp;
18376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      } else if (base == 16 && isxdigit(c)) {
18476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        val = (val << 4) | (int)(c + 10 - (islower(c) ? 'a' : 'A'));
18576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        c = *++cp;
18676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      } else
18776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        break;
18876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
18976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (c == '.') {
19076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      /*
19176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       * Internet format:
19276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       *  a.b.c.d
19376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       *  a.b.c   (with c treated as 16 bits)
19476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       *  a.b (with b treated as 24 bits)
19576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman       */
19676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (pp >= parts + 3) {
19776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        return (0);
19876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
19976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      *pp++ = val;
20076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      c = *++cp;
20176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } else
20276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      break;
20376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
20476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /*
20576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * Check for trailing characters.
20676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   */
20776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (c != '\0' && !isspace(c)) {
20876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return (0);
20976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
21076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  /*
21176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * Concoct the address according to
21276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   * the number of parts specified.
21376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman   */
21476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  switch (pp - parts + 1) {
21576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
21676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  case 0:
21776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    return (0);       /* initial nondigit */
21876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
21976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  case 1:             /* a -- 32 bits */
22076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    break;
22176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
22276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  case 2:             /* a.b -- 8.24 bits */
22376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (val > 0xffffffUL) {
22476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return (0);
22576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
22676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    val |= parts[0] << 24;
22776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    break;
22876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
22976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  case 3:             /* a.b.c -- 8.8.16 bits */
23076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (val > 0xffff) {
23176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return (0);
23276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
23376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    val |= (parts[0] << 24) | (parts[1] << 16);
23476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    break;
23576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
23676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  case 4:             /* a.b.c.d -- 8.8.8.8 bits */
23776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (val > 0xff) {
23876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return (0);
23976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
24076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
24176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    break;
24276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  default:
24376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    LWIP_ASSERT("unhandled", 0);
24476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    break;
24576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
24676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  if (addr) {
24776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ip4_addr_set_u32(addr, htonl(val));
24876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
24976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return (1);
25076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
25176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
25276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
25376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Convert numeric IP address into decimal dotted ASCII representation.
25476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * returns ptr to static buffer; not reentrant!
25576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
25676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @param addr ip address in network order to convert
25776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @return pointer to a global static (!) buffer that holds the ASCII
25876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *         represenation of addr
25976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
26076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanchar *
26176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanipaddr_ntoa(const ip_addr_t *addr)
26276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
26376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  static char str[16];
26476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return ipaddr_ntoa_r(addr, str, 16);
26576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
26676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
26776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/**
26876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Same as ipaddr_ntoa, but reentrant since a user-supplied buffer is used.
26976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *
27076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @param addr ip address in network order to convert
27176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @param buf target buffer where the string is stored
27276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @param buflen length of buf
27376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @return either pointer to buf which now holds the ASCII
27476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *         representation of addr or NULL if buf was too small
27576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */
27676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanchar *ipaddr_ntoa_r(const ip_addr_t *addr, char *buf, int buflen)
27776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{
27876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u32_t s_addr;
27976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  char inv[3];
28076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  char *rp;
28176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u8_t *ap;
28276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u8_t rem;
28376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u8_t n;
28476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  u8_t i;
28576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  int len = 0;
28676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
28776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  s_addr = ip4_addr_get_u32(addr);
28876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman
28976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  rp = buf;
29076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  ap = (u8_t *)&s_addr;
29176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  for(n = 0; n < 4; n++) {
29276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    i = 0;
29376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    do {
29476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      rem = *ap % (u8_t)10;
29576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      *ap /= (u8_t)10;
29676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      inv[i++] = '0' + rem;
29776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    } while(*ap);
29876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    while(i--) {
29976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      if (len++ >= buflen) {
30076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman        return NULL;
30176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      }
30276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      *rp++ = inv[i];
30376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
30476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    if (len++ >= buflen) {
30576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman      return NULL;
30676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    }
30776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    *rp++ = '.';
30876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman    ap++;
30976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  }
31076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  *--rp = 0;
31176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman  return buf;
31276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}
313