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