11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*	$OpenBSD: addrmatch.c,v 1.5 2010/02/26 20:29:54 djm Exp $ */
21305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
31305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
41305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 2004-2008 Damien Miller <djm@mindrot.org>
51305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
61305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Permission to use, copy, modify, and distribute this software for any
71305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * purpose with or without fee is hereby granted, provided that the above
81305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * copyright notice and this permission notice appear in all copies.
91305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "includes.h"
201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/types.h>
221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/socket.h>
231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <netinet/in.h>
241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <arpa/inet.h>
251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <netdb.h>
271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <string.h>
281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdlib.h>
291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdio.h>
301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdarg.h>
311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "match.h"
331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "log.h"
341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "xmalloc.h"
351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstruct xaddr {
371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	sa_family_t	af;
381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	union {
391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		struct in_addr		v4;
401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		struct in6_addr		v6;
411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		u_int8_t		addr8[16];
421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		u_int32_t		addr32[4];
431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	} xa;		    /* 128-bit address */
441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int32_t	scope_id;	/* iface scope id for v6 */
451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define v4	xa.v4
461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define v6	xa.v6
471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define addr8	xa.addr8
481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define addr32	xa.addr32
491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood};
501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodaddr_unicast_masklen(int af)
531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (af) {
551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case AF_INET:
561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 32;
571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case AF_INET6:
581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 128;
591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic inline int
651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodmasklen_valid(int af, u_int masklen)
661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (af) {
681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case AF_INET:
691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return masklen <= 32 ? 0 : -1;
701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case AF_INET6:
711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return masklen <= 128 ? 0 : -1;
721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Convert struct sockaddr to struct xaddr
791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Returns 0 on success, -1 on failure.
801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodaddr_sa_to_xaddr(struct sockaddr *sa, socklen_t slen, struct xaddr *xa)
831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct sockaddr_in *in4 = (struct sockaddr_in *)sa;
851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)sa;
861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(xa, '\0', sizeof(*xa));
881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (sa->sa_family) {
901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case AF_INET:
911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (slen < sizeof(*in4))
921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1;
931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xa->af = AF_INET;
941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		memcpy(&xa->v4, &in4->sin_addr, sizeof(xa->v4));
951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case AF_INET6:
971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (slen < sizeof(*in6))
981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1;
991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xa->af = AF_INET6;
1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		memcpy(&xa->v6, &in6->sin6_addr, sizeof(xa->v6));
1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID
1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		xa->scope_id = in6->sin6_scope_id;
1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif
1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		break;
1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 0;
1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Calculate a netmask of length 'l' for address family 'af' and
1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * store it in 'n'.
1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Returns 0 on success, -1 on failure.
1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodaddr_netmask(int af, u_int l, struct xaddr *n)
1191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int i;
1211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (masklen_valid(af, l) != 0 || n == NULL)
1231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
1241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(n, '\0', sizeof(*n));
1261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (af) {
1271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case AF_INET:
1281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		n->af = AF_INET;
1291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (l == 0)
1301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return 0;
1311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		n->v4.s_addr = htonl((0xffffffff << (32 - l)) & 0xffffffff);
1321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
1331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case AF_INET6:
1341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		n->af = AF_INET6;
1351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (i = 0; i < 4 && l >= 32; i++, l -= 32)
1361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			n->addr32[i] = 0xffffffffU;
1371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (i < 4 && l != 0)
1381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			n->addr32[i] = htonl((0xffffffff << (32 - l)) &
1391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    0xffffffff);
1401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
1411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
1421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
1431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
1471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Perform logical AND of addresses 'a' and 'b', storing result in 'dst'.
1481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Returns 0 on success, -1 on failure.
1491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
1501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
1511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodaddr_and(struct xaddr *dst, const struct xaddr *a, const struct xaddr *b)
1521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int i;
1541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (dst == NULL || a == NULL || b == NULL || a->af != b->af)
1561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
1571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memcpy(dst, a, sizeof(*dst));
1591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (a->af) {
1601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case AF_INET:
1611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		dst->v4.s_addr &= b->v4.s_addr;
1621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
1631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case AF_INET6:
1641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		dst->scope_id = a->scope_id;
1651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (i = 0; i < 4; i++)
1661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			dst->addr32[i] &= b->addr32[i];
1671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
1681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
1691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
1701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
1711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
1721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
1741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Compare addresses 'a' and 'b'
1751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Return 0 if addresses are identical, -1 if (a < b) or 1 if (a > b)
1761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
1771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
1781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodaddr_cmp(const struct xaddr *a, const struct xaddr *b)
1791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
1801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int i;
1811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (a->af != b->af)
1831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return a->af == AF_INET6 ? 1 : -1;
1841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
1851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (a->af) {
1861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case AF_INET:
1871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (a->v4.s_addr == b->v4.s_addr)
1881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return 0;
1891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return ntohl(a->v4.s_addr) > ntohl(b->v4.s_addr) ? 1 : -1;
1901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case AF_INET6:
1911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (i = 0; i < 16; i++)
1921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (a->addr8[i] - b->addr8[i] != 0)
1931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				return a->addr8[i] > b->addr8[i] ? 1 : -1;
1941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (a->scope_id == b->scope_id)
1951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return 0;
1961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return a->scope_id > b->scope_id ? 1 : -1;
1971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
1981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
1991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
2031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Parse string address 'p' into 'n'
2041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Returns 0 on success, -1 on failure.
2051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
2061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
2071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodaddr_pton(const char *p, struct xaddr *n)
2081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct addrinfo hints, *ai;
2101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memset(&hints, '\0', sizeof(hints));
2121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	hints.ai_flags = AI_NUMERICHOST;
2131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (p == NULL || getaddrinfo(p, NULL, &hints, &ai) != 0)
2151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
2161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (ai == NULL || ai->ai_addr == NULL)
2181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
2191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (n != NULL &&
2211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	    addr_sa_to_xaddr(ai->ai_addr, ai->ai_addrlen, n) == -1) {
2221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		freeaddrinfo(ai);
2231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
2241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	freeaddrinfo(ai);
2271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 0;
2281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
2311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Perform bitwise negation of address
2321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Returns 0 on success, -1 on failure.
2331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
2341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
2351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodaddr_invert(struct xaddr *n)
2361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int i;
2381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (n == NULL)
2401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (-1);
2411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (n->af) {
2431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case AF_INET:
2441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		n->v4.s_addr = ~n->v4.s_addr;
2451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (0);
2461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case AF_INET6:
2471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (i = 0; i < 4; i++)
2481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			n->addr32[i] = ~n->addr32[i];
2491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (0);
2501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
2511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (-1);
2521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
2561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Calculate a netmask of length 'l' for address family 'af' and
2571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * store it in 'n'.
2581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Returns 0 on success, -1 on failure.
2591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
2601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
2611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodaddr_hostmask(int af, u_int l, struct xaddr *n)
2621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (addr_netmask(af, l, n) == -1 || addr_invert(n) == -1)
2641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (-1);
2651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (0);
2661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
2691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Test whether address 'a' is all zeros (i.e. 0.0.0.0 or ::)
2701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Returns 0 on if address is all-zeros, -1 if not all zeros or on failure.
2711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
2721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
2731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodaddr_is_all0s(const struct xaddr *a)
2741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int i;
2761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	switch (a->af) {
2781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case AF_INET:
2791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (a->v4.s_addr == 0 ? 0 : -1);
2801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	case AF_INET6:;
2811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		for (i = 0; i < 4; i++)
2821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (a->addr32[i] != 0)
2831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				return (-1);
2841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (0);
2851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	default:
2861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (-1);
2871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
2881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
2891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
2901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
2911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Test whether host portion of address 'a', as determined by 'masklen'
2921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * is all zeros.
2931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Returns 0 on if host portion of address is all-zeros,
2941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * -1 if not all zeros or on failure.
2951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
2961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
2971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodaddr_host_is_all0s(const struct xaddr *a, u_int masklen)
2981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
2991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct xaddr tmp_addr, tmp_mask, tmp_result;
3001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	memcpy(&tmp_addr, a, sizeof(tmp_addr));
3021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (addr_hostmask(a->af, masklen, &tmp_mask) == -1)
3031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (-1);
3041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (addr_and(&tmp_result, &tmp_addr, &tmp_mask) == -1)
3051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return (-1);
3061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return (addr_is_all0s(&tmp_result));
3071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
3081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
3101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Parse a CIDR address (x.x.x.x/y or xxxx:yyyy::/z).
3111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Return -1 on parse error, -2 on inconsistency or 0 on success.
3121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
3131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
3141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodaddr_pton_cidr(const char *p, struct xaddr *n, u_int *l)
3151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
3161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct xaddr tmp;
3171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	long unsigned int masklen = 999;
3181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char addrbuf[64], *mp, *cp;
3191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	/* Don't modify argument */
3211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (p == NULL || strlcpy(addrbuf, p, sizeof(addrbuf)) > sizeof(addrbuf))
3221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
3231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((mp = strchr(addrbuf, '/')) != NULL) {
3251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*mp = '\0';
3261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		mp++;
3271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		masklen = strtoul(mp, &cp, 10);
3281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (*mp == '\0' || *cp != '\0' || masklen > 128)
3291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			return -1;
3301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
3311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (addr_pton(addrbuf, &tmp) == -1)
3331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
3341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (mp == NULL)
3361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		masklen = addr_unicast_masklen(tmp.af);
3371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (masklen_valid(tmp.af, masklen) == -1)
3381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -2;
3391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (addr_host_is_all0s(&tmp, masklen) != 0)
3401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -2;
3411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (n != NULL)
3431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		memcpy(n, &tmp, sizeof(*n));
3441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (l != NULL)
3451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		*l = masklen;
3461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return 0;
3481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
3491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodstatic int
3511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodaddr_netmatch(const struct xaddr *host, const struct xaddr *net, u_int masklen)
3521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
3531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct xaddr tmp_mask, tmp_result;
3541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (host->af != net->af)
3561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
3571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (addr_netmask(host->af, masklen, &tmp_mask) == -1)
3591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
3601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (addr_and(&tmp_result, host, &tmp_mask) == -1)
3611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
3621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return addr_cmp(&tmp_result, net);
3631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
3641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
3661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Match "addr" against list pattern list "_list", which may contain a
3671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * mix of CIDR addresses and old-school wildcards.
3681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
3691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * If addr is NULL, then no matching is performed, but _list is parsed
3701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * and checked for well-formedness.
3711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
3721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Returns 1 on match found (never returned when addr == NULL).
3731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Returns 0 on if no match found, or no errors found when addr == NULL.
3741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Returns -1 on negated match found (never returned when addr == NULL).
3751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Returns -2 on invalid list entry.
3761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
3771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
3781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodaddr_match_list(const char *addr, const char *_list)
3791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
3801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *list, *cp, *o;
3811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct xaddr try_addr, match_addr;
3821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int masklen, neg;
3831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int ret = 0, r;
3841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
3851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (addr != NULL && addr_pton(addr, &try_addr) != 0) {
3861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug2("%s: couldn't parse address %.100s", __func__, addr);
3871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
3881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
3891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((o = list = strdup(_list)) == NULL)
3901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
3911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while ((cp = strsep(&list, ",")) != NULL) {
3921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		neg = *cp == '!';
3931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (neg)
3941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			cp++;
3951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (*cp == '\0') {
3961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			ret = -2;
3971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
3981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
3991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Prefer CIDR address matching */
4001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		r = addr_pton_cidr(cp, &match_addr, &masklen);
4011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (r == -2) {
4021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("Inconsistent mask length for "
4031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    "network \"%.100s\"", cp);
4041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			ret = -2;
4051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
4061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else if (r == 0) {
4071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (addr != NULL && addr_netmatch(&try_addr,
4081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood                           &match_addr, masklen) == 0) {
4091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood foundit:
4101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				if (neg) {
4111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					ret = -1;
4121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood					break;
4131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				}
4141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				ret = 1;
4151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			}
4161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			continue;
4171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else {
4181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			/* If CIDR parse failed, try wildcard string match */
4191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (addr != NULL && match_pattern(addr, cp) == 1)
4201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				goto foundit;
4211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
4221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(o);
4241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return ret;
4261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
4271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/*
4291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Match "addr" against list CIDR list "_list". Lexical wildcards and
4301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * negation are not supported. If "addr" == NULL, will verify structure
4311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * of "_list".
4321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood *
4331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Returns 1 on match found (never returned when addr == NULL).
4341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Returns 0 on if no match found, or no errors found when addr == NULL.
4351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Returns -1 on error
4361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */
4371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint
4381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodaddr_match_cidr_list(const char *addr, const char *_list)
4391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{
4401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	char *list, *cp, *o;
4411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	struct xaddr try_addr, match_addr;
4421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	u_int masklen;
4431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	int ret = 0, r;
4441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if (addr != NULL && addr_pton(addr, &try_addr) != 0) {
4461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		debug2("%s: couldn't parse address %.100s", __func__, addr);
4471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return 0;
4481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	if ((o = list = strdup(_list)) == NULL)
4501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		return -1;
4511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	while ((cp = strsep(&list, ",")) != NULL) {
4521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (*cp == '\0') {
4531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("%s: empty entry in list \"%.100s\"",
4541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    __func__, o);
4551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			ret = -1;
4561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
4571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
4581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/*
4601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * NB. This function is called in pre-auth with untrusted data,
4611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * so be extra paranoid about junk reaching getaddrino (via
4621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 * addr_pton_cidr).
4631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		 */
4641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Stop junk from reaching getaddrinfo. +3 is for masklen */
4661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (strlen(cp) > INET6_ADDRSTRLEN + 3) {
4671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("%s: list entry \"%.100s\" too long",
4681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    __func__, cp);
4691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			ret = -1;
4701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
4711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
4721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define VALID_CIDR_CHARS "0123456789abcdefABCDEF.:/"
4731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (strspn(cp, VALID_CIDR_CHARS) != strlen(cp)) {
4741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("%s: list entry \"%.100s\" contains invalid "
4751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    "characters", __func__, cp);
4761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			ret = -1;
4771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
4781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		/* Prefer CIDR address matching */
4801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		r = addr_pton_cidr(cp, &match_addr, &masklen);
4811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		if (r == -1) {
4821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("Invalid network entry \"%.100s\"", cp);
4831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			ret = -1;
4841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
4851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else if (r == -2) {
4861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			error("Inconsistent mask length for "
4871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    "network \"%.100s\"", cp);
4881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			ret = -1;
4891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			break;
4901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		} else if (r == 0 && addr != NULL) {
4911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			if (addr_netmatch(&try_addr, &match_addr,
4921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			    masklen) == 0)
4931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood				ret = 1;
4941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood			continue;
4951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood		}
4961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	}
4971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	xfree(o);
4981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood
4991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood	return ret;
5001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood}
501