xref: /freebsd/sbin/ipf/libipf/parsewhoisline.c (revision ec0ea6efa1ad229d75c394c1a9b9cac33af2b1d3)
1 /*
2  * Copyright (C) 2012 by Darren Reed.
3  *
4  * See the IPFILTER.LICENCE file for details on licencing.
5  *
6  * $Id: parsewhoisline.c,v 1.2.2.5 2012/07/22 08:04:24 darren_r Exp $
7  */
8 #include "ipf.h"
9 
10 /*
11 Microsoft Corp MICROSOFT19 (NET-198-136-97-0-1) 198.137.97.0 - 198.137.97.255
12 Microsoft Corp SAVV-S233053-6 (NET-206-79-74-32-1) 206.79.74.32 - 206.79.74.47
13  */
14 int
15 parsewhoisline(line, addrp, maskp)
16 	char *line;
17 	addrfamily_t *addrp;
18 	addrfamily_t *maskp;
19 {
20 	struct in_addr a1, a2;
21 	char *src = line;
22 	char *s = NULL;
23 
24 	if (line == NULL)
25 		return -1;
26 
27 	while (*src != '\0') {
28 		s = strchr(src, '(');
29 		if (s == NULL)
30 			break;
31 
32 		if (strncmp(s, "(NET", 4)) {
33 			src = s + 1;
34 		}
35 		break;
36 	}
37 
38 	if (s == NULL)
39 		return -1;
40 
41 	memset(addrp, 0x00, sizeof(*maskp));
42 	memset(maskp, 0x00, sizeof(*maskp));
43 
44 	if (*(s + 4) == '6') {
45 #ifdef USE_INET6
46 		i6addr_t a61, a62;
47 
48 		s = strchr(s, ')');
49 		if (s == NULL || *++s != ' ')
50 			return -1;
51 		/*
52 		 * Parse the IPv6
53 		 */
54 		if (inet_pton(AF_INET6, s, &a61.in6) != 1)
55 			return -1;
56 
57 		s = strchr(s, ' ');
58 		if (s == NULL || strncmp(s, " - ", 3))
59 			return -1;
60 
61 		s += 3;
62 		if (inet_pton(AF_INET6, s, &a62) != 1)
63 			return -1;
64 
65 		addrp->adf_addr = a61;
66 		addrp->adf_family = AF_INET6;
67 		addrp->adf_len = offsetof(addrfamily_t, adf_addr) +
68 				 sizeof(struct in6_addr);
69 
70 		maskp->adf_addr.i6[0] = ~(a62.i6[0] ^ a61.i6[0]);
71 		maskp->adf_addr.i6[1] = ~(a62.i6[1] ^ a61.i6[1]);
72 		maskp->adf_addr.i6[2] = ~(a62.i6[2] ^ a61.i6[2]);
73 		maskp->adf_addr.i6[3] = ~(a62.i6[3] ^ a61.i6[3]);
74 
75 		/*
76 		 * If the mask that's been generated isn't a consecutive mask
77 		 * then we can't add it into a pool.
78 		 */
79 		if (count6bits(maskp->adf_addr.i6) == -1)
80 			return -1;
81 
82 		maskp->adf_family = AF_INET6;
83 		maskp->adf_len = addrp->adf_len;
84 
85 		if (IP6_MASKNEQ(&addrp->adf_addr.in6, &maskp->adf_addr.in6,
86 				&addrp->adf_addr.in6)) {
87 			return -1;
88 		}
89 		return 0;
90 #else
91 		return -1;
92 #endif
93 	}
94 
95 	s = strchr(s, ')');
96 	if (s == NULL || *++s != ' ')
97 		return -1;
98 
99 	s++;
100 
101 	if (inet_aton(s, &a1) != 1)
102 		return -1;
103 
104 	s = strchr(s, ' ');
105 	if (s == NULL || strncmp(s, " - ", 3))
106 		return -1;
107 
108 	s += 3;
109 	if (inet_aton(s, &a2) != 1)
110 		return -1;
111 
112 	addrp->adf_addr.in4 = a1;
113 	addrp->adf_family = AF_INET;
114 	addrp->adf_len = offsetof(addrfamily_t, adf_addr) +
115 			 sizeof(struct in_addr);
116 	maskp->adf_addr.in4.s_addr = ~(a2.s_addr ^ a1.s_addr);
117 
118 	/*
119 	 * If the mask that's been generated isn't a consecutive mask then
120 	 * we can't add it into a pool.
121 	 */
122 	if (count4bits(maskp->adf_addr.in4.s_addr) == -1)
123 		return -1;
124 
125 	maskp->adf_family = AF_INET;
126 	maskp->adf_len = addrp->adf_len;
127 	bzero((char *)maskp + maskp->adf_len, sizeof(*maskp) - maskp->adf_len);
128 	if ((addrp->adf_addr.in4.s_addr & maskp->adf_addr.in4.s_addr) !=
129 	    addrp->adf_addr.in4.s_addr)
130 		return -1;
131 	return 0;
132 }
133