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/*
11Microsoft Corp MICROSOFT19 (NET-198-136-97-0-1) 198.137.97.0 - 198.137.97.255
12Microsoft Corp SAVV-S233053-6 (NET-206-79-74-32-1) 206.79.74.32 - 206.79.74.47
13 */
14int
15parsewhoisline(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