xref: /netbsd/external/bsd/ipf/dist/lib/alist_new.c (revision f52ace7a)
1*f52ace7aSdarrenr /*	$NetBSD: alist_new.c,v 1.2 2012/07/22 14:27:36 darrenr Exp $	*/
226945a25Schristos 
326945a25Schristos /*
4c50c2f6fSdarrenr  * Copyright (C) 2012 by Darren Reed.
526945a25Schristos  *
626945a25Schristos  * See the IPFILTER.LICENCE file for details on licencing.
726945a25Schristos  *
8*f52ace7aSdarrenr  * Id: alist_new.c,v 1.1.1.2 2012/07/22 13:44:38 darrenr Exp $
926945a25Schristos  */
1026945a25Schristos 
1126945a25Schristos #include "ipf.h"
1226945a25Schristos #include <ctype.h>
1326945a25Schristos 
1426945a25Schristos alist_t *
alist_new(int family,char * host)1526945a25Schristos alist_new(int family, char *host)
1626945a25Schristos {
1726945a25Schristos 	int a, b, c, d, bits;
1826945a25Schristos 	char *slash;
1926945a25Schristos 	alist_t *al;
2026945a25Schristos 	u_int mask;
2126945a25Schristos 
2226945a25Schristos 	if (family == AF_UNSPEC) {
2326945a25Schristos 		if (strchr(host, ':') != NULL)
2426945a25Schristos 			family = AF_INET6;
2526945a25Schristos 		else
2626945a25Schristos 			family = AF_INET;
2726945a25Schristos 	}
2826945a25Schristos 	if (family != AF_INET && family != AF_INET6)
2926945a25Schristos 		return NULL;
3026945a25Schristos 
3126945a25Schristos 	al = calloc(1, sizeof(*al));
3226945a25Schristos 	if (al == NULL) {
3326945a25Schristos 		fprintf(stderr, "alist_new out of memory\n");
3426945a25Schristos 		return NULL;
3526945a25Schristos 	}
3626945a25Schristos 
3726945a25Schristos 	while (ISSPACE(*host))
3826945a25Schristos 		host++;
3926945a25Schristos 
4026945a25Schristos 	if (*host == '!') {
4126945a25Schristos 		al->al_not = 1;
4226945a25Schristos 		host++;
4326945a25Schristos 		while (ISSPACE(*host))
4426945a25Schristos 			host++;
4526945a25Schristos 	}
4626945a25Schristos 
4726945a25Schristos 	bits = -1;
4826945a25Schristos 	slash = strchr(host, '/');
4926945a25Schristos 	if (slash != NULL) {
5026945a25Schristos 		*slash = '\0';
5126945a25Schristos 		bits = atoi(slash + 1);
5226945a25Schristos 	}
5326945a25Schristos 
5426945a25Schristos 	if (family == AF_INET) {
5526945a25Schristos 		if (bits > 32)
5626945a25Schristos 			goto bad;
5726945a25Schristos 
5826945a25Schristos 		a = b = c = d = -1;
5926945a25Schristos 		sscanf(host, "%d.%d.%d.%d", &a, &b, &c, &d);
6026945a25Schristos 
6126945a25Schristos 		if (bits > 0 && bits < 33) {
6226945a25Schristos 			mask = 0xffffffff << (32 - bits);
6326945a25Schristos 		} else if (b == -1) {
6426945a25Schristos 			mask = 0xff000000;
6526945a25Schristos 			b = c = d = 0;
6626945a25Schristos 		} else if (c == -1) {
6726945a25Schristos 			mask = 0xffff0000;
6826945a25Schristos 			c = d = 0;
6926945a25Schristos 		} else if (d == -1) {
7026945a25Schristos 			mask = 0xffffff00;
7126945a25Schristos 			d = 0;
7226945a25Schristos 		} else {
7326945a25Schristos 			mask = 0xffffffff;
7426945a25Schristos 		}
7526945a25Schristos 		al->al_mask = htonl(mask);
7626945a25Schristos 	} else {
7726945a25Schristos 		if (bits > 128)
7826945a25Schristos 			goto bad;
7926945a25Schristos 		fill6bits(bits, al->al_i6mask.i6);
8026945a25Schristos 	}
8126945a25Schristos 
8226945a25Schristos 	if (gethost(family, host, &al->al_i6addr) == -1) {
8326945a25Schristos 		if (slash != NULL)
8426945a25Schristos 			*slash = '/';
8526945a25Schristos 		fprintf(stderr, "Cannot parse hostname\n");
8626945a25Schristos 		goto bad;
8726945a25Schristos 	}
8826945a25Schristos 	al->al_family = family;
8926945a25Schristos 	if (slash != NULL)
9026945a25Schristos 		*slash = '/';
9126945a25Schristos 	return al;
9226945a25Schristos bad:
9326945a25Schristos 	free(al);
9426945a25Schristos 	return NULL;
9526945a25Schristos }
96