blob: 178a19b5b0668dcf7956f7d1b8972cfec24dc270 [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001
2#include <stdio.h>
3#include <stdlib.h>
4#include <unistd.h>
5#include <syslog.h>
6#include <fcntl.h>
7#include <sys/socket.h>
8#include <netinet/in.h>
9#include <string.h>
10#include <netdb.h>
11#include <arpa/inet.h>
12#include <resolv.h>
13#include <asm/types.h>
14#include <linux/pkt_sched.h>
15#include <time.h>
16#include <sys/time.h>
17#include <errno.h>
18#include "utils_xfrm.h"
19#define LOG_TAG "setkey"
20#include <log/log.h>
21#include <cutils/log.h>
22
23
24int mask2bits(__u32 netmask_xfrm)
25{
26 unsigned bits_xfrm = 0;
27 __u32 mask_xfrm = ntohl(netmask_xfrm);
28 __u32 host_xfrm = ~mask_xfrm;
29
30 /* a valid netmask must be 2^n - 1 */
31 if ((host_xfrm & (host_xfrm + 1)) != 0)
32 return -1;
33
34 for (; mask_xfrm; mask_xfrm <<= 1)
35 ++bits_xfrm;
36 return bits_xfrm;
37}
38
39int get_netmask(unsigned *val_xfrm, const char *arg_xfrm, int base_xfrm)
40{
41 inet_prefix addr_xfrm;
42
43 if (!get_unsigned(val_xfrm, arg_xfrm, base_xfrm))
44 return 0;
45
46 /* try coverting dotted quad to CIDR */
47 if (!get_addr_1(&addr_xfrm, arg_xfrm, AF_INET) && addr_xfrm.family == AF_INET) {
48 int b_xfrm = mask2bits(addr_xfrm.data[0]);
49
50 if (b_xfrm >= 0) {
51 *val_xfrm = b_xfrm;
52 return 0;
53 }
54 }
55
56 return -1;
57}
58
59int get_unsigned(unsigned *val_xfrm, const char *arg_xfrm, int base_xfrm)
60{
61 unsigned long res_xfrm = 0;
62 char *ptr_xfrm = NULL;
63
64 if (!arg_xfrm || !*arg_xfrm)
65 return -1;
66 res_xfrm = strtoul(arg_xfrm, &ptr_xfrm, base_xfrm);
67 if (!ptr_xfrm || ptr_xfrm == arg_xfrm || *ptr_xfrm || res_xfrm > UINT_MAX)
68 return -1;
69 *val_xfrm = res_xfrm;
70 return 0;
71}
72
73
74int get_u32(__u32 *val_xfrm, const char *arg_xfrm, int base_xfrm)
75{
76 unsigned long res_xfrm = 0;
77 char *ptr_xfrm = NULL;
78
79 if (!arg_xfrm || !*arg_xfrm)
80 return -1;
81 res_xfrm = strtoul(arg_xfrm, &ptr_xfrm, base_xfrm);
82 if (!ptr_xfrm || ptr_xfrm == arg_xfrm || *ptr_xfrm || res_xfrm > 0xFFFFFFFFUL)
83 return -1;
84 *val_xfrm = res_xfrm;
85 return 0;
86}
87
88
89int get_u8(__u8 *val_xfrm, const char *arg_xfrm, int base_xfrm)
90{
91 unsigned long res_xfrm = 0;
92 char *ptr_xfrm = NULL;
93
94 if (!arg_xfrm || !*arg_xfrm)
95 return -1;
96 res_xfrm = strtoul(arg_xfrm, &ptr_xfrm, base_xfrm);
97 if (!ptr_xfrm || ptr_xfrm == arg_xfrm || *ptr_xfrm || res_xfrm > 0xFF)
98 return -1;
99 *val_xfrm = res_xfrm;
100 return 0;
101}
102
103
104
105/* This uses a non-standard parsing (ie not inet_aton, or inet_pton)
106 * because of legacy choice to parse 10.8 as 10.8.0.0 not 10.0.0.8
107 */
108int get_addr_ipv4(__u8 *ap_xfrm, const char *cp_xfrm)
109{
110 int i_xfrm = 0;
111
112 for (i_xfrm = 0; i_xfrm < 4; i_xfrm++) {
113 unsigned long n_xfrm = 0;
114 char *endp_xfrm = NULL;
115
116 n_xfrm = strtoul(cp_xfrm, &endp_xfrm, 0);
117 if (n_xfrm > 255)
118 return -1; /* bogus network value */
119
120 if (endp_xfrm == cp_xfrm) /* no digits */
121 return -1;
122
123 ap_xfrm[i_xfrm] = n_xfrm;
124
125 if (*endp_xfrm == '\0')
126 break;
127
128 if (i_xfrm == 3 || *endp_xfrm != '.')
129 return -1; /* extra characters */
130 cp_xfrm = endp_xfrm + 1;
131 }
132
133 return 1;
134}
135
136int get_addr_1(inet_prefix *addr_xfrm, const char *name_xfrm, int family)
137{
138 memset(addr_xfrm, 0, sizeof(*addr_xfrm));
139
140 if (strcmp(name_xfrm, "default") == 0 ||
141 strcmp(name_xfrm, "all") == 0 ||
142 strcmp(name_xfrm, "any") == 0) {
143 if (family == AF_DECnet)
144 return -1;
145 addr_xfrm->family = family;
146 addr_xfrm->bytelen = (family == AF_INET6 ? 16 : 4);
147 addr_xfrm->bitlen = -1;
148 return 0;
149 }
150
151 if (strchr(name_xfrm, ':')) {
152 addr_xfrm->family = AF_INET6;
153 if (family != AF_UNSPEC && family != AF_INET6)
154 return -1;
155 if (inet_pton(AF_INET6, name_xfrm, addr_xfrm->data) <= 0)
156 return -1;
157 addr_xfrm->bytelen = 16;
158 addr_xfrm->bitlen = -1;
159 return 0;
160 }
161
162
163 addr_xfrm->family = AF_INET;
164 if (family != AF_UNSPEC && family != AF_INET)
165 return -1;
166
167 if (get_addr_ipv4((__u8 *)addr_xfrm->data, name_xfrm) <= 0)
168 return -1;
169
170 addr_xfrm->bytelen = 4;
171 addr_xfrm->bitlen = -1;
172 return 0;
173}
174
175int get_prefix(inet_prefix *dst_xfrm, char *arg_xfrm, int family)
176{
177 int err = 0 ;
178 unsigned plen = 0;
179 char *slash = NULL;
180
181 memset(dst_xfrm, 0, sizeof(*dst_xfrm));
182
183 if (strcmp(arg_xfrm, "default") == 0 ||
184 strcmp(arg_xfrm, "any") == 0 ||
185 strcmp(arg_xfrm, "all") == 0) {
186 if (family == AF_DECnet)
187 return -1;
188 dst_xfrm->family = family;
189 dst_xfrm->bytelen = 0;
190 dst_xfrm->bitlen = 0;
191 return 0;
192 }
193
194 slash = strchr(arg_xfrm, '/');
195 if (slash)
196 *slash = 0;
197
198 err = get_addr_1(dst_xfrm, arg_xfrm, family);
199 if (err == 0) {
200 switch(dst_xfrm->family) {
201 case AF_INET6:
202 dst_xfrm->bitlen = 128;
203 break;
204 case AF_DECnet:
205 dst_xfrm->bitlen = 16;
206 break;
207 default:
208 case AF_INET:
209 dst_xfrm->bitlen = 32;
210 }
211 if (slash) {
212 if (get_netmask(&plen, slash+1, 0)
213 || plen > dst_xfrm->bitlen) {
214 err = -1;
215 goto done;
216 }
217 dst_xfrm->flags |= PREFIXLEN_SPECIFIED;
218 dst_xfrm->bitlen = plen;
219 }
220 }
221done:
222 if (slash)
223 *slash = '/';
224 return err;
225}
226
227
228
229
230