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