ncpaddr.c revision 113110
181634Sbrian/*-
281634Sbrian * Copyright (c) 2001 Brian Somers <brian@Awfulhak.org>
381634Sbrian * All rights reserved.
481634Sbrian *
581634Sbrian * Redistribution and use in source and binary forms, with or without
681634Sbrian * modification, are permitted provided that the following conditions
781634Sbrian * are met:
881634Sbrian * 1. Redistributions of source code must retain the above copyright
981634Sbrian *    notice, this list of conditions and the following disclaimer.
1081634Sbrian * 2. Redistributions in binary form must reproduce the above copyright
1181634Sbrian *    notice, this list of conditions and the following disclaimer in the
1281634Sbrian *    documentation and/or other materials provided with the distribution.
1381634Sbrian *
1481634Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1581634Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1681634Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1781634Sbrian * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1881634Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1981634Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2081634Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2181634Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2281634Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2381634Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2481634Sbrian * SUCH DAMAGE.
2581634Sbrian *
2681634Sbrian * $FreeBSD: head/usr.sbin/ppp/ncpaddr.c 113110 2003-04-05 10:10:33Z ume $
2781634Sbrian */
2881634Sbrian
2981634Sbrian#include <sys/types.h>
3081634Sbrian#include <sys/socket.h>
3196732Sbrian#ifdef __OpenBSD__
3296732Sbrian#include <net/if_types.h>
3396732Sbrian#include <net/route.h>
3496732Sbrian#endif
3581634Sbrian#include <netinet/in.h>
3681634Sbrian#include <netinet/in_systm.h>
3781634Sbrian#include <netinet/ip.h>
3881634Sbrian#include <arpa/inet.h>
3981634Sbrian#include <sys/un.h>
4081634Sbrian
4181634Sbrian#include <netdb.h>
4281634Sbrian#include <stdio.h>
4381634Sbrian#include <stdlib.h>
4481634Sbrian#include <string.h>
4581634Sbrian#include <termios.h>
4681634Sbrian
4781634Sbrian#include "log.h"
4881634Sbrian#include "ncpaddr.h"
4981634Sbrian#include "timer.h"
5081634Sbrian#include "fsm.h"
5181634Sbrian#include "defs.h"
5281634Sbrian#include "slcompress.h"
5381634Sbrian#include "iplist.h"
5481634Sbrian#include "throughput.h"
5581634Sbrian#include "mbuf.h"
5681634Sbrian#include "ipcp.h"
5781634Sbrian#include "descriptor.h"
5881634Sbrian#include "layer.h"
5981634Sbrian#include "lqr.h"
6081634Sbrian#include "hdlc.h"
6181634Sbrian#include "lcp.h"
6281634Sbrian#include "ccp.h"
6381634Sbrian#include "link.h"
6481634Sbrian#include "mp.h"
6581634Sbrian#include "ipv6cp.h"
6681634Sbrian#include "ncp.h"
6781634Sbrian
6881634Sbrian
6981634Sbrian#define ncprange_ip4addr	u.ip4.ipaddr
7081634Sbrian#define ncprange_ip4mask	u.ip4.mask
7181634Sbrian#define ncprange_ip4width	u.ip4.width
7281634Sbrian#define ncpaddr_ip4addr		u.ip4addr
7381634Sbrian#ifndef NOINET6
7481634Sbrian#define ncprange_ip6addr	u.ip6.ipaddr
7581634Sbrian#define ncprange_ip6width	u.ip6.width
7681634Sbrian#define ncpaddr_ip6addr		u.ip6addr
7781634Sbrian#endif
7881634Sbrian
7981634Sbrian#define	NCP_ASCIIBUFFERSIZE	52
8081634Sbrian
8181634Sbrianstatic struct in_addr
8281634Sbrianbits2mask4(int bits)
8381634Sbrian{
8481634Sbrian  struct in_addr result;
8581634Sbrian  u_int32_t bit = 0x80000000;
8681634Sbrian
8781634Sbrian  result.s_addr = 0;
8881634Sbrian
8981634Sbrian  while (bits) {
9081634Sbrian    result.s_addr |= bit;
9181634Sbrian    bit >>= 1;
9281634Sbrian    bits--;
9381634Sbrian  }
9481634Sbrian
9581634Sbrian  result.s_addr = htonl(result.s_addr);
9681634Sbrian  return result;
9781634Sbrian}
9881634Sbrian
9981634Sbrianstatic int
10081634Sbrianmask42bits(struct in_addr mask)
10181634Sbrian{
10281634Sbrian  u_int32_t msk = ntohl(mask.s_addr);
10381634Sbrian  u_int32_t tst;
10481634Sbrian  int ret;
10581634Sbrian
10681634Sbrian  for (ret = 32, tst = 1; tst; ret--, tst <<= 1)
10781634Sbrian    if (msk & tst)
10881634Sbrian      break;
10981634Sbrian
11081634Sbrian  for (tst <<= 1; tst; tst <<= 1)
11181634Sbrian    if (!(msk & tst))
11281634Sbrian      break;
11381634Sbrian
11481634Sbrian  return tst ? -1 : ret;
11581634Sbrian}
11681634Sbrian
11781634Sbrian#ifndef NOINET6
11881634Sbrianstatic struct in6_addr
11981634Sbrianbits2mask6(int bits)
12081634Sbrian{
12181634Sbrian  struct in6_addr result;
12281634Sbrian  u_int32_t bit = 0x80;
12381634Sbrian  u_char *c = result.s6_addr;
12481634Sbrian
12581634Sbrian  memset(&result, '\0', sizeof result);
12681634Sbrian
12781634Sbrian  while (bits) {
12881634Sbrian    if (bit == 0) {
12981634Sbrian      bit = 0x80;
13081634Sbrian      c++;
13181634Sbrian    }
13281634Sbrian    *c |= bit;
13381634Sbrian    bit >>= 1;
13481634Sbrian    bits--;
13581634Sbrian  }
13681634Sbrian
13781634Sbrian  return result;
13881634Sbrian}
13981634Sbrian
14081634Sbrianstatic int
14181634Sbrianmask62bits(const struct in6_addr *mask)
14281634Sbrian{
14381634Sbrian  const u_char masks[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
14481634Sbrian  const u_char *c, *p, *end;
14581634Sbrian  int masklen;
14681634Sbrian
14781634Sbrian  p = (const u_char *)mask;
14881634Sbrian  for (masklen = 0, end = p + 16; p < end && *p == 0xff; p++)
14981634Sbrian    masklen += 8;
15081634Sbrian
15181634Sbrian  if (p < end) {
15281634Sbrian    for (c = masks; c < masks + sizeof masks; c++)
15381634Sbrian      if (*c == *p) {
15481634Sbrian        masklen += c - masks;
15581634Sbrian        break;
15681634Sbrian      }
15781634Sbrian  }
15881634Sbrian
15981634Sbrian  return masklen;
16081634Sbrian}
16181634Sbrian
16281634Sbrianstatic void
16381634Sbrianadjust_linklocal(struct sockaddr_in6 *sin6)
16481634Sbrian{
16581634Sbrian    /* XXX: ?????!?!?!!!!!  This is horrible ! */
166102558Sbrian#if 0
167102558Sbrian    /*
168102558Sbrian     * The kernel does not understand sin6_scope_id for routing at this moment.
169102558Sbrian     * We should rather keep the embedded ID.
170102558Sbrian     * jinmei@kame.net, 20011026
171102558Sbrian     */
17281634Sbrian    if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) ||
17381634Sbrian        IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr)) {
17481634Sbrian      sin6->sin6_scope_id =
17581634Sbrian        ntohs(*(u_short *)&sin6->sin6_addr.s6_addr[2]);
17681634Sbrian      *(u_short *)&sin6->sin6_addr.s6_addr[2] = 0;
17781634Sbrian    }
178102558Sbrian#endif
17981634Sbrian}
18081634Sbrian#endif
18181634Sbrian
18281634Sbrianvoid
18381634Sbrianncpaddr_init(struct ncpaddr *addr)
18481634Sbrian{
18581634Sbrian  addr->ncpaddr_family = AF_UNSPEC;
18681634Sbrian}
18781634Sbrian
18881634Sbrianint
18981739Sbrianncpaddr_isset(const struct ncpaddr *addr)
19081739Sbrian{
19181739Sbrian  return addr->ncpaddr_family != AF_UNSPEC;
19281739Sbrian}
19381739Sbrian
19481739Sbrianint
19581634Sbrianncpaddr_isdefault(const struct ncpaddr *addr)
19681634Sbrian{
19781634Sbrian  switch (addr->ncpaddr_family) {
19881634Sbrian  case AF_INET:
19981634Sbrian    if (addr->ncpaddr_ip4addr.s_addr == INADDR_ANY)
20081634Sbrian      return 1;
20181634Sbrian    break;
20281634Sbrian
20381634Sbrian#ifndef NOINET6
20481634Sbrian  case AF_INET6:
20581634Sbrian    if (IN6_IS_ADDR_UNSPECIFIED(&addr->ncpaddr_ip6addr))
20681634Sbrian      return 1;
20781634Sbrian    break;
20881634Sbrian#endif
20981634Sbrian  }
21081634Sbrian
21181634Sbrian  return 0;
21281634Sbrian}
21381634Sbrian
21481634Sbrianint
21581634Sbrianncpaddr_equal(const struct ncpaddr *addr, const struct ncpaddr *cmp)
21681634Sbrian{
21781634Sbrian  if (addr->ncpaddr_family != cmp->ncpaddr_family)
21881634Sbrian    return 0;
21981634Sbrian
22081634Sbrian  switch (addr->ncpaddr_family) {
22181634Sbrian  case AF_INET:
22281634Sbrian    return addr->ncpaddr_ip4addr.s_addr == cmp->ncpaddr_ip4addr.s_addr;
22381634Sbrian
22481634Sbrian#ifndef NOINET6
22581634Sbrian  case AF_INET6:
22681634Sbrian    return !memcmp(&addr->ncpaddr_ip6addr, &cmp->ncpaddr_ip6addr,
22781634Sbrian                   sizeof addr->ncpaddr_ip6addr);
22881634Sbrian#endif
22981634Sbrian
23081634Sbrian  case AF_UNSPEC:
23181634Sbrian    return 1;
23281634Sbrian  }
23381634Sbrian
23481634Sbrian  return 0;
23581634Sbrian}
23681634Sbrian
23781634Sbrianvoid
23881634Sbrianncpaddr_copy(struct ncpaddr *addr, const struct ncpaddr *from)
23981634Sbrian{
24081634Sbrian  switch (from->ncpaddr_family) {
24181634Sbrian  case AF_INET:
24281634Sbrian    addr->ncpaddr_family = AF_INET;
24381634Sbrian    addr->ncpaddr_ip4addr = from->ncpaddr_ip4addr;
24481634Sbrian    break;
24581634Sbrian#ifndef NOINET6
24681634Sbrian  case AF_INET6:
24781634Sbrian    addr->ncpaddr_family = AF_INET6;
24881634Sbrian    addr->ncpaddr_ip6addr = from->ncpaddr_ip6addr;
24981634Sbrian    break;
25081634Sbrian#endif
25181634Sbrian  default:
25281634Sbrian    addr->ncpaddr_family = AF_UNSPEC;
25381634Sbrian  }
25481634Sbrian}
25581634Sbrian
25681634Sbrianvoid
25781634Sbrianncpaddr_setip4addr(struct ncpaddr *addr, u_int32_t ip)
25881634Sbrian{
25981634Sbrian  addr->ncpaddr_family = AF_INET;
26081634Sbrian  addr->ncpaddr_ip4addr.s_addr = ip;
26181634Sbrian}
26281634Sbrian
26381634Sbrianint
26481634Sbrianncpaddr_getip4addr(const struct ncpaddr *addr, u_int32_t *ip)
26581634Sbrian{
26681634Sbrian  if (addr->ncpaddr_family != AF_INET)
26781634Sbrian    return 0;
26881634Sbrian  *ip = addr->ncpaddr_ip4addr.s_addr;
26981634Sbrian  return 1;
27081634Sbrian}
27181634Sbrian
27281634Sbrianvoid
27381634Sbrianncpaddr_setip4(struct ncpaddr *addr, struct in_addr ip)
27481634Sbrian{
27581634Sbrian  addr->ncpaddr_family = AF_INET;
27681634Sbrian  addr->ncpaddr_ip4addr = ip;
27781634Sbrian}
27881634Sbrian
27981634Sbrianint
28081634Sbrianncpaddr_getip4(const struct ncpaddr *addr, struct in_addr *ip)
28181634Sbrian{
28281634Sbrian  if (addr->ncpaddr_family != AF_INET)
28381634Sbrian    return 0;
28481634Sbrian  *ip = addr->ncpaddr_ip4addr;
28581634Sbrian  return 1;
28681634Sbrian}
28781634Sbrian
28881634Sbrian#ifndef NOINET6
28981634Sbrianvoid
29081634Sbrianncpaddr_setip6(struct ncpaddr *addr, const struct in6_addr *ip6)
29181634Sbrian{
29281634Sbrian  addr->ncpaddr_family = AF_INET6;
29381634Sbrian  addr->ncpaddr_ip6addr = *ip6;
29481634Sbrian}
29581634Sbrian
29681634Sbrianint
29781634Sbrianncpaddr_getip6(const struct ncpaddr *addr, struct in6_addr *ip6)
29881634Sbrian{
29981634Sbrian  if (addr->ncpaddr_family != AF_INET6)
30081634Sbrian    return 0;
30181634Sbrian  *ip6 = addr->ncpaddr_ip6addr;
30281634Sbrian  return 1;
30381634Sbrian}
30481634Sbrian#endif
30581634Sbrian
30681634Sbrianvoid
30781634Sbrianncpaddr_getsa(const struct ncpaddr *addr, struct sockaddr_storage *host)
30881634Sbrian{
30981634Sbrian  struct sockaddr_in *host4 = (struct sockaddr_in *)host;
31081634Sbrian#ifndef NOINET6
31181634Sbrian  struct sockaddr_in6 *host6 = (struct sockaddr_in6 *)host;
31281634Sbrian#endif
31381634Sbrian
31481634Sbrian  memset(host, '\0', sizeof(*host));
31581634Sbrian
31681634Sbrian  switch (addr->ncpaddr_family) {
31781634Sbrian  case AF_INET:
31881634Sbrian    host4->sin_family = AF_INET;
31981634Sbrian    host4->sin_len = sizeof(*host4);
32081634Sbrian    host4->sin_addr = addr->ncpaddr_ip4addr;
32181634Sbrian    break;
32281634Sbrian
32381634Sbrian#ifndef NOINET6
32481634Sbrian  case AF_INET6:
32581634Sbrian    host6->sin6_family = AF_INET6;
32681634Sbrian    host6->sin6_len = sizeof(*host6);
32781634Sbrian    host6->sin6_addr = addr->ncpaddr_ip6addr;
32881634Sbrian    break;
32981634Sbrian#endif
33081634Sbrian
33181634Sbrian  default:
33281634Sbrian    host->ss_family = AF_UNSPEC;
33381634Sbrian    break;
33481634Sbrian  }
33581634Sbrian}
33681634Sbrian
33781634Sbrianvoid
33881634Sbrianncpaddr_setsa(struct ncpaddr *addr, const struct sockaddr *host)
33981634Sbrian{
34081634Sbrian  const struct sockaddr_in *host4 = (const struct sockaddr_in *)host;
34181634Sbrian#ifndef NOINET6
34281634Sbrian  const struct sockaddr_in6 *host6 = (const struct sockaddr_in6 *)host;
34381634Sbrian#endif
34481634Sbrian
34581634Sbrian  switch (host->sa_family) {
34681634Sbrian  case AF_INET:
34781634Sbrian    addr->ncpaddr_family = AF_INET;
34881634Sbrian    addr->ncpaddr_ip4addr = host4->sin_addr;
34981634Sbrian    break;
35081634Sbrian
35181634Sbrian#ifndef NOINET6
35281634Sbrian  case AF_INET6:
35381634Sbrian    if (IN6_IS_ADDR_V4MAPPED(&host6->sin6_addr)) {
35481634Sbrian      addr->ncpaddr_family = AF_INET;
35581634Sbrian      addr->ncpaddr_ip4addr.s_addr =
35681634Sbrian        *(const u_int32_t *)(host6->sin6_addr.s6_addr + 12);
35781634Sbrian    } else {
35881634Sbrian      addr->ncpaddr_family = AF_INET6;
35981634Sbrian      addr->ncpaddr_ip6addr = host6->sin6_addr;
36081634Sbrian    }
36181634Sbrian    break;
36281634Sbrian#endif
36381634Sbrian
36481634Sbrian  default:
36581634Sbrian    addr->ncpaddr_family = AF_UNSPEC;
36681634Sbrian  }
36781634Sbrian}
36881634Sbrian
36981634Sbrianstatic char *
37081634Sbrianncpaddr_ntowa(const struct ncpaddr *addr)
37181634Sbrian{
37281634Sbrian  static char res[NCP_ASCIIBUFFERSIZE];
37381634Sbrian#ifndef NOINET6
37481634Sbrian  struct sockaddr_in6 sin6;
37581634Sbrian#endif
37681634Sbrian
37781634Sbrian  switch (addr->ncpaddr_family) {
37881634Sbrian  case AF_INET:
37981634Sbrian    snprintf(res, sizeof res, "%s", inet_ntoa(addr->ncpaddr_ip4addr));
38081634Sbrian    return res;
38181634Sbrian
38281634Sbrian#ifndef NOINET6
38381634Sbrian  case AF_INET6:
38481634Sbrian    memset(&sin6, '\0', sizeof(sin6));
38581634Sbrian    sin6.sin6_len = sizeof(sin6);
38681634Sbrian    sin6.sin6_family = AF_INET6;
38781634Sbrian    sin6.sin6_addr = addr->ncpaddr_ip6addr;
38881634Sbrian    adjust_linklocal(&sin6);
389102558Sbrian#ifdef NI_WITHSCOPEID
39081634Sbrian    if (getnameinfo((struct sockaddr *)&sin6, sizeof sin6, res, sizeof(res),
39181634Sbrian                    NULL, 0, NI_WITHSCOPEID | NI_NUMERICHOST) != 0)
392102558Sbrian#else
393102558Sbrian    if (getnameinfo((struct sockaddr *)&sin6, sizeof sin6, res, sizeof(res),
394102558Sbrian                    NULL, 0, NI_NUMERICHOST) != 0)
395102558Sbrian#endif
39681634Sbrian      break;
39781634Sbrian
39881634Sbrian    return res;
39981634Sbrian#endif
40081634Sbrian  }
40181634Sbrian
40281634Sbrian  snprintf(res, sizeof res, "<AF_UNSPEC>");
40381634Sbrian  return res;
40481634Sbrian}
40581634Sbrian
40681634Sbrianconst char *
40781634Sbrianncpaddr_ntoa(const struct ncpaddr *addr)
40881634Sbrian{
40981634Sbrian  return ncpaddr_ntowa(addr);
41081634Sbrian}
41181634Sbrian
41281634Sbrian
41381634Sbrianint
41481634Sbrianncpaddr_aton(struct ncpaddr *addr, struct ncp *ncp, const char *data)
41581634Sbrian{
41681634Sbrian  struct ncprange range;
41781634Sbrian
41881634Sbrian  if (!ncprange_aton(&range, ncp, data))
41981634Sbrian    return 0;
42098243Sbrian
42181634Sbrian  if (range.ncprange_family == AF_INET && range.ncprange_ip4width != 32) {
42281634Sbrian    log_Printf(LogWARN, "ncpaddr_aton: %s: Only 32 bits allowed\n", data);
42381634Sbrian    return 0;
42481634Sbrian  }
42581634Sbrian
42681634Sbrian#ifndef NOINET6
42781634Sbrian  if (range.ncprange_family == AF_INET6 && range.ncprange_ip6width != 128) {
42881634Sbrian    log_Printf(LogWARN, "ncpaddr_aton: %s: Only 128 bits allowed\n", data);
42981634Sbrian    return 0;
43081634Sbrian  }
43181634Sbrian#endif
43281634Sbrian
43381634Sbrian  switch (range.ncprange_family) {
43481634Sbrian  case AF_INET:
43581634Sbrian    addr->ncpaddr_family = range.ncprange_family;
43681634Sbrian    addr->ncpaddr_ip4addr = range.ncprange_ip4addr;
43781634Sbrian    return 1;
43881634Sbrian
43981634Sbrian#ifndef NOINET6
44081634Sbrian  case AF_INET6:
44181634Sbrian    addr->ncpaddr_family = range.ncprange_family;
44281634Sbrian    addr->ncpaddr_ip6addr = range.ncprange_ip6addr;
44381634Sbrian    return 1;
44481634Sbrian#endif
44581634Sbrian  }
44681634Sbrian
44781634Sbrian  return 0;
44881634Sbrian}
44981634Sbrian
45081634Sbrianvoid
45181634Sbrianncprange_init(struct ncprange *range)
45281634Sbrian{
45381634Sbrian  range->ncprange_family = AF_UNSPEC;
45481634Sbrian}
45581634Sbrian
45681634Sbrianint
45781634Sbrianncprange_isset(const struct ncprange *range)
45881634Sbrian{
45981634Sbrian  return range->ncprange_family != AF_UNSPEC;
46081634Sbrian}
46181634Sbrian
46281634Sbrianint
46381634Sbrianncprange_equal(const struct ncprange *range, const struct ncprange *cmp)
46481634Sbrian{
46581634Sbrian  if (range->ncprange_family != cmp->ncprange_family)
46681634Sbrian    return 0;
46781634Sbrian
46881634Sbrian  switch (range->ncprange_family) {
46981634Sbrian  case AF_INET:
47081634Sbrian    if (range->ncprange_ip4addr.s_addr != cmp->ncprange_ip4addr.s_addr)
47181634Sbrian      return 0;
47281634Sbrian    return range->ncprange_ip4mask.s_addr == cmp->ncprange_ip4mask.s_addr;
47381634Sbrian
47481634Sbrian#ifndef NOINET6
47581634Sbrian  case AF_INET6:
47681634Sbrian    if (range->ncprange_ip6width != cmp->ncprange_ip6width)
47781634Sbrian      return 0;
47881634Sbrian    return !memcmp(&range->ncprange_ip6addr, &cmp->ncprange_ip6addr,
47981634Sbrian                   sizeof range->ncprange_ip6addr);
48081634Sbrian#endif
48181634Sbrian
48281634Sbrian  case AF_UNSPEC:
48381634Sbrian    return 1;
48481634Sbrian  }
48581634Sbrian
48681634Sbrian  return 0;
48781634Sbrian}
48881634Sbrian
48981634Sbrianint
49081634Sbrianncprange_isdefault(const struct ncprange *range)
49181634Sbrian{
49281634Sbrian  switch (range->ncprange_family) {
49381634Sbrian  case AF_INET:
49481634Sbrian    if (range->ncprange_ip4addr.s_addr == INADDR_ANY)
49581634Sbrian      return 1;
49681634Sbrian    break;
49781634Sbrian
49881634Sbrian#ifndef NOINET6
49981634Sbrian  case AF_INET6:
50081634Sbrian    if (range->ncprange_ip6width == 0 &&
50181634Sbrian        IN6_IS_ADDR_UNSPECIFIED(&range->ncprange_ip6addr))
50281634Sbrian      return 1;
50381634Sbrian    break;
50481634Sbrian#endif
50581634Sbrian  }
50681634Sbrian
50781634Sbrian  return 0;
50881634Sbrian}
50981634Sbrian
51081634Sbrianvoid
51181634Sbrianncprange_setdefault(struct ncprange *range, int af)
51281634Sbrian{
51381634Sbrian  memset(range, '\0', sizeof *range);
51481634Sbrian  range->ncprange_family = af;
51581634Sbrian}
51681634Sbrian
51781634Sbrianint
51881634Sbrianncprange_contains(const struct ncprange *range, const struct ncpaddr *addr)
51981634Sbrian{
52081634Sbrian#ifndef NOINET6
52181634Sbrian  const u_char masks[] = { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
52281634Sbrian  const u_char *addrp, *rangep;
52381634Sbrian  int bits;
52481634Sbrian#endif
52581634Sbrian
52681634Sbrian  if (range->ncprange_family != addr->ncpaddr_family)
52781634Sbrian    return 0;
52881634Sbrian
52981634Sbrian  switch (range->ncprange_family) {
53081634Sbrian  case AF_INET:
53181634Sbrian    return !((addr->ncpaddr_ip4addr.s_addr ^ range->ncprange_ip4addr.s_addr) &
53281634Sbrian             range->ncprange_ip4mask.s_addr);
53381634Sbrian
53481634Sbrian#ifndef NOINET6
53581634Sbrian  case AF_INET6:
53681634Sbrian    rangep = (const u_char *)range->ncprange_ip6addr.s6_addr;
53781634Sbrian    addrp = (const u_char *)addr->ncpaddr_ip6addr.s6_addr;
53881634Sbrian
53981634Sbrian    for (bits = range->ncprange_ip6width; bits > 0; bits -= 8)
54081634Sbrian      if ((*addrp++ ^ *rangep++) & masks[bits > 7 ? 7 : bits - 1])
54181634Sbrian        return 0;
54281634Sbrian
54381634Sbrian    return 1;
54481634Sbrian#endif
54581634Sbrian  }
54681634Sbrian
54781634Sbrian  return 0;
54881634Sbrian}
54981634Sbrian
55081634Sbrianint
55181634Sbrianncprange_containsip4(const struct ncprange *range, struct in_addr addr)
55281634Sbrian{
55381634Sbrian  switch (range->ncprange_family) {
55481634Sbrian  case AF_INET:
55581634Sbrian    return !((addr.s_addr ^ range->ncprange_ip4addr.s_addr) &
55681634Sbrian             range->ncprange_ip4mask.s_addr);
55781634Sbrian  }
55881634Sbrian
55981634Sbrian  return 0;
56081634Sbrian}
56181634Sbrian
56281634Sbrianvoid
56381634Sbrianncprange_copy(struct ncprange *range, const struct ncprange *from)
56481634Sbrian{
56581634Sbrian  switch (from->ncprange_family) {
56681634Sbrian  case AF_INET:
56781634Sbrian    range->ncprange_family = AF_INET;
56881634Sbrian    range->ncprange_ip4addr = from->ncprange_ip4addr;
56981634Sbrian    range->ncprange_ip4mask = from->ncprange_ip4mask;
57081634Sbrian    range->ncprange_ip4width = from->ncprange_ip4width;
57181634Sbrian    break;
57281634Sbrian
57381634Sbrian#ifndef NOINET6
57481634Sbrian  case AF_INET6:
57581634Sbrian    range->ncprange_family = AF_INET6;
57681634Sbrian    range->ncprange_ip6addr = from->ncprange_ip6addr;
57781634Sbrian    range->ncprange_ip6width = from->ncprange_ip6width;
57881634Sbrian    break;
57981634Sbrian#endif
58081634Sbrian
58181634Sbrian  default:
58281634Sbrian    range->ncprange_family = AF_UNSPEC;
58381634Sbrian  }
58481634Sbrian}
58581634Sbrian
58681634Sbrianvoid
58781634Sbrianncprange_set(struct ncprange *range, const struct ncpaddr *addr, int width)
58881634Sbrian{
58981634Sbrian  ncprange_sethost(range, addr);
59081634Sbrian  ncprange_setwidth(range, width);
59181634Sbrian}
59281634Sbrian
59381634Sbrianvoid
59481634Sbrianncprange_sethost(struct ncprange *range, const struct ncpaddr *from)
59581634Sbrian{
59681634Sbrian  switch (from->ncpaddr_family) {
59781634Sbrian  case AF_INET:
59881634Sbrian    range->ncprange_family = AF_INET;
59981634Sbrian    range->ncprange_ip4addr = from->ncpaddr_ip4addr;
60086832Sbrian    if (from->ncpaddr_ip4addr.s_addr == INADDR_ANY) {
60186832Sbrian      range->ncprange_ip4mask.s_addr = INADDR_ANY;
60286832Sbrian      range->ncprange_ip4width = 0;
60386832Sbrian    } else {
60486832Sbrian      range->ncprange_ip4mask.s_addr = INADDR_BROADCAST;
60586832Sbrian      range->ncprange_ip4width = 32;
60686832Sbrian    }
60781634Sbrian    break;
60881634Sbrian
60981634Sbrian#ifndef NOINET6
61081634Sbrian  case AF_INET6:
61181634Sbrian    range->ncprange_family = AF_INET6;
61281634Sbrian    range->ncprange_ip6addr = from->ncpaddr_ip6addr;
61381634Sbrian    range->ncprange_ip6width = 128;
61481634Sbrian    break;
61581634Sbrian#endif
61681634Sbrian
61781634Sbrian  default:
61881634Sbrian    range->ncprange_family = AF_UNSPEC;
61981634Sbrian  }
62081634Sbrian}
62181634Sbrian
62281634Sbrianint
62386815Sbrianncprange_ishost(const struct ncprange *range)
62486815Sbrian{
62586815Sbrian  switch (range->ncprange_family) {
62686815Sbrian  case AF_INET:
62786815Sbrian    return range->ncprange_ip4width == 32;
62886815Sbrian#ifndef NOINET6
62986815Sbrian  case AF_INET6:
63086815Sbrian    return range->ncprange_ip6width == 128;
63186815Sbrian#endif
63286815Sbrian  }
63386815Sbrian
63486815Sbrian  return (0);
63586815Sbrian}
63686815Sbrian
63786815Sbrianint
63881634Sbrianncprange_setwidth(struct ncprange *range, int width)
63981634Sbrian{
64081634Sbrian  switch (range->ncprange_family) {
64181634Sbrian  case AF_INET:
64281634Sbrian    if (width < 0 || width > 32)
64381634Sbrian      break;
64481634Sbrian    range->ncprange_ip4width = width;
64581634Sbrian    range->ncprange_ip4mask = bits2mask4(width);
64681634Sbrian    break;
64781634Sbrian
64881634Sbrian#ifndef NOINET6
64981634Sbrian  case AF_INET6:
65081634Sbrian    if (width < 0 || width > 128)
65181634Sbrian      break;
65281634Sbrian    range->ncprange_ip6width = width;
65381634Sbrian    break;
65481634Sbrian#endif
65581634Sbrian
65681634Sbrian  case AF_UNSPEC:
65781634Sbrian    return 1;
65881634Sbrian  }
65981634Sbrian
66081634Sbrian  return 0;
66181634Sbrian}
66281634Sbrian
66381634Sbrianvoid
66481634Sbrianncprange_setip4host(struct ncprange *range, struct in_addr from)
66581634Sbrian{
66681634Sbrian  range->ncprange_family = AF_INET;
66781634Sbrian  range->ncprange_ip4addr = from;
66886832Sbrian  if (from.s_addr == INADDR_ANY) {
66986832Sbrian    range->ncprange_ip4mask.s_addr = INADDR_ANY;
67086832Sbrian    range->ncprange_ip4width = 0;
67186832Sbrian  } else {
67286832Sbrian    range->ncprange_ip4mask.s_addr = INADDR_BROADCAST;
67386832Sbrian    range->ncprange_ip4width = 32;
67486832Sbrian  }
67581634Sbrian}
67681634Sbrian
67781634Sbrianvoid
67881634Sbrianncprange_setip4(struct ncprange *range, struct in_addr from, struct in_addr msk)
67981634Sbrian{
68081634Sbrian  range->ncprange_family = AF_INET;
68181634Sbrian  range->ncprange_ip4addr = from;
68281634Sbrian  range->ncprange_ip4mask = msk;
68381634Sbrian  range->ncprange_ip4width = mask42bits(msk);
68481634Sbrian}
68581634Sbrian
68681634Sbrian
68781634Sbrianint
68881634Sbrianncprange_setip4mask(struct ncprange *range, struct in_addr mask)
68981634Sbrian{
69081634Sbrian  if (range->ncprange_family != AF_INET)
69181634Sbrian    return 0;
69281634Sbrian  range->ncprange_ip4mask = mask;
69381634Sbrian  range->ncprange_ip4width = mask42bits(mask);
69481634Sbrian  return 1;
69581634Sbrian}
69681634Sbrian
69781634Sbrianvoid
69881634Sbrianncprange_setsa(struct ncprange *range, const struct sockaddr *host,
69981634Sbrian               const struct sockaddr *mask)
70081634Sbrian{
70181634Sbrian  const struct sockaddr_in *host4 = (const struct sockaddr_in *)host;
70281634Sbrian  const struct sockaddr_in *mask4 = (const struct sockaddr_in *)mask;
70381634Sbrian#ifndef NOINET6
70481634Sbrian  const struct sockaddr_in6 *host6 = (const struct sockaddr_in6 *)host;
70581634Sbrian  const struct sockaddr_in6 *mask6 = (const struct sockaddr_in6 *)mask;
70681634Sbrian#endif
70781634Sbrian
70881634Sbrian  switch (host->sa_family) {
70981634Sbrian  case AF_INET:
71081634Sbrian    range->ncprange_family = AF_INET;
71181634Sbrian    range->ncprange_ip4addr = host4->sin_addr;
71286832Sbrian    if (host4->sin_addr.s_addr == INADDR_ANY) {
71386832Sbrian      range->ncprange_ip4mask.s_addr = INADDR_ANY;
71486832Sbrian      range->ncprange_ip4width = 0;
71586832Sbrian    } else if (mask4 && mask4->sin_family == AF_INET) {
71681634Sbrian      range->ncprange_ip4mask.s_addr = mask4->sin_addr.s_addr;
71781634Sbrian      range->ncprange_ip4width = mask42bits(mask4->sin_addr);
71881634Sbrian    } else {
71981634Sbrian      range->ncprange_ip4mask.s_addr = INADDR_BROADCAST;
72081634Sbrian      range->ncprange_ip4width = 32;
72181634Sbrian    }
72281634Sbrian    break;
72381634Sbrian
72481634Sbrian#ifndef NOINET6
72581634Sbrian  case AF_INET6:
72681634Sbrian    range->ncprange_family = AF_INET6;
72781634Sbrian    range->ncprange_ip6addr = host6->sin6_addr;
728113110Sume    if (IN6_IS_ADDR_UNSPECIFIED(&host6->sin6_addr))
729113110Sume      range->ncprange_ip6width = 0;
730113110Sume    else
731113110Sume      range->ncprange_ip6width = mask6 ? mask62bits(&mask6->sin6_addr) : 128;
73281634Sbrian    break;
73381634Sbrian#endif
73481634Sbrian
73581634Sbrian  default:
73681634Sbrian    range->ncprange_family = AF_UNSPEC;
73781634Sbrian  }
73881634Sbrian}
73981634Sbrian
74081634Sbrianvoid
74181634Sbrianncprange_getsa(const struct ncprange *range, struct sockaddr_storage *host,
74281634Sbrian               struct sockaddr_storage *mask)
74381634Sbrian{
74481634Sbrian  struct sockaddr_in *host4 = (struct sockaddr_in *)host;
74581634Sbrian  struct sockaddr_in *mask4 = (struct sockaddr_in *)mask;
74681634Sbrian#ifndef NOINET6
74781634Sbrian  struct sockaddr_in6 *host6 = (struct sockaddr_in6 *)host;
74881634Sbrian  struct sockaddr_in6 *mask6 = (struct sockaddr_in6 *)mask;
74981634Sbrian#endif
75081634Sbrian
75181634Sbrian  memset(host, '\0', sizeof(*host));
75281634Sbrian  if (mask)
75381634Sbrian    memset(mask, '\0', sizeof(*mask));
75481634Sbrian
75581634Sbrian  switch (range->ncprange_family) {
75681634Sbrian  case AF_INET:
75781634Sbrian    host4->sin_family = AF_INET;
75881634Sbrian    host4->sin_len = sizeof(*host4);
75981634Sbrian    host4->sin_addr = range->ncprange_ip4addr;
76081634Sbrian    if (mask4) {
76181634Sbrian      mask4->sin_family = AF_INET;
76281634Sbrian      mask4->sin_len = sizeof(*host4);
76381690Sbrian      mask4->sin_addr = range->ncprange_ip4mask;
76481634Sbrian    }
76581634Sbrian    break;
76681634Sbrian
76781634Sbrian#ifndef NOINET6
76881634Sbrian  case AF_INET6:
76981634Sbrian    host6->sin6_family = AF_INET6;
77081634Sbrian    host6->sin6_len = sizeof(*host6);
77181634Sbrian    host6->sin6_addr = range->ncprange_ip6addr;
77281634Sbrian    if (mask6) {
77381634Sbrian      mask6->sin6_family = AF_INET6;
77481634Sbrian      mask6->sin6_len = sizeof(*host6);
77581634Sbrian      mask6->sin6_addr = bits2mask6(range->ncprange_ip6width);
77681634Sbrian    }
77781634Sbrian    break;
77881634Sbrian#endif
77981634Sbrian
78081634Sbrian  default:
78181634Sbrian    host->ss_family = AF_UNSPEC;
78281634Sbrian    if (mask)
78381634Sbrian      mask->ss_family = AF_UNSPEC;
78481634Sbrian    break;
78581634Sbrian  }
78681634Sbrian}
78781634Sbrian
78881634Sbrianint
78981634Sbrianncprange_getaddr(const struct ncprange *range, struct ncpaddr *addr)
79081634Sbrian{
79181634Sbrian  switch (range->ncprange_family) {
79281634Sbrian  case AF_INET:
79381634Sbrian    addr->ncpaddr_family = AF_INET;
79481634Sbrian    addr->ncpaddr_ip4addr = range->ncprange_ip4addr;
79581634Sbrian    return 1;
79681634Sbrian#ifndef NOINET6
79781634Sbrian  case AF_INET6:
79881634Sbrian    addr->ncpaddr_family = AF_INET6;
79981634Sbrian    addr->ncpaddr_ip6addr =  range->ncprange_ip6addr;
80081634Sbrian    return 1;
80181634Sbrian#endif
80281634Sbrian  }
80381634Sbrian
80481634Sbrian  return 0;
80581634Sbrian}
80681634Sbrian
80781634Sbrianint
80881634Sbrianncprange_getip4addr(const struct ncprange *range, struct in_addr *addr)
80981634Sbrian{
81081634Sbrian  if (range->ncprange_family != AF_INET)
81181634Sbrian    return 0;
81281634Sbrian
81381634Sbrian  *addr = range->ncprange_ip4addr;
81481634Sbrian  return 1;
81581634Sbrian}
81681634Sbrian
81781634Sbrianint
81881634Sbrianncprange_getip4mask(const struct ncprange *range, struct in_addr *mask)
81981634Sbrian{
82081634Sbrian  switch (range->ncprange_family) {
82181634Sbrian  case AF_INET:
82281634Sbrian    *mask = range->ncprange_ip4mask;
82381634Sbrian    return 1;
82481634Sbrian  }
82581634Sbrian
82681634Sbrian  return 0;
82781634Sbrian}
82881634Sbrian
82981634Sbrianint
83081634Sbrianncprange_getwidth(const struct ncprange *range, int *width)
83181634Sbrian{
83281634Sbrian  switch (range->ncprange_family) {
83381634Sbrian  case AF_INET:
83481634Sbrian    *width = range->ncprange_ip4width;
83581634Sbrian    return 1;
83681634Sbrian#ifndef NOINET6
83781634Sbrian  case AF_INET6:
83881634Sbrian    *width = range->ncprange_ip6width;
83981634Sbrian    return 1;
84081634Sbrian#endif
84181634Sbrian  }
84281634Sbrian
84381634Sbrian  return 0;
84481634Sbrian}
84581634Sbrian
84681634Sbrianconst char *
84781634Sbrianncprange_ntoa(const struct ncprange *range)
84881634Sbrian{
84981634Sbrian  char *res;
85081634Sbrian  struct ncpaddr addr;
85181634Sbrian  int len;
85281634Sbrian
85381634Sbrian  if (!ncprange_getaddr(range, &addr))
85481634Sbrian    return "<AF_UNSPEC>";
85581634Sbrian
85681634Sbrian  res = ncpaddr_ntowa(&addr);
85781634Sbrian  len = strlen(res);
85881634Sbrian  if (len >= NCP_ASCIIBUFFERSIZE - 1)
85981634Sbrian    return res;
86081634Sbrian
86181634Sbrian  switch (range->ncprange_family) {
86281634Sbrian  case AF_INET:
86381634Sbrian    if (range->ncprange_ip4width == -1) {
86481634Sbrian      /* A non-contiguous mask */
86581634Sbrian      for (; len >= 3; res[len -= 2] = '\0')
86681634Sbrian        if (strcmp(res + len - 2, ".0"))
86781634Sbrian          break;
86881634Sbrian      snprintf(res + len, sizeof res - len, "&0x%08lx",
86981924Sbrian               (unsigned long)ntohl(range->ncprange_ip4mask.s_addr));
87081634Sbrian    } else if (range->ncprange_ip4width < 32)
87181634Sbrian      snprintf(res + len, sizeof res - len, "/%d", range->ncprange_ip4width);
87281634Sbrian
87381634Sbrian    return res;
87481634Sbrian
87581634Sbrian#ifndef NOINET6
87681634Sbrian  case AF_INET6:
87781634Sbrian    if (range->ncprange_ip6width != 128)
87881634Sbrian      snprintf(res + len, sizeof res - len, "/%d", range->ncprange_ip6width);
87981634Sbrian
88081634Sbrian    return res;
88181634Sbrian#endif
88281634Sbrian  }
88381634Sbrian
88481634Sbrian  return "<AF_UNSPEC>";
88581634Sbrian}
88681634Sbrian
88781634Sbrian#ifndef NOINET6
88881634Sbrianint
88981634Sbrianncprange_scopeid(const struct ncprange *range)
89081634Sbrian{
89181634Sbrian  const struct in6_addr *sin6;
89281634Sbrian  int scopeid = -1;
89381634Sbrian
89481634Sbrian  if (range->ncprange_family == AF_INET6) {
89581634Sbrian    sin6 = &range->ncprange_ip6addr;
89681634Sbrian    if (IN6_IS_ADDR_LINKLOCAL(sin6) || IN6_IS_ADDR_MC_LINKLOCAL(sin6))
89781634Sbrian      if ((scopeid = ntohs(*(const u_short *)&sin6->s6_addr[2])) == 0)
89881634Sbrian        scopeid = -1;
89981634Sbrian  }
90081634Sbrian
90181634Sbrian  return scopeid;
90281634Sbrian}
90381634Sbrian#endif
90481634Sbrian
90581634Sbrianint
90681634Sbrianncprange_aton(struct ncprange *range, struct ncp *ncp, const char *data)
90781634Sbrian{
90881634Sbrian  int bits, len;
90981634Sbrian  char *wp;
91081634Sbrian  const char *cp;
91181634Sbrian  char *s;
91281634Sbrian
91381634Sbrian  len = strcspn(data, "/");
91481634Sbrian
91581634Sbrian  if (ncp && strncasecmp(data, "HISADDR", len) == 0) {
91681634Sbrian    range->ncprange_family = AF_INET;
91781634Sbrian    range->ncprange_ip4addr = ncp->ipcp.peer_ip;
91881634Sbrian    range->ncprange_ip4mask.s_addr = INADDR_BROADCAST;
91981634Sbrian    range->ncprange_ip4width = 32;
92081634Sbrian    return 1;
92181634Sbrian#ifndef NOINET6
92281634Sbrian  } else if (ncp && strncasecmp(data, "HISADDR6", len) == 0) {
923112673Sume    range->ncprange_family = AF_INET6;
924112673Sume    range->ncprange_ip6addr = ncp->ipv6cp.hisaddr.ncpaddr_ip6addr;
925112673Sume    range->ncprange_ip6width = 128;
92681634Sbrian    return 1;
92781634Sbrian#endif
92881634Sbrian  } else if (ncp && strncasecmp(data, "MYADDR", len) == 0) {
92981634Sbrian    range->ncprange_family = AF_INET;
93081634Sbrian    range->ncprange_ip4addr = ncp->ipcp.my_ip;
93181634Sbrian    range->ncprange_ip4mask.s_addr = INADDR_BROADCAST;
93281634Sbrian    range->ncprange_ip4width = 32;
93381634Sbrian    return 1;
93481634Sbrian#ifndef NOINET6
93581634Sbrian  } else if (ncp && strncasecmp(data, "MYADDR6", len) == 0) {
936112673Sume    range->ncprange_family = AF_INET6;
937112673Sume    range->ncprange_ip6addr = ncp->ipv6cp.myaddr.ncpaddr_ip6addr;
938112673Sume    range->ncprange_ip6width = 128;
93981634Sbrian    return 1;
94081634Sbrian#endif
94181634Sbrian  } else if (ncp && strncasecmp(data, "DNS0", len) == 0) {
94281634Sbrian    range->ncprange_family = AF_INET;
94381634Sbrian    range->ncprange_ip4addr = ncp->ipcp.ns.dns[0];
94481634Sbrian    range->ncprange_ip4mask.s_addr = INADDR_BROADCAST;
94581634Sbrian    range->ncprange_ip4width = 32;
94681634Sbrian    return 1;
94781634Sbrian  } else if (ncp && strncasecmp(data, "DNS1", len) == 0) {
94881634Sbrian    range->ncprange_family = AF_INET;
94981634Sbrian    range->ncprange_ip4addr = ncp->ipcp.ns.dns[1];
95081634Sbrian    range->ncprange_ip4mask.s_addr = INADDR_BROADCAST;
95181634Sbrian    range->ncprange_ip4width = 32;
95281634Sbrian    return 1;
95381634Sbrian  }
95481634Sbrian
95581634Sbrian  s = (char *)alloca(len + 1);
95681634Sbrian  strncpy(s, data, len);
95781634Sbrian  s[len] = '\0';
95881634Sbrian  bits = -1;
95981634Sbrian
96081634Sbrian  if (data[len] != '\0') {
96181634Sbrian    bits = strtol(data + len + 1, &wp, 0);
96281634Sbrian    if (*wp || wp == data + len + 1 || bits < 0 || bits > 128) {
96381634Sbrian      log_Printf(LogWARN, "ncprange_aton: bad mask width.\n");
96481634Sbrian      return 0;
96581634Sbrian    }
96681634Sbrian  }
96781634Sbrian
96881634Sbrian  if ((cp = strchr(data, ':')) == NULL) {
96981634Sbrian    range->ncprange_family = AF_INET;
97081634Sbrian
97181634Sbrian    range->ncprange_ip4addr = GetIpAddr(s);
97281634Sbrian
97381634Sbrian    if (range->ncprange_ip4addr.s_addr == INADDR_NONE) {
97481634Sbrian      log_Printf(LogWARN, "ncprange_aton: %s: Bad address\n", s);
97581634Sbrian      return 0;
97681634Sbrian    }
97781634Sbrian
97881634Sbrian    if (range->ncprange_ip4addr.s_addr == INADDR_ANY) {
97981634Sbrian      range->ncprange_ip4mask.s_addr = INADDR_ANY;
98081634Sbrian      range->ncprange_ip4width = 0;
98181690Sbrian    } else if (bits == -1) {
98281634Sbrian      range->ncprange_ip4mask.s_addr = INADDR_BROADCAST;
98381634Sbrian      range->ncprange_ip4width = 32;
98481690Sbrian    } else if (bits > 32) {
98581690Sbrian      log_Printf(LogWARN, "ncprange_aton: bad mask width.\n");
98681690Sbrian      return 0;
98781634Sbrian    } else {
98881634Sbrian      range->ncprange_ip4mask = bits2mask4(bits);
98981634Sbrian      range->ncprange_ip4width = bits;
99081634Sbrian    }
99181634Sbrian
99281634Sbrian    return 1;
99381634Sbrian#ifndef NOINET6
99481634Sbrian  } else if (strchr(cp + 1, ':') != NULL) {
99581634Sbrian    range->ncprange_family = AF_INET6;
99681634Sbrian
99781634Sbrian    if (inet_pton(AF_INET6, s, &range->ncprange_ip6addr) != 1) {
99881634Sbrian      log_Printf(LogWARN, "ncprange_aton: %s: Bad address\n", s);
99981634Sbrian      return 0;
100081634Sbrian    }
100181634Sbrian
100281634Sbrian    if (IN6_IS_ADDR_UNSPECIFIED(&range->ncprange_ip6addr))
100381634Sbrian      range->ncprange_ip6width = 0;
100481634Sbrian    else
100581634Sbrian      range->ncprange_ip6width = (bits == -1) ? 128 : bits;
100681634Sbrian    return 1;
100781634Sbrian#endif
100881634Sbrian  }
100981634Sbrian
101081634Sbrian  return 0;
101181634Sbrian}
1012