Logo Search packages:      
Sourcecode: libnl2 version File versions  Download package

int nl_addr_parse ( const char *  addrstr,
int  hint,
struct nl_addr **  result 
)

Allocate abstract address object based on a character string

  • addrstr Address represented as character string.
  • hint Address family hint or AF_UNSPEC.
  • result Pointer to store resulting address.

Regognizes the following address formats:

  Format                      Len                Family
  ----------------------------------------------------------------
  IPv6 address format         16                 AF_INET6
  ddd.ddd.ddd.ddd             4                  AF_INET
  HH:HH:HH:HH:HH:HH           6                  AF_LLC
  AA{.|,}NNNN                 2                  AF_DECnet
  HH:HH:HH:...                variable           AF_UNSPEC

Special values:

  • none: All bits and length set to 0.
  • {default|all|any}: All bits set to 0, length based on hint or AF_INET if no hint is given.

The prefix length may be appened at the end prefixed with a slash, e.g. 10.0.0.0/8.

Returns:
0 on success or a negative error code.

Definition at line 245 of file addr.c.

References nl_addr_alloc(), nl_addr_destroy(), and nl_addr_set_binary_addr().

{
      int err, copy = 0, len = 0, family = AF_UNSPEC;
      char *str, *prefix, buf[32];
      struct nl_addr *addr = NULL; /* gcc ain't that smart */

      str = strdup(addrstr);
      if (!str) {
            err = -NLE_NOMEM;
            goto errout;
      }

      prefix = strchr(str, '/');
      if (prefix)
            *prefix = '\0';

      if (!strcasecmp(str, "none")) {
            family = hint;
            goto prefix;
      }

      if (!strcasecmp(str, "default") ||
          !strcasecmp(str, "all") ||
          !strcasecmp(str, "any")) {
                  
            switch (hint) {
                  case AF_INET:
                  case AF_UNSPEC:
                        /* Kind of a hack, we assume that if there is
                         * no hint given the user wants to have a IPv4
                         * address given back. */
                        family = AF_INET;
                        len = 4;
                        goto prefix;

                  case AF_INET6:
                        family = AF_INET6;
                        len = 16;
                        goto prefix;

                  case AF_LLC:
                        family = AF_LLC;
                        len = 6;
                        goto prefix;

                  default:
                        err = -NLE_AF_NOSUPPORT;
                        goto errout;
            }
      }

      copy = 1;

      if (hint == AF_INET || hint == AF_UNSPEC) {
            if (inet_pton(AF_INET, str, buf) > 0) {
                  family = AF_INET;
                  len = 4;
                  goto prefix;
            }
            if (hint == AF_INET) {
                  err = -NLE_NOADDR;
                  goto errout;
            }
      }

      if (hint == AF_INET6 || hint == AF_UNSPEC) {
            if (inet_pton(AF_INET6, str, buf) > 0) {
                  family = AF_INET6;
                  len = 16;
                  goto prefix;
            }
            if (hint == AF_INET6) {
                  err = -NLE_NOADDR;
                  goto errout;
            }
      }

      if ((hint == AF_LLC || hint == AF_UNSPEC) && strchr(str, ':')) {
            unsigned int a, b, c, d, e, f;

            if (sscanf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
                &a, &b, &c, &d, &e, &f) == 6) {
                  family = AF_LLC;
                  len = 6;
                  buf[0] = (unsigned char) a;
                  buf[1] = (unsigned char) b;
                  buf[2] = (unsigned char) c;
                  buf[3] = (unsigned char) d;
                  buf[4] = (unsigned char) e;
                  buf[5] = (unsigned char) f;
                  goto prefix;
            }

            if (hint == AF_LLC) {
                  err = -NLE_NOADDR;
                  goto errout;
            }
      }

      if ((hint == AF_DECnet || hint == AF_UNSPEC) &&
          (strchr(str, '.') || strchr(str, ','))) {
            if (dnet_pton(str, buf) > 0) {
                  family = AF_DECnet;
                  len = 2;
                  goto prefix;
            }
            if (hint == AF_DECnet) {
                  err = -NLE_NOADDR;
                  goto errout;
            }
      }

      if (hint == AF_UNSPEC && strchr(str, ':')) {
            int i = 0;
            char *s = str, *p;
            for (;;) {
                  long l = strtol(s, &p, 16);

                  if (s == p || l > 0xff || i >= sizeof(buf)) {
                        err = -NLE_INVAL;
                        goto errout;
                  }

                  buf[i++] = (unsigned char) l;
                  if (*p == '\0')
                        break;
                  s = ++p;
            }

            len = i;
            family = AF_UNSPEC;
            goto prefix;
      }

      err = -NLE_NOADDR;
      goto errout;

prefix:
      addr = nl_addr_alloc(len);
      if (!addr) {
            err = -NLE_NOMEM;
            goto errout;
      }

      nl_addr_set_family(addr, family);

      if (copy)
            nl_addr_set_binary_addr(addr, buf, len);

      if (prefix) {
            char *p;
            long pl = strtol(++prefix, &p, 0);
            if (p == prefix) {
                  nl_addr_destroy(addr);
                  err = -NLE_INVAL;
                  goto errout;
            }
            nl_addr_set_prefixlen(addr, pl);
      } else
            nl_addr_set_prefixlen(addr, len * 8);

      *result = addr;
      err = 0;
errout:
      free(str);

      return err;
}

Here is the call graph for this function:


Generated by  Doxygen 1.6.0   Back to index