1 /* $NetBSD: alist_new.c,v 1.2 2012/07/22 14:27:36 darrenr Exp $ */
2
3 /*
4 * Copyright (C) 2012 by Darren Reed.
5 *
6 * See the IPFILTER.LICENCE file for details on licencing.
7 *
8 * Id: alist_new.c,v 1.1.1.2 2012/07/22 13:44:38 darrenr Exp $
9 */
10
11 #include "ipf.h"
12 #include <ctype.h>
13
14 alist_t *
alist_new(int family,char * host)15 alist_new(int family, char *host)
16 {
17 int a, b, c, d, bits;
18 char *slash;
19 alist_t *al;
20 u_int mask;
21
22 if (family == AF_UNSPEC) {
23 if (strchr(host, ':') != NULL)
24 family = AF_INET6;
25 else
26 family = AF_INET;
27 }
28 if (family != AF_INET && family != AF_INET6)
29 return NULL;
30
31 al = calloc(1, sizeof(*al));
32 if (al == NULL) {
33 fprintf(stderr, "alist_new out of memory\n");
34 return NULL;
35 }
36
37 while (ISSPACE(*host))
38 host++;
39
40 if (*host == '!') {
41 al->al_not = 1;
42 host++;
43 while (ISSPACE(*host))
44 host++;
45 }
46
47 bits = -1;
48 slash = strchr(host, '/');
49 if (slash != NULL) {
50 *slash = '\0';
51 bits = atoi(slash + 1);
52 }
53
54 if (family == AF_INET) {
55 if (bits > 32)
56 goto bad;
57
58 a = b = c = d = -1;
59 sscanf(host, "%d.%d.%d.%d", &a, &b, &c, &d);
60
61 if (bits > 0 && bits < 33) {
62 mask = 0xffffffff << (32 - bits);
63 } else if (b == -1) {
64 mask = 0xff000000;
65 b = c = d = 0;
66 } else if (c == -1) {
67 mask = 0xffff0000;
68 c = d = 0;
69 } else if (d == -1) {
70 mask = 0xffffff00;
71 d = 0;
72 } else {
73 mask = 0xffffffff;
74 }
75 al->al_mask = htonl(mask);
76 } else {
77 if (bits > 128)
78 goto bad;
79 fill6bits(bits, al->al_i6mask.i6);
80 }
81
82 if (gethost(family, host, &al->al_i6addr) == -1) {
83 if (slash != NULL)
84 *slash = '/';
85 fprintf(stderr, "Cannot parse hostname\n");
86 goto bad;
87 }
88 al->al_family = family;
89 if (slash != NULL)
90 *slash = '/';
91 return al;
92 bad:
93 free(al);
94 return NULL;
95 }
96