ncpaddr.c revision 134789
1126261Smlaier/*-
2132303Smlaier * Copyright (c) 2001 Brian Somers <brian@Awfulhak.org>
3126258Smlaier * All rights reserved.
4126258Smlaier *
5126258Smlaier * Redistribution and use in source and binary forms, with or without
6130613Smlaier * modification, are permitted provided that the following conditions
7126258Smlaier * are met:
8126258Smlaier * 1. Redistributions of source code must retain the above copyright
9126258Smlaier *    notice, this list of conditions and the following disclaimer.
10126258Smlaier * 2. Redistributions in binary form must reproduce the above copyright
11126258Smlaier *    notice, this list of conditions and the following disclaimer in the
12126258Smlaier *    documentation and/or other materials provided with the distribution.
13126258Smlaier *
14126258Smlaier * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15126258Smlaier * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16126258Smlaier * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17126258Smlaier * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18126258Smlaier * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19126258Smlaier * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20126258Smlaier * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21126258Smlaier * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22126258Smlaier * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23126258Smlaier * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24126258Smlaier * SUCH DAMAGE.
25126258Smlaier *
26126258Smlaier * $FreeBSD: head/usr.sbin/ppp/ncpaddr.c 134789 2004-09-05 01:46:52Z brian $
27126258Smlaier */
28126258Smlaier
29126258Smlaier#include <sys/types.h>
30126258Smlaier#include <sys/socket.h>
31126258Smlaier#ifdef __OpenBSD__
32126258Smlaier#include <net/if_types.h>
33126258Smlaier#include <net/route.h>
34126258Smlaier#endif
35126258Smlaier#include <netinet/in.h>
36126258Smlaier#include <netinet/in_systm.h>
37126258Smlaier#include <netinet/ip.h>
38126258Smlaier#include <arpa/inet.h>
39127145Smlaier#include <sys/un.h>
40126261Smlaier
41126261Smlaier#include <netdb.h>
42126261Smlaier#include <stdio.h>
43126261Smlaier#include <stdlib.h>
44127145Smlaier#include <string.h>
45126261Smlaier#include <termios.h>
46126261Smlaier
47127145Smlaier#include "log.h"
48127145Smlaier#include "ncpaddr.h"
49127145Smlaier#include "timer.h"
50126261Smlaier#include "fsm.h"
51126258Smlaier#include "defs.h"
52126258Smlaier#include "slcompress.h"
53126258Smlaier#include "iplist.h"
54126261Smlaier#include "throughput.h"
55126258Smlaier#include "mbuf.h"
56126258Smlaier#include "ipcp.h"
57126258Smlaier#include "descriptor.h"
58126258Smlaier#include "layer.h"
59126258Smlaier#include "lqr.h"
60126258Smlaier#include "hdlc.h"
61126258Smlaier#include "lcp.h"
62126258Smlaier#include "ccp.h"
63126258Smlaier#include "link.h"
64127145Smlaier#include "mp.h"
65126261Smlaier#include "ipv6cp.h"
66130613Smlaier#include "ncp.h"
67126261Smlaier
68126258Smlaier
69126261Smlaier#define ncprange_ip4addr	u.ip4.ipaddr
70126258Smlaier#define ncprange_ip4mask	u.ip4.mask
71126258Smlaier#define ncprange_ip4width	u.ip4.width
72126258Smlaier#define ncpaddr_ip4addr		u.ip4addr
73126258Smlaier#ifndef NOINET6
74126258Smlaier#define ncprange_ip6addr	u.ip6.ipaddr
75126258Smlaier#define ncprange_ip6width	u.ip6.width
76126258Smlaier#define ncpaddr_ip6addr		u.ip6addr
77126258Smlaier#endif
78126258Smlaier
79126258Smlaier#define	NCP_ASCIIBUFFERSIZE	52
80126258Smlaier
81126258Smlaierstatic struct in_addr
82126258Smlaierbits2mask4(int bits)
83126258Smlaier{
84126258Smlaier  struct in_addr result;
85126258Smlaier  u_int32_t bit = 0x80000000;
86126258Smlaier
87126258Smlaier  result.s_addr = 0;
88126258Smlaier
89126258Smlaier  while (bits) {
90126258Smlaier    result.s_addr |= bit;
91127145Smlaier    bit >>= 1;
92126258Smlaier    bits--;
93126261Smlaier  }
94126258Smlaier
95126258Smlaier  result.s_addr = htonl(result.s_addr);
96130613Smlaier  return result;
97130613Smlaier}
98126258Smlaier
99130613Smlaierstatic int
100126258Smlaiermask42bits(struct in_addr mask)
101126258Smlaier{
102126258Smlaier  u_int32_t msk = ntohl(mask.s_addr);
103126258Smlaier  u_int32_t tst;
104126258Smlaier  int ret;
105126258Smlaier
106127145Smlaier  for (ret = 32, tst = 1; tst; ret--, tst <<= 1)
107126261Smlaier    if (msk & tst)
108126261Smlaier      break;
109126261Smlaier
110126258Smlaier  for (tst <<= 1; tst; tst <<= 1)
111126258Smlaier    if (!(msk & tst))
112127145Smlaier      break;
113126261Smlaier
114126261Smlaier  return tst ? -1 : ret;
115126261Smlaier}
116126258Smlaier
117126261Smlaier#ifndef NOINET6
118126261Smlaierstatic struct in6_addr
119126261Smlaierbits2mask6(int bits)
120126258Smlaier{
121126258Smlaier  struct in6_addr result;
122126258Smlaier  u_int32_t bit = 0x80;
123126258Smlaier  u_char *c = result.s6_addr;
124126258Smlaier
125126258Smlaier  memset(&result, '\0', sizeof result);
126126258Smlaier
127126258Smlaier  while (bits) {
128126258Smlaier    if (bit == 0) {
129126258Smlaier      bit = 0x80;
130126258Smlaier      c++;
131126258Smlaier    }
132126258Smlaier    *c |= bit;
133126258Smlaier    bit >>= 1;
134126258Smlaier    bits--;
135126258Smlaier  }
136130613Smlaier
137126258Smlaier  return result;
138126258Smlaier}
139127145Smlaier
140126261Smlaierstatic int
141126261Smlaiermask62bits(const struct in6_addr *mask)
142126258Smlaier{
143126261Smlaier  const u_char masks[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
144126258Smlaier  const u_char *c, *p, *end;
145126261Smlaier  int masklen, m;
146127145Smlaier
147130613Smlaier  p = (const u_char *)mask;
148126261Smlaier  for (masklen = 0, end = p + 16; p < end && *p == 0xff; p++)
149126261Smlaier    masklen += 8;
150130613Smlaier
151126258Smlaier  if (p < end) {
152126261Smlaier    for (c = masks, m = 0; c < masks + sizeof masks; c++, m++)
153126258Smlaier      if (*c == *p) {
154126258Smlaier        masklen += m;
155126258Smlaier        break;
156126258Smlaier      }
157126258Smlaier  }
158126258Smlaier
159126258Smlaier  return masklen;
160126258Smlaier}
161126258Smlaier
162126258Smlaier#if 0
163126258Smlaierstatic void
164126258Smlaieradjust_linklocal(struct sockaddr_in6 *sin6)
165126258Smlaier{
166126258Smlaier    /* XXX: ?????!?!?!!!!!  This is horrible ! */
167126258Smlaier    /*
168126258Smlaier     * The kernel does not understand sin6_scope_id for routing at this moment.
169126258Smlaier     * We should rather keep the embedded ID.
170126258Smlaier     * jinmei@kame.net, 20011026
171126258Smlaier     */
172126258Smlaier    if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) ||
173126258Smlaier        IN6_IS_ADDR_MC_LINKLOCAL(&sin6->sin6_addr)) {
174126258Smlaier      sin6->sin6_scope_id =
175126258Smlaier        ntohs(*(u_short *)&sin6->sin6_addr.s6_addr[2]);
176126258Smlaier      *(u_short *)&sin6->sin6_addr.s6_addr[2] = 0;
177126258Smlaier    }
178130613Smlaier}
179126258Smlaier#endif
180126258Smlaier#endif
181126258Smlaier
182130613Smlaiervoid
183126258Smlaierncpaddr_init(struct ncpaddr *addr)
184126258Smlaier{
185126258Smlaier  addr->ncpaddr_family = AF_UNSPEC;
186126258Smlaier}
187130613Smlaier
188126258Smlaierint
189126258Smlaierncpaddr_isset(const struct ncpaddr *addr)
190126258Smlaier{
191130613Smlaier  return addr->ncpaddr_family != AF_UNSPEC;
192126258Smlaier}
193126258Smlaier
194126258Smlaierint
195130613Smlaierncpaddr_isdefault(const struct ncpaddr *addr)
196126258Smlaier{
197126258Smlaier  switch (addr->ncpaddr_family) {
198126258Smlaier  case AF_INET:
199130613Smlaier    if (addr->ncpaddr_ip4addr.s_addr == INADDR_ANY)
200126258Smlaier      return 1;
201126258Smlaier    break;
202126258Smlaier
203130613Smlaier#ifndef NOINET6
204126258Smlaier  case AF_INET6:
205126258Smlaier    if (IN6_IS_ADDR_UNSPECIFIED(&addr->ncpaddr_ip6addr))
206126258Smlaier      return 1;
207130613Smlaier    break;
208126258Smlaier#endif
209126258Smlaier  }
210130613Smlaier
211126258Smlaier  return 0;
212126258Smlaier}
213130613Smlaier
214126258Smlaierint
215126258Smlaierncpaddr_equal(const struct ncpaddr *addr, const struct ncpaddr *cmp)
216130613Smlaier{
217126258Smlaier  if (addr->ncpaddr_family != cmp->ncpaddr_family)
218126258Smlaier    return 0;
219130613Smlaier
220126258Smlaier  switch (addr->ncpaddr_family) {
221126258Smlaier  case AF_INET:
222130613Smlaier    return addr->ncpaddr_ip4addr.s_addr == cmp->ncpaddr_ip4addr.s_addr;
223126258Smlaier
224130613Smlaier#ifndef NOINET6
225130613Smlaier  case AF_INET6:
226126258Smlaier    return !memcmp(&addr->ncpaddr_ip6addr, &cmp->ncpaddr_ip6addr,
227130613Smlaier                   sizeof addr->ncpaddr_ip6addr);
228130613Smlaier#endif
229126258Smlaier
230126258Smlaier  case AF_UNSPEC:
231126258Smlaier    return 1;
232126258Smlaier  }
233130613Smlaier
234126258Smlaier  return 0;
235126258Smlaier}
236126258Smlaier
237126258Smlaiervoid
238126258Smlaierncpaddr_copy(struct ncpaddr *addr, const struct ncpaddr *from)
239126258Smlaier{
240126258Smlaier  switch (from->ncpaddr_family) {
241126258Smlaier  case AF_INET:
242126258Smlaier    addr->ncpaddr_family = AF_INET;
243126258Smlaier    addr->ncpaddr_ip4addr = from->ncpaddr_ip4addr;
244126258Smlaier    break;
245126258Smlaier#ifndef NOINET6
246126258Smlaier  case AF_INET6:
247130613Smlaier    addr->ncpaddr_family = AF_INET6;
248130613Smlaier    addr->ncpaddr_ip6addr = from->ncpaddr_ip6addr;
249130613Smlaier    break;
250126258Smlaier#endif
251127145Smlaier  default:
252126261Smlaier    addr->ncpaddr_family = AF_UNSPEC;
253126258Smlaier  }
254126261Smlaier}
255126261Smlaier
256130613Smlaiervoid
257130613Smlaierncpaddr_setip4addr(struct ncpaddr *addr, u_int32_t ip)
258130613Smlaier{
259130613Smlaier  addr->ncpaddr_family = AF_INET;
260130613Smlaier  addr->ncpaddr_ip4addr.s_addr = ip;
261126261Smlaier}
262126258Smlaier
263126258Smlaierint
264126258Smlaierncpaddr_getip4addr(const struct ncpaddr *addr, u_int32_t *ip)
265126258Smlaier{
266130613Smlaier  if (addr->ncpaddr_family != AF_INET)
267130613Smlaier    return 0;
268126258Smlaier  *ip = addr->ncpaddr_ip4addr.s_addr;
269130613Smlaier  return 1;
270130613Smlaier}
271126258Smlaier
272126258Smlaiervoid
273126258Smlaierncpaddr_setip4(struct ncpaddr *addr, struct in_addr ip)
274126258Smlaier{
275126258Smlaier  addr->ncpaddr_family = AF_INET;
276126258Smlaier  addr->ncpaddr_ip4addr = ip;
277126258Smlaier}
278130613Smlaier
279130613Smlaierint
280126258Smlaierncpaddr_getip4(const struct ncpaddr *addr, struct in_addr *ip)
281126258Smlaier{
282126258Smlaier  if (addr->ncpaddr_family != AF_INET)
283126258Smlaier    return 0;
284126258Smlaier  *ip = addr->ncpaddr_ip4addr;
285126258Smlaier  return 1;
286126258Smlaier}
287126258Smlaier
288126258Smlaier#ifndef NOINET6
289126258Smlaiervoid
290126258Smlaierncpaddr_setip6(struct ncpaddr *addr, const struct in6_addr *ip6)
291130613Smlaier{
292130613Smlaier  addr->ncpaddr_family = AF_INET6;
293130613Smlaier  addr->ncpaddr_ip6addr = *ip6;
294126258Smlaier}
295130613Smlaier
296130613Smlaierint
297130613Smlaierncpaddr_getip6(const struct ncpaddr *addr, struct in6_addr *ip6)
298130613Smlaier{
299130613Smlaier  if (addr->ncpaddr_family != AF_INET6)
300130613Smlaier    return 0;
301130613Smlaier  *ip6 = addr->ncpaddr_ip6addr;
302126258Smlaier  return 1;
303130613Smlaier}
304130613Smlaier#endif
305130613Smlaier
306130613Smlaiervoid
307130613Smlaierncpaddr_getsa(const struct ncpaddr *addr, struct sockaddr_storage *host)
308130613Smlaier{
309130613Smlaier  struct sockaddr_in *host4 = (struct sockaddr_in *)host;
310130613Smlaier#ifndef NOINET6
311130613Smlaier  struct sockaddr_in6 *host6 = (struct sockaddr_in6 *)host;
312130613Smlaier#endif
313130613Smlaier
314130613Smlaier  memset(host, '\0', sizeof(*host));
315130613Smlaier
316127145Smlaier  switch (addr->ncpaddr_family) {
317126409Smlaier  case AF_INET:
318126409Smlaier    host4->sin_family = AF_INET;
319126258Smlaier    host4->sin_len = sizeof(*host4);
320126409Smlaier    host4->sin_addr = addr->ncpaddr_ip4addr;
321130613Smlaier    break;
322126258Smlaier
323126258Smlaier#ifndef NOINET6
324126258Smlaier  case AF_INET6:
325130613Smlaier    host6->sin6_family = AF_INET6;
326130613Smlaier    host6->sin6_len = sizeof(*host6);
327130613Smlaier    host6->sin6_addr = addr->ncpaddr_ip6addr;
328130613Smlaier    break;
329130613Smlaier#endif
330130613Smlaier
331130613Smlaier  default:
332130613Smlaier    host->ss_family = AF_UNSPEC;
333130613Smlaier    break;
334130613Smlaier  }
335130613Smlaier}
336130613Smlaier
337130613Smlaiervoid
338130613Smlaierncpaddr_setsa(struct ncpaddr *addr, const struct sockaddr *host)
339130613Smlaier{
340130613Smlaier  const struct sockaddr_in *host4 = (const struct sockaddr_in *)host;
341130613Smlaier#ifndef NOINET6
342130613Smlaier  const struct sockaddr_in6 *host6 = (const struct sockaddr_in6 *)host;
343130613Smlaier#endif
344130613Smlaier
345130613Smlaier  switch (host->sa_family) {
346130613Smlaier  case AF_INET:
347130613Smlaier    addr->ncpaddr_family = AF_INET;
348130613Smlaier    addr->ncpaddr_ip4addr = host4->sin_addr;
349130613Smlaier    break;
350130613Smlaier
351130613Smlaier#ifndef NOINET6
352130613Smlaier  case AF_INET6:
353130613Smlaier    if (IN6_IS_ADDR_V4MAPPED(&host6->sin6_addr)) {
354130613Smlaier      addr->ncpaddr_family = AF_INET;
355130613Smlaier      addr->ncpaddr_ip4addr.s_addr =
356130613Smlaier        *(const u_int32_t *)(host6->sin6_addr.s6_addr + 12);
357130613Smlaier    } else {
358130613Smlaier      addr->ncpaddr_family = AF_INET6;
359130613Smlaier      addr->ncpaddr_ip6addr = host6->sin6_addr;
360130613Smlaier    }
361130613Smlaier    break;
362130613Smlaier#endif
363130613Smlaier
364130613Smlaier  default:
365130613Smlaier    addr->ncpaddr_family = AF_UNSPEC;
366130613Smlaier  }
367130613Smlaier}
368130613Smlaier
369130613Smlaierstatic char *
370130613Smlaierncpaddr_ntowa(const struct ncpaddr *addr)
371130613Smlaier{
372130613Smlaier  static char res[NCP_ASCIIBUFFERSIZE];
373126258Smlaier#ifndef NOINET6
374126258Smlaier  struct sockaddr_in6 sin6;
375126258Smlaier#endif
376126258Smlaier
377126258Smlaier  switch (addr->ncpaddr_family) {
378126258Smlaier  case AF_INET:
379126258Smlaier    snprintf(res, sizeof res, "%s", inet_ntoa(addr->ncpaddr_ip4addr));
380130613Smlaier    return res;
381126258Smlaier
382130613Smlaier#ifndef NOINET6
383126258Smlaier  case AF_INET6:
384130613Smlaier    memset(&sin6, '\0', sizeof(sin6));
385126258Smlaier    sin6.sin6_len = sizeof(sin6);
386130613Smlaier    sin6.sin6_family = AF_INET6;
387126258Smlaier    sin6.sin6_addr = addr->ncpaddr_ip6addr;
388126258Smlaier#if 0
389126258Smlaier    adjust_linklocal(&sin6);
390126258Smlaier#endif
391126258Smlaier#ifdef NI_WITHSCOPEID
392130613Smlaier    if (getnameinfo((struct sockaddr *)&sin6, sizeof sin6, res, sizeof(res),
393126258Smlaier                    NULL, 0, NI_WITHSCOPEID | NI_NUMERICHOST) != 0)
394130613Smlaier#else
395126258Smlaier    if (getnameinfo((struct sockaddr *)&sin6, sizeof sin6, res, sizeof(res),
396130613Smlaier                    NULL, 0, NI_NUMERICHOST) != 0)
397126258Smlaier#endif
398130613Smlaier      break;
399126258Smlaier
400130613Smlaier    return res;
401126258Smlaier#endif
402130613Smlaier  }
403126258Smlaier
404130613Smlaier  snprintf(res, sizeof res, "<AF_UNSPEC>");
405126258Smlaier  return res;
406130613Smlaier}
407126258Smlaier
408130613Smlaierconst char *
409126258Smlaierncpaddr_ntoa(const struct ncpaddr *addr)
410130613Smlaier{
411126258Smlaier  return ncpaddr_ntowa(addr);
412130613Smlaier}
413126258Smlaier
414130613Smlaier
415126258Smlaierint
416130613Smlaierncpaddr_aton(struct ncpaddr *addr, struct ncp *ncp, const char *data)
417126258Smlaier{
418130613Smlaier  struct ncprange range;
419126258Smlaier
420130613Smlaier  if (!ncprange_aton(&range, ncp, data))
421126258Smlaier    return 0;
422130613Smlaier
423126258Smlaier  if (range.ncprange_family == AF_INET && range.ncprange_ip4width != 32 &&
424126258Smlaier      range.ncprange_ip4addr.s_addr != INADDR_ANY) {
425126258Smlaier    log_Printf(LogWARN, "ncpaddr_aton: %s: Only 32 bits allowed\n", data);
426126258Smlaier    return 0;
427126258Smlaier  }
428130613Smlaier
429126258Smlaier#ifndef NOINET6
430130613Smlaier  if (range.ncprange_family == AF_INET6 && range.ncprange_ip6width != 128 &&
431126258Smlaier      !IN6_IS_ADDR_UNSPECIFIED(&range.ncprange_ip6addr)) {
432126258Smlaier    log_Printf(LogWARN, "ncpaddr_aton: %s: Only 128 bits allowed\n", data);
433126258Smlaier    return 0;
434126258Smlaier  }
435126258Smlaier#endif
436130613Smlaier
437130613Smlaier  switch (range.ncprange_family) {
438130613Smlaier  case AF_INET:
439130613Smlaier    addr->ncpaddr_family = range.ncprange_family;
440130613Smlaier    addr->ncpaddr_ip4addr = range.ncprange_ip4addr;
441130613Smlaier    return 1;
442130613Smlaier
443130613Smlaier#ifndef NOINET6
444130613Smlaier  case AF_INET6:
445130613Smlaier    addr->ncpaddr_family = range.ncprange_family;
446130613Smlaier    addr->ncpaddr_ip6addr = range.ncprange_ip6addr;
447130613Smlaier    return 1;
448130613Smlaier#endif
449130613Smlaier  }
450130613Smlaier
451130613Smlaier  return 0;
452130613Smlaier}
453130613Smlaier
454130613Smlaiervoid
455130613Smlaierncprange_init(struct ncprange *range)
456130613Smlaier{
457130613Smlaier  range->ncprange_family = AF_UNSPEC;
458130613Smlaier}
459130613Smlaier
460130613Smlaierint
461130613Smlaierncprange_isset(const struct ncprange *range)
462126258Smlaier{
463130613Smlaier  return range->ncprange_family != AF_UNSPEC;
464130613Smlaier}
465130613Smlaier
466130613Smlaierint
467130613Smlaierncprange_equal(const struct ncprange *range, const struct ncprange *cmp)
468130613Smlaier{
469130613Smlaier  if (range->ncprange_family != cmp->ncprange_family)
470130613Smlaier    return 0;
471130613Smlaier
472130613Smlaier  switch (range->ncprange_family) {
473130613Smlaier  case AF_INET:
474130613Smlaier    if (range->ncprange_ip4addr.s_addr != cmp->ncprange_ip4addr.s_addr)
475130613Smlaier      return 0;
476130613Smlaier    return range->ncprange_ip4mask.s_addr == cmp->ncprange_ip4mask.s_addr;
477130613Smlaier
478130613Smlaier#ifndef NOINET6
479130613Smlaier  case AF_INET6:
480130613Smlaier    if (range->ncprange_ip6width != cmp->ncprange_ip6width)
481130613Smlaier      return 0;
482130613Smlaier    return !memcmp(&range->ncprange_ip6addr, &cmp->ncprange_ip6addr,
483130613Smlaier                   sizeof range->ncprange_ip6addr);
484130613Smlaier#endif
485130613Smlaier
486130613Smlaier  case AF_UNSPEC:
487130613Smlaier    return 1;
488130613Smlaier  }
489130613Smlaier
490130613Smlaier  return 0;
491130613Smlaier}
492130613Smlaier
493130613Smlaierint
494130613Smlaierncprange_isdefault(const struct ncprange *range)
495130613Smlaier{
496130613Smlaier  switch (range->ncprange_family) {
497130613Smlaier  case AF_INET:
498130613Smlaier    if (range->ncprange_ip4addr.s_addr == INADDR_ANY)
499130613Smlaier      return 1;
500130613Smlaier    break;
501130613Smlaier
502130613Smlaier#ifndef NOINET6
503130613Smlaier  case AF_INET6:
504130613Smlaier    if (range->ncprange_ip6width == 0 &&
505130613Smlaier        IN6_IS_ADDR_UNSPECIFIED(&range->ncprange_ip6addr))
506130613Smlaier      return 1;
507130613Smlaier    break;
508130613Smlaier#endif
509130613Smlaier  }
510130613Smlaier
511130613Smlaier  return 0;
512130613Smlaier}
513130613Smlaier
514130613Smlaiervoid
515130613Smlaierncprange_setdefault(struct ncprange *range, int af)
516130613Smlaier{
517130613Smlaier  memset(range, '\0', sizeof *range);
518130613Smlaier  range->ncprange_family = af;
519130613Smlaier}
520130613Smlaier
521130613Smlaierint
522130613Smlaierncprange_contains(const struct ncprange *range, const struct ncpaddr *addr)
523130613Smlaier{
524130613Smlaier#ifndef NOINET6
525130613Smlaier  const u_char masks[] = { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
526130613Smlaier  const u_char *addrp, *rangep;
527130613Smlaier  int bits;
528126258Smlaier#endif
529126258Smlaier
530126258Smlaier  if (range->ncprange_family != addr->ncpaddr_family)
531126258Smlaier    return 0;
532126258Smlaier
533126258Smlaier  switch (range->ncprange_family) {
534126258Smlaier  case AF_INET:
535126258Smlaier    return !((addr->ncpaddr_ip4addr.s_addr ^ range->ncprange_ip4addr.s_addr) &
536126258Smlaier             range->ncprange_ip4mask.s_addr);
537126258Smlaier
538126258Smlaier#ifndef NOINET6
539126258Smlaier  case AF_INET6:
540126258Smlaier    rangep = (const u_char *)range->ncprange_ip6addr.s6_addr;
541126258Smlaier    addrp = (const u_char *)addr->ncpaddr_ip6addr.s6_addr;
542126258Smlaier
543126258Smlaier    for (bits = range->ncprange_ip6width; bits > 0; bits -= 8)
544126258Smlaier      if ((*addrp++ ^ *rangep++) & masks[bits > 7 ? 7 : bits - 1])
545126258Smlaier        return 0;
546126258Smlaier
547126258Smlaier    return 1;
548130613Smlaier#endif
549126258Smlaier  }
550130613Smlaier
551130613Smlaier  return 0;
552130613Smlaier}
553126258Smlaier
554130613Smlaierint
555130613Smlaierncprange_containsip4(const struct ncprange *range, struct in_addr addr)
556130613Smlaier{
557130613Smlaier  switch (range->ncprange_family) {
558130613Smlaier  case AF_INET:
559126258Smlaier    return !((addr.s_addr ^ range->ncprange_ip4addr.s_addr) &
560130613Smlaier             range->ncprange_ip4mask.s_addr);
561130613Smlaier  }
562130613Smlaier
563130613Smlaier  return 0;
564130613Smlaier}
565130613Smlaier
566130613Smlaiervoid
567130613Smlaierncprange_copy(struct ncprange *range, const struct ncprange *from)
568130613Smlaier{
569126258Smlaier  switch (from->ncprange_family) {
570130613Smlaier  case AF_INET:
571130613Smlaier    range->ncprange_family = AF_INET;
572130613Smlaier    range->ncprange_ip4addr = from->ncprange_ip4addr;
573130613Smlaier    range->ncprange_ip4mask = from->ncprange_ip4mask;
574130613Smlaier    range->ncprange_ip4width = from->ncprange_ip4width;
575130613Smlaier    break;
576130613Smlaier
577130613Smlaier#ifndef NOINET6
578130613Smlaier  case AF_INET6:
579130613Smlaier    range->ncprange_family = AF_INET6;
580130613Smlaier    range->ncprange_ip6addr = from->ncprange_ip6addr;
581126258Smlaier    range->ncprange_ip6width = from->ncprange_ip6width;
582126258Smlaier    break;
583130613Smlaier#endif
584130613Smlaier
585130613Smlaier  default:
586130613Smlaier    range->ncprange_family = AF_UNSPEC;
587130613Smlaier  }
588130613Smlaier}
589130613Smlaier
590130613Smlaiervoid
591130613Smlaierncprange_set(struct ncprange *range, const struct ncpaddr *addr, int width)
592130613Smlaier{
593130613Smlaier  ncprange_sethost(range, addr);
594130613Smlaier  ncprange_setwidth(range, width);
595130613Smlaier}
596130613Smlaier
597130613Smlaiervoid
598130613Smlaierncprange_sethost(struct ncprange *range, const struct ncpaddr *from)
599130613Smlaier{
600130613Smlaier  switch (from->ncpaddr_family) {
601130613Smlaier  case AF_INET:
602130613Smlaier    range->ncprange_family = AF_INET;
603130613Smlaier    range->ncprange_ip4addr = from->ncpaddr_ip4addr;
604130613Smlaier    if (from->ncpaddr_ip4addr.s_addr == INADDR_ANY) {
605130613Smlaier      range->ncprange_ip4mask.s_addr = INADDR_ANY;
606130613Smlaier      range->ncprange_ip4width = 0;
607130613Smlaier    } else {
608130613Smlaier      range->ncprange_ip4mask.s_addr = INADDR_BROADCAST;
609130613Smlaier      range->ncprange_ip4width = 32;
610130613Smlaier    }
611130613Smlaier    break;
612130613Smlaier
613130613Smlaier#ifndef NOINET6
614130613Smlaier  case AF_INET6:
615130613Smlaier    range->ncprange_family = AF_INET6;
616130613Smlaier    range->ncprange_ip6addr = from->ncpaddr_ip6addr;
617130613Smlaier    range->ncprange_ip6width = 128;
618130613Smlaier    break;
619130613Smlaier#endif
620130613Smlaier
621126258Smlaier  default:
622130613Smlaier    range->ncprange_family = AF_UNSPEC;
623130613Smlaier  }
624126258Smlaier}
625130613Smlaier
626126258Smlaierint
627130613Smlaierncprange_ishost(const struct ncprange *range)
628130613Smlaier{
629130613Smlaier  switch (range->ncprange_family) {
630130613Smlaier  case AF_INET:
631130613Smlaier    return range->ncprange_ip4width == 32;
632130613Smlaier#ifndef NOINET6
633130613Smlaier  case AF_INET6:
634130613Smlaier    return range->ncprange_ip6width == 128;
635130613Smlaier#endif
636130613Smlaier  }
637130613Smlaier
638130613Smlaier  return (0);
639130613Smlaier}
640130613Smlaier
641130613Smlaierint
642130613Smlaierncprange_setwidth(struct ncprange *range, int width)
643130613Smlaier{
644130613Smlaier  switch (range->ncprange_family) {
645130613Smlaier  case AF_INET:
646130613Smlaier    if (width < 0 || width > 32)
647130613Smlaier      break;
648130613Smlaier    range->ncprange_ip4width = width;
649130613Smlaier    range->ncprange_ip4mask = bits2mask4(width);
650130613Smlaier    break;
651130613Smlaier
652130613Smlaier#ifndef NOINET6
653130613Smlaier  case AF_INET6:
654130613Smlaier    if (width < 0 || width > 128)
655130613Smlaier      break;
656130613Smlaier    range->ncprange_ip6width = width;
657130613Smlaier    break;
658130613Smlaier#endif
659130613Smlaier
660130613Smlaier  case AF_UNSPEC:
661130613Smlaier    return 1;
662130613Smlaier  }
663130613Smlaier
664130613Smlaier  return 0;
665130613Smlaier}
666130613Smlaier
667130613Smlaiervoid
668130613Smlaierncprange_setip4host(struct ncprange *range, struct in_addr from)
669130613Smlaier{
670130613Smlaier  range->ncprange_family = AF_INET;
671130613Smlaier  range->ncprange_ip4addr = from;
672130613Smlaier  if (from.s_addr == INADDR_ANY) {
673130613Smlaier    range->ncprange_ip4mask.s_addr = INADDR_ANY;
674130613Smlaier    range->ncprange_ip4width = 0;
675130613Smlaier  } else {
676130613Smlaier    range->ncprange_ip4mask.s_addr = INADDR_BROADCAST;
677130613Smlaier    range->ncprange_ip4width = 32;
678130613Smlaier  }
679126258Smlaier}
680130613Smlaier
681130613Smlaiervoid
682130613Smlaierncprange_setip4(struct ncprange *range, struct in_addr from, struct in_addr msk)
683126258Smlaier{
684130613Smlaier  range->ncprange_family = AF_INET;
685130613Smlaier  range->ncprange_ip4addr = from;
686126258Smlaier  range->ncprange_ip4mask = msk;
687126258Smlaier  range->ncprange_ip4width = mask42bits(msk);
688126258Smlaier}
689126258Smlaier
690126258Smlaier
691126258Smlaierint
692126258Smlaierncprange_setip4mask(struct ncprange *range, struct in_addr mask)
693126258Smlaier{
694126258Smlaier  if (range->ncprange_family != AF_INET)
695126258Smlaier    return 0;
696126258Smlaier  range->ncprange_ip4mask = mask;
697130613Smlaier  range->ncprange_ip4width = mask42bits(mask);
698130613Smlaier  return 1;
699126258Smlaier}
700126258Smlaier
701126258Smlaiervoid
702126258Smlaierncprange_setsa(struct ncprange *range, const struct sockaddr *host,
703126258Smlaier               const struct sockaddr *mask)
704130613Smlaier{
705126258Smlaier  const struct sockaddr_in *host4 = (const struct sockaddr_in *)host;
706126258Smlaier  const struct sockaddr_in *mask4 = (const struct sockaddr_in *)mask;
707126258Smlaier#ifndef NOINET6
708126258Smlaier  const struct sockaddr_in6 *host6 = (const struct sockaddr_in6 *)host;
709126258Smlaier  const struct sockaddr_in6 *mask6 = (const struct sockaddr_in6 *)mask;
710126258Smlaier#endif
711126258Smlaier
712126258Smlaier  switch (host->sa_family) {
713126258Smlaier  case AF_INET:
714126258Smlaier    range->ncprange_family = AF_INET;
715126258Smlaier    range->ncprange_ip4addr = host4->sin_addr;
716130613Smlaier    if (host4->sin_addr.s_addr == INADDR_ANY) {
717130613Smlaier      range->ncprange_ip4mask.s_addr = INADDR_ANY;
718126258Smlaier      range->ncprange_ip4width = 0;
719126258Smlaier    } else if (mask4 && mask4->sin_family == AF_INET) {
720130613Smlaier      range->ncprange_ip4mask.s_addr = mask4->sin_addr.s_addr;
721126258Smlaier      range->ncprange_ip4width = mask42bits(mask4->sin_addr);
722126258Smlaier    } else {
723126258Smlaier      range->ncprange_ip4mask.s_addr = INADDR_BROADCAST;
724130613Smlaier      range->ncprange_ip4width = 32;
725130613Smlaier    }
726130613Smlaier    break;
727130613Smlaier
728130613Smlaier#ifndef NOINET6
729130613Smlaier  case AF_INET6:
730130613Smlaier    range->ncprange_family = AF_INET6;
731130613Smlaier    range->ncprange_ip6addr = host6->sin6_addr;
732130613Smlaier    if (IN6_IS_ADDR_UNSPECIFIED(&host6->sin6_addr))
733130613Smlaier      range->ncprange_ip6width = 0;
734130613Smlaier    else
735130613Smlaier      range->ncprange_ip6width = mask6 ? mask62bits(&mask6->sin6_addr) : 128;
736130613Smlaier    break;
737130613Smlaier#endif
738130613Smlaier
739130613Smlaier  default:
740130613Smlaier    range->ncprange_family = AF_UNSPEC;
741130613Smlaier  }
742130613Smlaier}
743130613Smlaier
744130613Smlaiervoid
745130613Smlaierncprange_getsa(const struct ncprange *range, struct sockaddr_storage *host,
746130613Smlaier               struct sockaddr_storage *mask)
747130613Smlaier{
748130613Smlaier  struct sockaddr_in *host4 = (struct sockaddr_in *)host;
749130613Smlaier  struct sockaddr_in *mask4 = (struct sockaddr_in *)mask;
750126258Smlaier#ifndef NOINET6
751126258Smlaier  struct sockaddr_in6 *host6 = (struct sockaddr_in6 *)host;
752130613Smlaier  struct sockaddr_in6 *mask6 = (struct sockaddr_in6 *)mask;
753126258Smlaier#endif
754126258Smlaier
755126258Smlaier  memset(host, '\0', sizeof(*host));
756126258Smlaier  if (mask)
757126258Smlaier    memset(mask, '\0', sizeof(*mask));
758126258Smlaier
759126258Smlaier  switch (range->ncprange_family) {
760126258Smlaier  case AF_INET:
761126258Smlaier    host4->sin_family = AF_INET;
762127145Smlaier    host4->sin_len = sizeof(*host4);
763126261Smlaier    host4->sin_addr = range->ncprange_ip4addr;
764126261Smlaier    if (mask4) {
765126258Smlaier      mask4->sin_family = AF_INET;
766126261Smlaier      mask4->sin_len = sizeof(*host4);
767126258Smlaier      mask4->sin_addr = range->ncprange_ip4mask;
768126258Smlaier    }
769127145Smlaier    break;
770126261Smlaier
771126261Smlaier#ifndef NOINET6
772126258Smlaier  case AF_INET6:
773126258Smlaier    host6->sin6_family = AF_INET6;
774126258Smlaier    host6->sin6_len = sizeof(*host6);
775130613Smlaier    host6->sin6_addr = range->ncprange_ip6addr;
776126258Smlaier    if (mask6) {
777127145Smlaier      mask6->sin6_family = AF_INET6;
778126261Smlaier      mask6->sin6_len = sizeof(*host6);
779126261Smlaier      mask6->sin6_addr = bits2mask6(range->ncprange_ip6width);
780126258Smlaier    }
781127145Smlaier    break;
782126261Smlaier#endif
783126261Smlaier
784126261Smlaier  default:
785126258Smlaier    host->ss_family = AF_UNSPEC;
786126261Smlaier    if (mask)
787126258Smlaier      mask->ss_family = AF_UNSPEC;
788126258Smlaier    break;
789126258Smlaier  }
790126258Smlaier}
791126258Smlaier
792126258Smlaierint
793126258Smlaierncprange_getaddr(const struct ncprange *range, struct ncpaddr *addr)
794126258Smlaier{
795126258Smlaier  switch (range->ncprange_family) {
796126258Smlaier  case AF_INET:
797126258Smlaier    addr->ncpaddr_family = AF_INET;
798126258Smlaier    addr->ncpaddr_ip4addr = range->ncprange_ip4addr;
799127145Smlaier    return 1;
800126261Smlaier#ifndef NOINET6
801126261Smlaier  case AF_INET6:
802126258Smlaier    addr->ncpaddr_family = AF_INET6;
803126261Smlaier    addr->ncpaddr_ip6addr =  range->ncprange_ip6addr;
804126258Smlaier    return 1;
805126258Smlaier#endif
806127145Smlaier  }
807126261Smlaier
808126261Smlaier  return 0;
809126261Smlaier}
810126258Smlaier
811126261Smlaierint
812126258Smlaierncprange_getip4addr(const struct ncprange *range, struct in_addr *addr)
813126258Smlaier{
814126258Smlaier  if (range->ncprange_family != AF_INET)
815126258Smlaier    return 0;
816126258Smlaier
817126258Smlaier  *addr = range->ncprange_ip4addr;
818126258Smlaier  return 1;
819126258Smlaier}
820126258Smlaier
821126258Smlaierint
822126258Smlaierncprange_getip4mask(const struct ncprange *range, struct in_addr *mask)
823126258Smlaier{
824126258Smlaier  switch (range->ncprange_family) {
825126258Smlaier  case AF_INET:
826126258Smlaier    *mask = range->ncprange_ip4mask;
827126258Smlaier    return 1;
828126258Smlaier  }
829127145Smlaier
830126261Smlaier  return 0;
831126261Smlaier}
832126258Smlaier
833126261Smlaierint
834126258Smlaierncprange_getwidth(const struct ncprange *range, int *width)
835126258Smlaier{
836126258Smlaier  switch (range->ncprange_family) {
837126258Smlaier  case AF_INET:
838126258Smlaier    *width = range->ncprange_ip4width;
839130613Smlaier    return 1;
840126258Smlaier#ifndef NOINET6
841130613Smlaier  case AF_INET6:
842126258Smlaier    *width = range->ncprange_ip6width;
843130613Smlaier    return 1;
844130613Smlaier#endif
845126258Smlaier  }
846127145Smlaier
847130613Smlaier  return 0;
848126261Smlaier}
849130613Smlaier
850126261Smlaierconst char *
851130613Smlaierncprange_ntoa(const struct ncprange *range)
852130613Smlaier{
853130613Smlaier  char *res;
854130613Smlaier  struct ncpaddr addr;
855130613Smlaier  int len;
856130613Smlaier
857130613Smlaier  if (!ncprange_getaddr(range, &addr))
858130613Smlaier    return "<AF_UNSPEC>";
859130613Smlaier
860130613Smlaier  res = ncpaddr_ntowa(&addr);
861130613Smlaier  len = strlen(res);
862130613Smlaier  if (len >= NCP_ASCIIBUFFERSIZE - 1)
863130613Smlaier    return res;
864126258Smlaier
865130613Smlaier  switch (range->ncprange_family) {
866130613Smlaier  case AF_INET:
867130613Smlaier    if (range->ncprange_ip4width == -1) {
868130613Smlaier      /* A non-contiguous mask */
869126258Smlaier      for (; len >= 3; res[len -= 2] = '\0')
870130613Smlaier        if (strcmp(res + len - 2, ".0"))
871130613Smlaier          break;
872130613Smlaier      snprintf(res + len, sizeof res - len, "&0x%08lx",
873130613Smlaier               (unsigned long)ntohl(range->ncprange_ip4mask.s_addr));
874130613Smlaier    } else if (range->ncprange_ip4width < 32)
875130613Smlaier      snprintf(res + len, sizeof res - len, "/%d", range->ncprange_ip4width);
876127145Smlaier
877130613Smlaier    return res;
878126261Smlaier
879130613Smlaier#ifndef NOINET6
880126261Smlaier  case AF_INET6:
881130613Smlaier    if (range->ncprange_ip6width != 128)
882130613Smlaier      snprintf(res + len, sizeof res - len, "/%d", range->ncprange_ip6width);
883130613Smlaier
884130613Smlaier    return res;
885130613Smlaier#endif
886130613Smlaier  }
887130613Smlaier
888130613Smlaier  return "<AF_UNSPEC>";
889130613Smlaier}
890130613Smlaier
891130613Smlaier#ifndef NOINET6
892130613Smlaierint
893130613Smlaierncprange_scopeid(const struct ncprange *range)
894130613Smlaier{
895130613Smlaier  const struct in6_addr *sin6;
896130613Smlaier  int scopeid = -1;
897130613Smlaier
898126258Smlaier  if (range->ncprange_family == AF_INET6) {
899130613Smlaier    sin6 = &range->ncprange_ip6addr;
900130613Smlaier    if (IN6_IS_ADDR_LINKLOCAL(sin6) || IN6_IS_ADDR_MC_LINKLOCAL(sin6))
901130613Smlaier      if ((scopeid = ntohs(*(const u_short *)&sin6->s6_addr[2])) == 0)
902130613Smlaier        scopeid = -1;
903130613Smlaier  }
904130613Smlaier
905130613Smlaier  return scopeid;
906130613Smlaier}
907130613Smlaier#endif
908130613Smlaier
909130613Smlaierint
910130613Smlaierncprange_aton(struct ncprange *range, struct ncp *ncp, const char *data)
911130613Smlaier{
912130613Smlaier  int bits, len;
913130613Smlaier  char *wp;
914130613Smlaier  const char *cp;
915130613Smlaier  char *s;
916130613Smlaier
917130613Smlaier  len = strcspn(data, "/");
918130613Smlaier
919130613Smlaier  if (ncp && strncasecmp(data, "HISADDR", len) == 0) {
920130613Smlaier    range->ncprange_family = AF_INET;
921130613Smlaier    range->ncprange_ip4addr = ncp->ipcp.peer_ip;
922130613Smlaier    range->ncprange_ip4mask.s_addr = INADDR_BROADCAST;
923130613Smlaier    range->ncprange_ip4width = 32;
924126258Smlaier    return 1;
925130613Smlaier#ifndef NOINET6
926126258Smlaier  } else if (ncp && strncasecmp(data, "HISADDR6", len) == 0) {
927130613Smlaier    range->ncprange_family = AF_INET6;
928130613Smlaier    range->ncprange_ip6addr = ncp->ipv6cp.hisaddr.ncpaddr_ip6addr;
929130613Smlaier    range->ncprange_ip6width = 128;
930130613Smlaier    return 1;
931130613Smlaier#endif
932130613Smlaier  } else if (ncp && strncasecmp(data, "MYADDR", len) == 0) {
933130613Smlaier    range->ncprange_family = AF_INET;
934130613Smlaier    range->ncprange_ip4addr = ncp->ipcp.my_ip;
935130613Smlaier    range->ncprange_ip4mask.s_addr = INADDR_BROADCAST;
936130613Smlaier    range->ncprange_ip4width = 32;
937130613Smlaier    return 1;
938130613Smlaier#ifndef NOINET6
939130613Smlaier  } else if (ncp && strncasecmp(data, "MYADDR6", len) == 0) {
940130613Smlaier    range->ncprange_family = AF_INET6;
941130613Smlaier    range->ncprange_ip6addr = ncp->ipv6cp.myaddr.ncpaddr_ip6addr;
942126258Smlaier    range->ncprange_ip6width = 128;
943126258Smlaier    return 1;
944126258Smlaier#endif
945126258Smlaier  } else if (ncp && strncasecmp(data, "DNS0", len) == 0) {
946126258Smlaier    range->ncprange_family = AF_INET;
947126258Smlaier    range->ncprange_ip4addr = ncp->ipcp.ns.dns[0];
948126258Smlaier    range->ncprange_ip4mask.s_addr = INADDR_BROADCAST;
949126258Smlaier    range->ncprange_ip4width = 32;
950126258Smlaier    return 1;
951126258Smlaier  } else if (ncp && strncasecmp(data, "DNS1", len) == 0) {
952126258Smlaier    range->ncprange_family = AF_INET;
953126258Smlaier    range->ncprange_ip4addr = ncp->ipcp.ns.dns[1];
954126258Smlaier    range->ncprange_ip4mask.s_addr = INADDR_BROADCAST;
955126258Smlaier    range->ncprange_ip4width = 32;
956126258Smlaier    return 1;
957126258Smlaier  }
958126258Smlaier
959126258Smlaier  s = (char *)alloca(len + 1);
960126258Smlaier  strncpy(s, data, len);
961126258Smlaier  s[len] = '\0';
962126258Smlaier  bits = -1;
963126258Smlaier
964126258Smlaier  if (data[len] != '\0') {
965126258Smlaier    bits = strtol(data + len + 1, &wp, 0);
966126258Smlaier    if (*wp || wp == data + len + 1 || bits < 0 || bits > 128) {
967126258Smlaier      log_Printf(LogWARN, "ncprange_aton: bad mask width.\n");
968126258Smlaier      return 0;
969126258Smlaier    }
970126258Smlaier  }
971126258Smlaier
972126258Smlaier  if ((cp = strchr(data, ':')) == NULL) {
973126258Smlaier    range->ncprange_family = AF_INET;
974126258Smlaier
975126258Smlaier    range->ncprange_ip4addr = GetIpAddr(s);
976126258Smlaier
977126258Smlaier    if (range->ncprange_ip4addr.s_addr == INADDR_NONE) {
978126258Smlaier      log_Printf(LogWARN, "ncprange_aton: %s: Bad address\n", s);
979126258Smlaier      return 0;
980126258Smlaier    }
981126258Smlaier
982126258Smlaier    if (range->ncprange_ip4addr.s_addr == INADDR_ANY) {
983126258Smlaier      range->ncprange_ip4mask.s_addr = INADDR_ANY;
984126258Smlaier      range->ncprange_ip4width = 0;
985126258Smlaier    } else if (bits == -1) {
986126258Smlaier      range->ncprange_ip4mask.s_addr = INADDR_BROADCAST;
987126258Smlaier      range->ncprange_ip4width = 32;
988126258Smlaier    } else if (bits > 32) {
989126258Smlaier      log_Printf(LogWARN, "ncprange_aton: bad mask width.\n");
990126258Smlaier      return 0;
991126258Smlaier    } else {
992126258Smlaier      range->ncprange_ip4mask = bits2mask4(bits);
993126258Smlaier      range->ncprange_ip4width = bits;
994126258Smlaier    }
995126258Smlaier
996126258Smlaier    return 1;
997126258Smlaier#ifndef NOINET6
998126258Smlaier  } else if (strchr(cp + 1, ':') != NULL) {
999126258Smlaier    range->ncprange_family = AF_INET6;
1000126258Smlaier
1001126258Smlaier    if (inet_pton(AF_INET6, s, &range->ncprange_ip6addr) != 1) {
1002126258Smlaier      log_Printf(LogWARN, "ncprange_aton: %s: Bad address\n", s);
1003126258Smlaier      return 0;
1004126258Smlaier    }
1005126258Smlaier
1006126258Smlaier    if (IN6_IS_ADDR_UNSPECIFIED(&range->ncprange_ip6addr))
1007126258Smlaier      range->ncprange_ip6width = 0;
1008126258Smlaier    else
1009126258Smlaier      range->ncprange_ip6width = (bits == -1) ? 128 : bits;
1010126258Smlaier    return 1;
1011126258Smlaier#endif
1012126258Smlaier  }
1013126258Smlaier
1014126258Smlaier  return 0;
1015126258Smlaier}
1016126258Smlaier