1170263Sdarrenr/*
2255332Scy * Copyright (C) 2012 by Darren Reed.
3170263Sdarrenr *
4170263Sdarrenr * See the IPFILTER.LICENCE file for details on licencing.
5170263Sdarrenr *
6255332Scy * $Id: alist_new.c,v 1.5.2.2 2012/07/22 08:04:24 darren_r Exp $
7170263Sdarrenr */
8170263Sdarrenr
9170263Sdarrenr#include "ipf.h"
10255332Scy#include <ctype.h>
11170263Sdarrenr
12255332Scyalist_t *
13255332Scyalist_new(int family, char *host)
14170263Sdarrenr{
15170263Sdarrenr	int a, b, c, d, bits;
16255332Scy	char *slash;
17255332Scy	alist_t *al;
18255332Scy	u_int mask;
19170263Sdarrenr
20255332Scy	if (family == AF_UNSPEC) {
21255332Scy		if (strchr(host, ':') != NULL)
22255332Scy			family = AF_INET6;
23255332Scy		else
24255332Scy			family = AF_INET;
25255332Scy	}
26255332Scy	if (family != AF_INET && family != AF_INET6)
27255332Scy		return NULL;
28255332Scy
29170263Sdarrenr	al = calloc(1, sizeof(*al));
30170263Sdarrenr	if (al == NULL) {
31170263Sdarrenr		fprintf(stderr, "alist_new out of memory\n");
32170263Sdarrenr		return NULL;
33170263Sdarrenr	}
34170263Sdarrenr
35255332Scy	while (ISSPACE(*host))
36255332Scy		host++;
37255332Scy
38255332Scy	if (*host == '!') {
39255332Scy		al->al_not = 1;
40255332Scy		host++;
41255332Scy		while (ISSPACE(*host))
42255332Scy			host++;
43255332Scy	}
44255332Scy
45255332Scy	bits = -1;
46170263Sdarrenr	slash = strchr(host, '/');
47170263Sdarrenr	if (slash != NULL) {
48170263Sdarrenr		*slash = '\0';
49170263Sdarrenr		bits = atoi(slash + 1);
50170263Sdarrenr	}
51170263Sdarrenr
52255332Scy	if (family == AF_INET) {
53255332Scy		if (bits > 32)
54255332Scy			goto bad;
55170263Sdarrenr
56255332Scy		a = b = c = d = -1;
57255332Scy		sscanf(host, "%d.%d.%d.%d", &a, &b, &c, &d);
58255332Scy
59255332Scy		if (bits > 0 && bits < 33) {
60255332Scy			mask = 0xffffffff << (32 - bits);
61255332Scy		} else if (b == -1) {
62255332Scy			mask = 0xff000000;
63255332Scy			b = c = d = 0;
64255332Scy		} else if (c == -1) {
65255332Scy			mask = 0xffff0000;
66255332Scy			c = d = 0;
67255332Scy		} else if (d == -1) {
68255332Scy			mask = 0xffffff00;
69255332Scy			d = 0;
70255332Scy		} else {
71255332Scy			mask = 0xffffffff;
72255332Scy		}
73255332Scy		al->al_mask = htonl(mask);
74170263Sdarrenr	} else {
75255332Scy		if (bits > 128)
76255332Scy			goto bad;
77255332Scy		fill6bits(bits, al->al_i6mask.i6);
78170263Sdarrenr	}
79170263Sdarrenr
80255332Scy	if (gethost(family, host, &al->al_i6addr) == -1) {
81172771Sdarrenr		if (slash != NULL)
82172771Sdarrenr			*slash = '/';
83170263Sdarrenr		fprintf(stderr, "Cannot parse hostname\n");
84255332Scy		goto bad;
85170263Sdarrenr	}
86255332Scy	al->al_family = family;
87172771Sdarrenr	if (slash != NULL)
88172771Sdarrenr		*slash = '/';
89170263Sdarrenr	return al;
90255332Scybad:
91255332Scy	free(al);
92255332Scy	return NULL;
93170263Sdarrenr}
94