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