1 /*
2 * Copyright (C) 2015 Adrien Vergé
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "ipv4.h"
19 #include "tunnel.h"
20 #include "config.h"
21 #include "log.h"
22 #include "xml.h"
23
24 #include <unistd.h>
25 #include <arpa/inet.h>
26 #include <fcntl.h>
27 #include <sys/ioctl.h>
28 #include <sys/stat.h>
29
30 #include <errno.h>
31 #include <limits.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <stdint.h>
35 #include <string.h>
36
37 #define IPV4_GET_ROUTE_BUFFER_CHUNK_SIZE 65536
38 #define SHOW_ROUTE_BUFFER_SIZE 128
39
40 static char show_route_buffer[SHOW_ROUTE_BUFFER_SIZE];
41
42 #define ERR_IPV4_SEE_ERRNO -1
43 #define ERR_IPV4_NO_MEM -2
44 #define ERR_IPV4_PERMISSION -3
45 #define ERR_IPV4_NO_SUCH_ROUTE -4
46 #define ERR_IPV4_PROC_NET_ROUTE -5
47
err_ipv4_str(int code)48 static inline const char *err_ipv4_str(int code)
49 {
50 if (code == ERR_IPV4_SEE_ERRNO)
51 return strerror(errno);
52 else if (code == ERR_IPV4_NO_MEM)
53 return "Not enough memory";
54 else if (code == ERR_IPV4_PERMISSION)
55 return "Permission denied";
56 else if (code == ERR_IPV4_NO_SUCH_ROUTE)
57 return "Route not found";
58 else if (code == ERR_IPV4_PROC_NET_ROUTE)
59 return "Parsing /proc/net/route failed";
60 return "unknown";
61 }
62
63 /*
64 * Returns a string representation of the route, such as:
65 * to 192.168.1.0/255.255.255.0 via 172.16.0.1 dev eth0
66 *
67 * Warning: the returned buffer is static, so multiple calls will overwrite it.
68 */
ipv4_show_route(struct rtentry_ofvpn * route)69 static char *ipv4_show_route(struct rtentry_ofvpn *route)
70 {
71 strcpy(show_route_buffer, "to ");
72 strncat(show_route_buffer, inet_ntoa(route_dest(route)), 15);
73 strcat(show_route_buffer, "/");
74 strncat(show_route_buffer, inet_ntoa(route_mask(route)), 15);
75 if (route->rt_flags & RTF_GATEWAY) {
76 strcat(show_route_buffer, " via ");
77 strncat(show_route_buffer, inet_ntoa(route_gtw(route)), 15);
78 }
79 if (route_iface(route) != NULL) {
80 strcat(show_route_buffer, " dev ");
81 strncat(show_route_buffer, route_iface(route),
82 SHOW_ROUTE_BUFFER_SIZE - strlen(show_route_buffer) - 1);
83 }
84
85 return show_route_buffer;
86 }
87
route_init(struct rtentry_ofvpn * route)88 static inline int route_init(struct rtentry_ofvpn *route)
89 {
90 memset(route, 0, sizeof(*route));
91
92 cast_addr(&(route)->rt_dst)->sin_family = AF_INET;
93 cast_addr(&(route)->rt_genmask)->sin_family = AF_INET;
94 cast_addr(&(route)->rt_gateway)->sin_family = AF_INET;
95
96 return 0;
97 }
98
route_destroy(struct rtentry_ofvpn * route)99 static inline void route_destroy(struct rtentry_ofvpn *route)
100 {
101 free(route_iface(route));
102 route_iface(route) = NULL;
103 }
104
105 /*
106 * Finds system IP route to a destination.
107 *
108 * The passed route must have dest and mask set. If the route is found,
109 * the function searches for a match in the routing table and returns
110 * that one. Note that dest and mask contain the network address and
111 * the mask of the corresponding routing table entry after calling.
112 * After calling ipv4_get_route it might be necessary to set dest
113 * and mask again to the desired values for further processing.
114 */
ipv4_get_route(struct rtentry_ofvpn * route)115 static int ipv4_get_route(struct rtentry_ofvpn *route)
116 {
117 size_t buffer_size = IPV4_GET_ROUTE_BUFFER_CHUNK_SIZE;
118 char *buffer = malloc(buffer_size);
119 char *realloc_buffer;
120 int err = 0;
121 char *start, *line;
122 char *saveptr1 = NULL, *saveptr2 = NULL;
123 uint32_t rtdest, rtmask, rtgtw;
124 int rtfound = 0;
125
126 if (!buffer) {
127 err = ERR_IPV4_SEE_ERRNO;
128 goto end;
129 }
130
131 /*
132 * initialize the buffer with zeroes, aiming to address the
133 * coverity issue "TAINTED_SCALAR passed to a tainted sink"
134 *
135 * Later on, the routing table is read into this buffer using
136 * read() and therefore the content of the buffer is considered
137 * tainted. strtok_r internally uses it in a loop boundary.
138 * The theoretical problem is that the loop could iterate forever,
139 * if the buffer contains a huge string which doesn't contain
140 * the token character, which we are parsing for.
141 *
142 * We can declare this as a false positive, because
143 * - the routing table is to some extent trusted input,
144 * - it's not that large,
145 * - and the loop in strtok_r increments the pointer in each
146 * iteration until it reaches the area where we have ensured
147 * that there is a delimiting '\0' character by proper
148 * initialization. We ensure this also when growing the buffer.
149 */
150 memset(buffer, '\0', IPV4_GET_ROUTE_BUFFER_CHUNK_SIZE);
151 log_debug("ip route show %s\n", ipv4_show_route(route));
152
153 // store what we are looking for
154 rtdest = route_dest(route).s_addr;
155 rtmask = route_mask(route).s_addr;
156 rtgtw = route_gtw(route).s_addr;
157
158 // initialize the output record
159 route_dest(route).s_addr = inet_addr("0.0.0.0");
160 route_mask(route).s_addr = inet_addr("0.0.0.0");
161 route_gtw(route).s_addr = inet_addr("0.0.0.0");
162
163 #if HAVE_PROC_NET_ROUTE
164 /* this is not present on Mac OS X and FreeBSD */
165 int fd;
166 uint32_t total_bytes_read = 0;
167
168 // Cannot stat, mmap not lseek this special /proc file
169 fd = open("/proc/net/route", O_RDONLY);
170 if (fd == -1) {
171 err = ERR_IPV4_SEE_ERRNO;
172 goto end;
173 }
174
175 int bytes_read;
176
177 while ((bytes_read = read(fd, buffer + total_bytes_read,
178 buffer_size - total_bytes_read - 1)) > 0) {
179 total_bytes_read += bytes_read;
180
181 if ((buffer_size - total_bytes_read) < 1) {
182 buffer_size += IPV4_GET_ROUTE_BUFFER_CHUNK_SIZE;
183
184 realloc_buffer = realloc(buffer, buffer_size);
185 if (realloc_buffer) {
186 buffer = realloc_buffer;
187 } else {
188 err = ERR_IPV4_SEE_ERRNO;
189 goto cleanup;
190 }
191 buffer[buffer_size-1] = '\0';
192 }
193 }
194
195 cleanup:
196 if (close(fd))
197 log_warn("Could not close /proc/net/route (%s).\n", strerror(errno));
198 if (err)
199 goto end;
200
201 if (bytes_read < 0) {
202 err = ERR_IPV4_SEE_ERRNO;
203 goto end;
204 }
205
206 #else
207 FILE * fp;
208 uint32_t total_bytes_read = 0;
209
210 char *saveptr3 = NULL;
211 int have_ref = 0;
212 int have_use = 0;
213
214 static const char netstat_path[] = NETSTAT_PATH;
215
216 if (access(netstat_path, F_OK) != 0) {
217 log_error("%s: %s.\n", netstat_path, strerror(errno));
218 return 1;
219 }
220 log_debug("netstat_path: %s\n", netstat_path);
221
222 // Open the command for reading
223 fp = popen(NETSTAT_PATH " -f inet -rn", "r");
224 if (fp == NULL) {
225 err = ERR_IPV4_SEE_ERRNO;
226 goto end;
227 }
228
229 line = buffer;
230 // Read the output a line at a time
231 while (fgets(line, buffer_size - total_bytes_read - 1, fp) != NULL) {
232 uint32_t bytes_read = strlen(line);
233
234 total_bytes_read += bytes_read;
235
236 if (bytes_read > 0 && line[bytes_read - 1] != '\n') {
237 buffer_size += IPV4_GET_ROUTE_BUFFER_CHUNK_SIZE;
238
239 realloc_buffer = realloc(buffer, buffer_size);
240 if (realloc_buffer) {
241 buffer = realloc_buffer;
242 } else {
243 err = ERR_IPV4_SEE_ERRNO;
244 goto cleanup;
245 }
246 }
247
248 line = buffer + total_bytes_read;
249 }
250
251 cleanup:
252 if (pclose(fp))
253 log_warn("Could not close netstat pipe (%s).\n", strerror(errno));
254 if (err)
255 goto end;
256
257 // reserve enough memory (256 shorts)
258 // to make sure not to access out of bounds later,
259 // for ipv4 only unsigned short is allowed
260
261 unsigned short flag_table[256] = { 0 };
262
263 /*
264 * Fill the flag_table now. Unfortunately it is not easy
265 * to do this in a more elegant way. The problem here
266 * is that these are already preprocessor macros and
267 * we can't use them as arguments for another macro which
268 * would include the #ifdef statements.
269 *
270 * Also, not all flags might be allowed in the context
271 * of ipv4, and the code depends on which ones are
272 * actually implemented on the target platform, which
273 * might also be varying between Mac OS X versions.
274 *
275 */
276
277 #ifdef RTF_PROTO1 // Protocol specific routing flag #1
278 flag_table['1'] = RTF_PROTO1 & USHRT_MAX;
279 #endif
280 #ifdef RTF_PROTO2 // Protocol specific routing flag #2
281 flag_table['2'] = RTF_PROTO2 & USHRT_MAX;
282 #endif
283 #ifdef RTF_PROTO3 // Protocol specific routing flag #3
284 flag_table['3'] = RTF_PROTO3 & USHRT_MAX;
285 #endif
286 #ifdef RTF_BLACKHOLE // Just discard packets (during updates)
287 flag_table['B'] = RTF_BLACKHOLE & USHRT_MAX;
288 #endif
289 #ifdef RTF_BROADCAST // The route represents a broadcast address
290 flag_table['b'] = RTF_BROADCAST & USHRT_MAX;
291 #endif
292 #ifdef RTF_CLONING // Generate new routes on use
293 flag_table['C'] = RTF_CLONING & USHRT_MAX;
294 #endif
295 #ifdef RTF_PRCLONING // Protocol-specified generate new routes on use
296 flag_table['c'] = RTF_PRCLONING & USHRT_MAX;
297 #endif
298 #ifdef RTF_DYNAMIC // Created dynamically (by redirect)
299 flag_table['D'] = RTF_DYNAMIC & USHRT_MAX;
300 #endif
301 #ifdef RTF_GATEWAY // Destination requires forwarding by intermediary
302 flag_table['G'] = RTF_GATEWAY & USHRT_MAX;
303 #endif
304 #ifdef RTF_HOST // Host entry (net otherwise)
305 flag_table['H'] = RTF_HOST & USHRT_MAX;
306 #endif
307 #ifdef RTF_IFSCOPE // Route is associated with an interface scope
308 flag_table['I'] = RTF_IFSCOPE & USHRT_MAX;
309 #endif
310 #ifdef RTF_IFREF // Route is holding a reference to the interface
311 flag_table['i'] = RTF_IFREF & USHRT_MAX;
312 #endif
313 #ifdef RTF_LLINFO // Valid protocol to link address translation
314 flag_table['L'] = RTF_LLINFO & USHRT_MAX;
315 #endif
316 #ifdef RTF_MODIFIED // Modified dynamically (by redirect)
317 flag_table['M'] = RTF_MODIFIED & USHRT_MAX;
318 #endif
319 #ifdef RTF_MULTICAST // The route represents a multicast address
320 flag_table['m'] = RTF_MULTICAST & USHRT_MAX;
321 #endif
322 #ifdef RTF_REJECT // Host or net unreachable
323 flag_table['R'] = RTF_REJECT & USHRT_MAX;
324 #endif
325 #ifdef RTF_ROUTER // Host is a default router
326 flag_table['r'] = RTF_ROUTER & USHRT_MAX;
327 #endif
328 #ifdef RTF_STATIC // Manually added
329 flag_table['S'] = RTF_STATIC & USHRT_MAX;
330 #endif
331 #ifdef RTF_UP // Route usable
332 flag_table['U'] = RTF_UP & USHRT_MAX;
333 #endif
334 #ifdef RTF_WASCLONED // Route was generated as a result of cloning
335 flag_table['W'] = RTF_WASCLONED & USHRT_MAX;
336 #endif
337 #ifdef RTF_XRESOLVE // External daemon translates proto to link address
338 flag_table['X'] = RTF_XRESOLVE & USHRT_MAX;
339 #endif
340 #ifdef RTF_PROXY // Proxying; cloned routes will not be scoped
341 flag_table['Y'] = RTF_PROXY & USHRT_MAX;
342 #endif
343
344 #endif
345
346 if (total_bytes_read == 0) {
347 log_debug("routing table is empty.\n");
348 err = ERR_IPV4_PROC_NET_ROUTE;
349 goto end;
350 }
351 buffer[total_bytes_read] = '\0';
352
353 // Skip first line
354 start = strchr(buffer, '\n');
355 if (start == NULL) {
356 log_debug("routing table is malformed.\n");
357 err = ERR_IPV4_PROC_NET_ROUTE;
358 goto end;
359 }
360 start++;
361
362 #if !HAVE_PROC_NET_ROUTE
363 if (strstr(buffer, "Ref") != NULL)
364 have_ref = 1;
365 if (strstr(buffer, "Use") != NULL)
366 have_use = 1;
367 // Skip 3 more lines from netstat output on Mac OS X and on FreeBSD
368 start = strchr(start, '\n');
369 start = strchr(++start, '\n');
370 start = strchr(++start, '\n');
371 if (start == NULL) {
372 log_debug("routing table is malformed.\n");
373 err = ERR_IPV4_PROC_NET_ROUTE;
374 goto end;
375 }
376 #endif
377
378 if (strchr(start, '\n') == NULL) {
379 log_debug("routing table is malformed.\n");
380 err = ERR_IPV4_PROC_NET_ROUTE;
381 goto end;
382 }
383
384 // Look for the route
385 line = strtok_r(start, "\n", &saveptr1);
386 while (line != NULL) {
387 char *iface;
388 uint32_t dest, mask, gtw;
389 unsigned short flags;
390 #if HAVE_PROC_NET_ROUTE
391 unsigned short irtt;
392 short metric;
393 unsigned long mtu, window;
394
395 iface = strtok_r(line, "\t", &saveptr2);
396 dest = strtoul(strtok_r(NULL, "\t", &saveptr2), NULL, 16);
397 gtw = strtoul(strtok_r(NULL, "\t", &saveptr2), NULL, 16);
398 flags = strtoul(strtok_r(NULL, "\t", &saveptr2), NULL, 16);
399 strtok_r(NULL, "\t", &saveptr2); // "RefCnt"
400 strtok_r(NULL, "\t", &saveptr2); // "Use"
401 metric = strtoul(strtok_r(NULL, "\t", &saveptr2), NULL, 16);
402 mask = strtoul(strtok_r(NULL, "\t", &saveptr2), NULL, 16);
403 mtu = strtoul(strtok_r(NULL, "\t", &saveptr2), NULL, 16);
404 window = strtoul(strtok_r(NULL, "\t", &saveptr2), NULL, 16);
405 irtt = strtoul(strtok_r(NULL, "\t", &saveptr2), NULL, 16);
406 #else
407 /* parse netstat output on Mac OS X and BSD */
408 char tmp_ip_string[16];
409 struct in_addr dstaddr;
410 int pos;
411 char *tmpstr;
412
413 log_debug_details("\n");
414 log_debug_details("line: %s\n", line);
415
416 saveptr3 = NULL;
417 dest = UINT32_MAX;
418 mask = UINT32_MAX;
419 // "Destination"
420 tmpstr = strtok_r(line, " ", &saveptr2);
421 if (strncmp(tmpstr, "Internet6", 9) == 0) {
422 // we have arrived at the end of ipv4 output
423 goto end;
424 }
425 log_debug_details("- Destination: %s\n", tmpstr);
426 // replace literal "default" route by IPV4 numbers-and-dots notation
427 if (strncmp(tmpstr, "default", 7) == 0) {
428 dest = 0;
429 mask = 0;
430 } else {
431 int is_mask_set = 0;
432 char *tmp_position;
433 int dot_count = -1;
434
435 if (strchr(tmpstr, '/') != NULL) {
436 // 123.123.123.123/30 style
437 // 123.123.123/24 style
438 // 123.123/24 style
439
440 // break CIDR up into address and mask part
441 strcpy(tmp_ip_string, strtok_r(tmpstr, "/", &saveptr3));
442 mask = strtoul(saveptr3, NULL, 10);
443 // convert from CIDR to ipv4 mask
444 mask = 0xffffffff << (32-mask);
445
446 is_mask_set = 1;
447 } else if (inet_aton(tmpstr, &dstaddr)) {
448 // 123.123.123.123 style
449 // 123.123.123 style
450 // 123.123 style
451
452 strcpy(tmp_ip_string, tmpstr);
453 is_mask_set = 0;
454 }
455
456 // Process Destination IP Expression
457 tmp_position = tmp_ip_string;
458 while (tmp_position != NULL) {
459 ++dot_count;
460 tmp_position = strchr(++tmp_position, '.');
461 }
462
463 for (int i = dot_count; i < 3; i++)
464 strcat(tmp_ip_string, ".0");
465
466 if (inet_aton(tmp_ip_string, &dstaddr))
467 dest = dstaddr.s_addr;
468
469 if (!is_mask_set) {
470 // convert from CIDR to ipv4 mask
471 mask = 0xffffffff << (32-((dot_count + 1) * 8));
472 }
473 // convert mask to reversed byte order
474 mask = ((mask & 0xff000000) >> 24)
475 | ((mask & 0xff0000) >> 8)
476 | ((mask & 0xff00) << 8)
477 | ((mask & 0xff) << 24);
478 }
479 log_debug_details("- Destination IP Hex: %x\n", dest);
480 log_debug_details("- Destination Mask Hex: %x\n", mask);
481 // "Gateway"
482 gtw = 0;
483 if (inet_aton(strtok_r(NULL, " ", &saveptr2), &dstaddr)) {
484 gtw = dstaddr.s_addr;
485 log_debug_details("- Gateway Mask Hex: %x\n", gtw);
486 }
487 // "Flags"
488 tmpstr = strtok_r(NULL, " ", &saveptr2);
489 flags = 0;
490 // this is the reason for the 256 entries mentioned above
491 for (pos = 0; pos < strlen(tmpstr); pos++)
492 flags |= flag_table[(unsigned char)tmpstr[pos]];
493
494 if (have_ref)
495 strtok_r(NULL, " ", &saveptr2); // "Ref"
496 if (have_use)
497 strtok_r(NULL, " ", &saveptr2); // "Use"
498
499 iface = strtok_r(NULL, " ", &saveptr2); // "Netif"
500 log_debug_details("- Interface: %s\n", iface);
501 #endif
502 /*
503 * Now that we have parsed a routing entry, check if it
504 * matches the current argument to the function call.
505 * In rtentry_ofvpn we have integer representation, i.e.
506 * the most significant byte corresponds to the last
507 * number of dotted-number representation and vice versa.
508 * In this representation ( address & mask ) is the network
509 * address.
510 * The routing algorithm does the following:
511 * First, check if the network address we are looking for
512 * falls into the network for the current route.
513 * Therefore, calculate the network address for both, the
514 * current route and for the destination we are searching.
515 * If the destination is a smaller network (for instance a
516 * single host), we have to mask again with the netmask of
517 * the routing entry that we are checking in order to obtain
518 * the network address in the context of the current route.
519 * If both network addresses match, we have found a candidate
520 * for a route.
521 * However, there might be another route for a smaller network,
522 * therefore repeat this and only store the resulting route
523 * when the mask is at least as large as the one we may
524 * have already found in a previous iteration (a larger
525 * netmask corresponds to a smaller network in this
526 * representation, and has a higher priority by default).
527 * Also, only consider routing entries for which the
528 * netmask is not larger than the netmask used in the
529 * argument when calling the function - so that we can
530 * distinguish between different routing entries for subnets
531 * of different size but with the same network address.
532 * For routing entries with the same destination and
533 * the same netmask the metric can be used for adjusting
534 * the priority (this is not supported on mac).
535 * If the metric is larger than one found for this network
536 * size, skip the current route (smaller numbers denote
537 * less hops and therefore have a higher priority).
538 */
539
540 if (((dest & mask) == (rtdest & rtmask & mask))
541 && (mask >= route_mask(route).s_addr)
542 && (mask <= rtmask)
543 && ((route_iface(route) == NULL)
544 || (strcmp(iface, route_iface(route)) == 0)
545 || (strlen(route_iface(route)) > 0
546 && route_iface(route)[0] == '!'
547 && strcmp(iface, &route_iface(route)[1]) != 0)
548 )) {
549 #if HAVE_PROC_NET_ROUTE
550 if (((mask == route_mask(route).s_addr)
551 && (metric <= route->rt_metric))
552 || (rtfound == 0)
553 || (mask > route_mask(route).s_addr)) {
554 #endif
555 rtfound = 1;
556 // Requested route has been found
557 route_dest(route).s_addr = dest;
558 route_mask(route).s_addr = mask;
559 route_gtw(route).s_addr = gtw;
560 route->rt_flags = flags;
561
562 free(route_iface(route));
563 route_iface(route) = strdup(iface);
564 if (!route_iface(route)) {
565 err = ERR_IPV4_NO_MEM;
566 goto end;
567 }
568
569 #if HAVE_PROC_NET_ROUTE
570 // we do not have these values from Mac OS X netstat,
571 // so stay with defaults denoted by values of 0
572 route->rt_metric = metric;
573 route->rt_mtu = mtu;
574 route->rt_window = window;
575 route->rt_irtt = irtt;
576 }
577 #else
578 log_debug_details("- route matches\n");
579 #endif
580 }
581 line = strtok_r(NULL, "\n", &saveptr1);
582 }
583
584 end:
585 free(buffer);
586 if (err)
587 return err;
588
589 if (rtfound == 0) {
590 // should not occur anymore unless there is no default route
591 log_debug("Route not found.\n");
592 // at least restore input values
593 route_dest(route).s_addr = rtdest;
594 route_mask(route).s_addr = rtmask;
595 route_gtw(route).s_addr = rtgtw;
596
597 return ERR_IPV4_NO_SUCH_ROUTE;
598 }
599
600 return 0;
601 }
602
ipv4_set_route(struct rtentry_ofvpn * route)603 static int ipv4_set_route(struct rtentry_ofvpn *route)
604 {
605 #ifdef HAVE_RT_ENTRY_WITH_RT_DST
606 /* we can copy rtentry_ofvpn struct directly between openfortivpn and kernel */
607 log_debug("ip route add %s\n", ipv4_show_route(route));
608
609 int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
610
611 if (sockfd < 0)
612 return ERR_IPV4_SEE_ERRNO;
613 if (ioctl(sockfd, SIOCADDRT, route) == -1) {
614 if (close(sockfd))
615 log_warn("Could not close socket for setting route (%s).\n",
616 strerror(errno));
617 return ERR_IPV4_SEE_ERRNO;
618 }
619 if (close(sockfd))
620 log_warn("Could not close socket for setting route: %s\n",
621 strerror(errno));
622 #else
623 /* we have to use the route command as tool for route manipulation */
624 char cmd[SHOW_ROUTE_BUFFER_SIZE];
625
626 if (access("/sbin/route", F_OK) != 0) {
627 log_error("/sbin/route: %s.\n", strerror(errno));
628 return 1;
629 }
630
631 strcpy(cmd, "/sbin/route -n add ");
632 if (route->rt_flags & RTF_HOST)
633 strcat(cmd, "-host ");
634 else
635 strcat(cmd, "-net ");
636
637 strncat(cmd, inet_ntoa(route_dest(route)), 15);
638 if (!(route->rt_flags & RTF_HOST)) {
639 strcat(cmd, " -netmask ");
640 strncat(cmd, inet_ntoa(route_mask(route)), 15);
641 }
642 if (route->rt_flags & RTF_GATEWAY) {
643 strcat(cmd, " ");
644 strncat(cmd, inet_ntoa(route_gtw(route)), 15);
645 } else {
646 strcat(cmd, " -interface ");
647 strncat(cmd, route_iface(route),
648 SHOW_ROUTE_BUFFER_SIZE - strlen(cmd) - 1);
649 }
650
651 log_debug("%s\n", cmd);
652
653 int res = system(cmd);
654
655 if (res == -1)
656 return ERR_IPV4_SEE_ERRNO;
657 #endif
658
659 return 0;
660 }
661
ipv4_del_route(struct rtentry_ofvpn * route)662 static int ipv4_del_route(struct rtentry_ofvpn *route)
663 {
664 #ifdef HAVE_RT_ENTRY_WITH_RT_DST
665 /* we can copy rtentry_ofvpn struct directly between openfortivpn and kernel */
666 struct rtentry_ofvpn tmp;
667 int sockfd;
668
669 log_debug("ip route del %s\n", ipv4_show_route(route));
670
671 // Copy route to a temp variable to clear some of its properties
672 memcpy(&tmp, route, sizeof(tmp));
673 tmp.rt_metric = 0;
674 tmp.rt_mtu = 0;
675 tmp.rt_window = 0;
676 tmp.rt_irtt = 0;
677
678 sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
679 if (sockfd < 0)
680 return ERR_IPV4_SEE_ERRNO;
681 if (ioctl(sockfd, SIOCDELRT, &tmp) == -1) {
682 if (close(sockfd))
683 log_warn("Could not close socket for deleting route (%s).\n",
684 strerror(errno));
685 return ERR_IPV4_SEE_ERRNO;
686 }
687 if (close(sockfd))
688 log_warn("Could not close socket for deleting route (%s).\n",
689 strerror(errno));
690 #else
691 char cmd[SHOW_ROUTE_BUFFER_SIZE];
692
693 if (access("/sbin/route", F_OK) != 0) {
694 log_error("/sbin/route: %s.\n", strerror(errno));
695 return 1;
696 }
697
698 strcpy(cmd, "/sbin/route -n delete ");
699 if (route->rt_flags & RTF_HOST)
700 strcat(cmd, "-host ");
701 else
702 strcat(cmd, "-net ");
703
704 strncat(cmd, inet_ntoa(route_dest(route)), 15);
705 if (!(route->rt_flags & RTF_HOST)) {
706 strcat(cmd, " -netmask ");
707 strncat(cmd, inet_ntoa(route_mask(route)), 15);
708 }
709 if (route->rt_flags & RTF_GATEWAY) {
710 strcat(cmd, " ");
711 strncat(cmd, inet_ntoa(route_gtw(route)), 15);
712 } else {
713 strcat(cmd, " -interface ");
714 strncat(cmd, route_iface(route),
715 SHOW_ROUTE_BUFFER_SIZE - strlen(cmd) - 1);
716 }
717
718 log_debug("%s\n", cmd);
719
720 int res = system(cmd);
721
722 if (res == -1)
723 return ERR_IPV4_SEE_ERRNO;
724 #endif
725 return 0;
726 }
727
ipv4_protect_tunnel_route(struct tunnel * tunnel)728 int ipv4_protect_tunnel_route(struct tunnel *tunnel)
729 {
730 struct rtentry_ofvpn *gtw_rt = &tunnel->ipv4.gtw_rt;
731 struct rtentry_ofvpn *def_rt = &tunnel->ipv4.def_rt;
732 int ret;
733
734 route_init(def_rt);
735 route_init(gtw_rt);
736
737 // Back up default route
738 route_dest(def_rt).s_addr = inet_addr("0.0.0.0");
739 route_mask(def_rt).s_addr = inet_addr("0.0.0.0");
740 route_iface(def_rt) = malloc(strlen(tunnel->ppp_iface) + 2);
741 if (!route_iface(def_rt)) {
742 log_error("malloc: %s\n", strerror(errno));
743 return ERR_IPV4_SEE_ERRNO;
744 }
745 sprintf(route_iface(def_rt), "!%s", tunnel->ppp_iface);
746
747 ret = ipv4_get_route(def_rt);
748 if (ret != 0) {
749 log_warn("Could not get current default route (%s).\n",
750 err_ipv4_str(ret));
751 log_warn("Protecting tunnel route has failed. But this can be working except for some cases.\n");
752 goto err_destroy_def_rt;
753 }
754
755 // Set the up a route to the tunnel gateway
756 route_dest(gtw_rt).s_addr = tunnel->config->gateway_ip.s_addr;
757 route_mask(gtw_rt).s_addr = inet_addr("255.255.255.255");
758 route_iface(gtw_rt) = malloc(strlen(tunnel->ppp_iface) + 2);
759 if (!route_iface(gtw_rt)) {
760 log_error("malloc: %s\n", strerror(errno));
761 return ERR_IPV4_SEE_ERRNO;
762 }
763 sprintf(route_iface(gtw_rt), "%s", tunnel->ppp_iface);
764 ret = ipv4_get_route(gtw_rt);
765 if ((ret == 0)
766 && (route_dest(gtw_rt).s_addr == tunnel->config->gateway_ip.s_addr)
767 && (route_mask(gtw_rt).s_addr == inet_addr("255.255.255.255"))) {
768 log_debug("removing wrong route to vpn server...\n");
769 log_debug("ip route show %s\n", ipv4_show_route(gtw_rt));
770 ipv4_del_route(gtw_rt);
771 }
772 sprintf(route_iface(gtw_rt), "!%s", tunnel->ppp_iface);
773 ret = ipv4_get_route(gtw_rt);
774 if (ret != 0) {
775 log_warn("Could not get route to gateway (%s).\n",
776 err_ipv4_str(ret));
777 log_warn("Protecting tunnel route has failed. But this can be working except for some cases.\n");
778 goto err_destroy_gtw_rt;
779 }
780 route_dest(gtw_rt).s_addr = tunnel->config->gateway_ip.s_addr;
781 route_mask(gtw_rt).s_addr = inet_addr("255.255.255.255");
782 gtw_rt->rt_flags |= RTF_HOST;
783 gtw_rt->rt_metric = 0;
784
785 tunnel->ipv4.route_to_vpn_is_added = 1;
786 log_debug("Setting route to vpn server...\n");
787 log_debug("ip route show %s\n", ipv4_show_route(gtw_rt));
788 ret = ipv4_set_route(gtw_rt);
789 if (ret == ERR_IPV4_SEE_ERRNO && errno == EEXIST) {
790 log_warn("Route to vpn server exists already.\n");
791
792 tunnel->ipv4.route_to_vpn_is_added = 0;
793 } else if (ret != 0)
794 log_warn("Could not set route to vpn server (%s).\n",
795 err_ipv4_str(ret));
796
797 return 0;
798
799 err_destroy_gtw_rt:
800 route_destroy(gtw_rt);
801 err_destroy_def_rt:
802 route_destroy(def_rt);
803 tunnel->ipv4.route_to_vpn_is_added = 0;
804 return ret;
805 }
806
807 #if HAVE_USR_SBIN_PPPD
add_text_route(struct tunnel * tunnel,const char * dest,const char * mask,const char * gw)808 static void add_text_route(struct tunnel *tunnel, const char *dest,
809 const char *mask, const char *gw)
810 {
811 size_t l0, l1;
812 static const char fmt[] = ",%s/%s/%s";
813 static const char trigger[] = "openfortivpn";
814 char **target = &tunnel->config->pppd_ipparam;
815 char *ptr;
816
817 if (*target == NULL || strncmp(*target, trigger, strlen(trigger)))
818 return;
819 if (!dest || !mask || !gw)
820 return;
821 log_info("Registering route %s/%s via %s\n", dest, mask, gw);
822 l0 = strlen(*target);
823 l1 = strlen(fmt) + strlen(dest) + strlen(mask) + strlen(gw) + 1;
824 ptr = realloc(*target, l0 + l1);
825 if (ptr) {
826 *target = ptr;
827 snprintf(*target + l0, l1, fmt, dest, mask, gw);
828 } else {
829 log_error("realloc: %s\n", strerror(errno));
830 }
831 }
832 #endif
833
ipv4_add_split_vpn_route(struct tunnel * tunnel,char * dest,char * mask,char * gateway)834 int ipv4_add_split_vpn_route(struct tunnel *tunnel, char *dest, char *mask,
835 char *gateway)
836 {
837 struct rtentry_ofvpn *route;
838 char env_var[24];
839
840 #if HAVE_USR_SBIN_PPPD
841 add_text_route(tunnel, dest, mask, gateway);
842 #endif
843 if (tunnel->ipv4.split_routes == MAX_SPLIT_ROUTES)
844 return ERR_IPV4_NO_MEM;
845 if ((tunnel->ipv4.split_rt == NULL)
846 || ((tunnel->ipv4.split_routes % STEP_SPLIT_ROUTES) == 0)) {
847 void *new_ptr
848 = realloc(tunnel->ipv4.split_rt,
849 (size_t) (tunnel->ipv4.split_routes + STEP_SPLIT_ROUTES)
850 * sizeof(*(tunnel->ipv4.split_rt)));
851 if (new_ptr == NULL)
852 return ERR_IPV4_NO_MEM;
853 tunnel->ipv4.split_rt = new_ptr;
854 }
855
856 sprintf(env_var, "VPN_ROUTE_DEST_%d", tunnel->ipv4.split_routes);
857 setenv(env_var, dest, 0);
858 sprintf(env_var, "VPN_ROUTE_MASK_%d", tunnel->ipv4.split_routes);
859 setenv(env_var, mask, 0);
860 if (gateway != NULL) {
861 sprintf(env_var, "VPN_ROUTE_GATEWAY_%d",
862 tunnel->ipv4.split_routes);
863 setenv(env_var, gateway, 0);
864 }
865
866 route = &tunnel->ipv4.split_rt[tunnel->ipv4.split_routes++];
867
868 route_init(route);
869 route_dest(route).s_addr = inet_addr(dest);
870 route_mask(route).s_addr = inet_addr(mask);
871 if (gateway != NULL) {
872 route_gtw(route).s_addr = inet_addr(gateway);
873 route->rt_flags |= RTF_GATEWAY;
874 } else {
875 free(route_iface(route));
876 route_iface(route) = strdup(tunnel->ppp_iface);
877 if (!route_iface(route))
878 return ERR_IPV4_NO_MEM;
879 }
880
881 return 0;
882 }
883
ipv4_set_split_routes(struct tunnel * tunnel)884 static int ipv4_set_split_routes(struct tunnel *tunnel)
885 {
886 int i;
887
888 for (i = 0; i < tunnel->ipv4.split_routes; i++) {
889 struct rtentry_ofvpn *route;
890 int ret;
891
892 route = &tunnel->ipv4.split_rt[i];
893 // check if the route to be added is not the one to the gateway itself
894 if (route_dest(route).s_addr == route_dest(&tunnel->ipv4.gtw_rt).s_addr) {
895 log_debug("Skipping route to tunnel gateway (%s).\n",
896 ipv4_show_route(route));
897 continue;
898 }
899
900 free(route_iface(route));
901 route_iface(route) = strdup(tunnel->ppp_iface);
902 if (!route_iface(route))
903 return ERR_IPV4_NO_MEM;
904 if (route_gtw(route).s_addr == tunnel->ipv4.ip_addr.s_addr)
905 route_gtw(route).s_addr = 0;
906 if (route_gtw(route).s_addr == 0)
907 route->rt_flags &= ~RTF_GATEWAY;
908 if (route_gtw(route).s_addr != 0)
909 route->rt_flags |= RTF_GATEWAY;
910 ret = ipv4_set_route(route);
911 if (ret == ERR_IPV4_SEE_ERRNO && errno == EEXIST)
912 log_warn("Route to gateway exists already.\n");
913 else if (ret != 0)
914 log_warn("Could not set route to tunnel gateway (%s).\n",
915 err_ipv4_str(ret));
916 }
917 return 0;
918 }
919
ipv4_set_default_routes(struct tunnel * tunnel)920 static int ipv4_set_default_routes(struct tunnel *tunnel)
921 {
922 int ret;
923 struct rtentry_ofvpn *def_rt = &tunnel->ipv4.def_rt;
924 struct rtentry_ofvpn *ppp_rt = &tunnel->ipv4.ppp_rt;
925 struct vpn_config *cfg = tunnel->config;
926
927 route_init(ppp_rt);
928
929 if (cfg->half_internet_routes == 0) {
930 // Delete the current default route
931 log_debug("Deleting the current default route...\n");
932 ret = ipv4_del_route(def_rt);
933 if (ret != 0)
934 log_warn("Could not delete the current default route (%s).\n",
935 err_ipv4_str(ret));
936
937 // Set the new default route
938 // ip route add to 0/0 dev ppp0
939 route_dest(ppp_rt).s_addr = inet_addr("0.0.0.0");
940 route_mask(ppp_rt).s_addr = inet_addr("0.0.0.0");
941 route_gtw(ppp_rt).s_addr = inet_addr("0.0.0.0");
942 log_debug("Setting new default route...\n");
943
944 free(route_iface(ppp_rt));
945 route_iface(ppp_rt) = strdup(tunnel->ppp_iface);
946 if (!route_iface(ppp_rt))
947 return ERR_IPV4_NO_MEM;
948 if (route_gtw(ppp_rt).s_addr == tunnel->ipv4.ip_addr.s_addr)
949 route_gtw(ppp_rt).s_addr = 0;
950 if (route_gtw(ppp_rt).s_addr == 0)
951 ppp_rt->rt_flags &= ~RTF_GATEWAY;
952 if (route_gtw(ppp_rt).s_addr != 0)
953 ppp_rt->rt_flags |= RTF_GATEWAY;
954 ret = ipv4_set_route(ppp_rt);
955 if (ret == ERR_IPV4_SEE_ERRNO && errno == EEXIST) {
956 log_warn("Default route exists already.\n");
957 } else if (ret != 0) {
958 log_warn("Could not set the new default route (%s).\n",
959 err_ipv4_str(ret));
960 }
961
962 } else {
963 // Emulate default routes as two "half internet" routes
964 // This allows for e.g. DHCP renewing default routes without
965 // breaking the tunnel
966 log_debug("Setting new half-internet routes...\n");
967 route_dest(ppp_rt).s_addr = inet_addr("0.0.0.0");
968 route_mask(ppp_rt).s_addr = inet_addr("128.0.0.0");
969
970 free(route_iface(ppp_rt));
971 route_iface(ppp_rt) = strdup(tunnel->ppp_iface);
972 if (!route_iface(ppp_rt))
973 return ERR_IPV4_NO_MEM;
974 if (route_gtw(ppp_rt).s_addr == tunnel->ipv4.ip_addr.s_addr)
975 route_gtw(ppp_rt).s_addr = 0;
976 if (route_gtw(ppp_rt).s_addr == 0)
977 ppp_rt->rt_flags &= ~RTF_GATEWAY;
978 if (route_gtw(ppp_rt).s_addr != 0)
979 ppp_rt->rt_flags |= RTF_GATEWAY;
980 ret = ipv4_set_route(ppp_rt);
981 if (ret == ERR_IPV4_SEE_ERRNO && errno == EEXIST) {
982 log_warn("0.0.0.0/1 route exists already.\n");
983 } else if (ret != 0) {
984 log_warn("Could not set the new 0.0.0.0/1 route (%s).\n",
985 err_ipv4_str(ret));
986 }
987
988 route_dest(ppp_rt).s_addr = inet_addr("128.0.0.0");
989 ret = ipv4_set_route(ppp_rt);
990 if (ret == ERR_IPV4_SEE_ERRNO && errno == EEXIST) {
991 log_warn("128.0.0.0/1 route exists already.\n");
992 } else if (ret != 0) {
993 log_warn("Could not set the new 128.0.0.0/1 route (%s).\n",
994 err_ipv4_str(ret));
995 }
996 }
997
998 return 0;
999 }
1000
ipv4_set_tunnel_routes(struct tunnel * tunnel)1001 int ipv4_set_tunnel_routes(struct tunnel *tunnel)
1002 {
1003 int ret = ipv4_protect_tunnel_route(tunnel);
1004
1005 if (tunnel->ipv4.split_routes)
1006 // try even if ipv4_protect_tunnel_route has failed
1007 return ipv4_set_split_routes(tunnel);
1008 else if (ret == 0)
1009 return ipv4_set_default_routes(tunnel);
1010 else
1011 return ret;
1012 }
1013
ipv4_restore_routes(struct tunnel * tunnel)1014 int ipv4_restore_routes(struct tunnel *tunnel)
1015 {
1016 struct rtentry_ofvpn *def_rt = &tunnel->ipv4.def_rt;
1017 struct rtentry_ofvpn *gtw_rt = &tunnel->ipv4.gtw_rt;
1018 struct rtentry_ofvpn *ppp_rt = &tunnel->ipv4.ppp_rt;
1019 struct vpn_config *cfg = tunnel->config;
1020
1021 if (tunnel->ipv4.route_to_vpn_is_added) {
1022 int ret;
1023
1024 ret = ipv4_del_route(gtw_rt);
1025 if (ret != 0)
1026 log_warn("Could not delete route to vpn server (%s).\n",
1027 err_ipv4_str(ret));
1028 if ((cfg->half_internet_routes == 0) &&
1029 (tunnel->ipv4.split_routes == 0)) {
1030 ret = ipv4_del_route(ppp_rt);
1031 if (ret != 0)
1032 log_warn("Could not delete route through tunnel (%s).\n",
1033 err_ipv4_str(ret));
1034
1035 // Restore the default route. It seems not to be
1036 // automatically restored on all linux distributions
1037 ret = ipv4_set_route(def_rt);
1038 if (ret != 0) {
1039 log_warn("Could not restore default route (%s). Already restored?\n",
1040 err_ipv4_str(ret));
1041 }
1042 }
1043 } else {
1044 log_debug("Route to vpn server was not added\n");
1045 }
1046 route_destroy(ppp_rt);
1047 route_destroy(def_rt);
1048 route_destroy(gtw_rt);
1049
1050 return 0;
1051 }
1052
replace_char(char * str,char find,char replace)1053 static inline char *replace_char(char *str, char find, char replace)
1054 {
1055 int i;
1056
1057 for (i = 0; i < strlen(str); i++)
1058 if (str[i] == find)
1059 str[i] = replace;
1060 return str;
1061 }
1062
ipv4_add_nameservers_to_resolv_conf(struct tunnel * tunnel)1063 int ipv4_add_nameservers_to_resolv_conf(struct tunnel *tunnel)
1064 {
1065 int ret = -1;
1066 FILE *file;
1067 struct stat stat;
1068 #define NS_SIZE ARRAY_SIZE("nameserver xxx.xxx.xxx.xxx\n")
1069 char ns1[NS_SIZE], ns2[NS_SIZE];
1070 #undef NS_SIZE
1071 #define DNS_SUFFIX_SIZE (ARRAY_SIZE("search \n") + MAX_DOMAIN_LENGTH)
1072 char dns_suffix[DNS_SUFFIX_SIZE];
1073 #undef DNS_SUFFIX_SIZE
1074 char *buffer = NULL;
1075 #if HAVE_RESOLVCONF
1076 int use_resolvconf = 0;
1077 #endif
1078
1079 tunnel->ipv4.ns1_was_there = 0;
1080 tunnel->ipv4.ns2_was_there = 0;
1081 tunnel->ipv4.dns_suffix_was_there = 0;
1082
1083 if (tunnel->ipv4.ns1_addr.s_addr == 0)
1084 tunnel->ipv4.ns1_was_there = -1;
1085
1086 if (tunnel->ipv4.ns2_addr.s_addr == 0)
1087 tunnel->ipv4.ns2_was_there = -1;
1088
1089 #if HAVE_RESOLVCONF
1090 if (tunnel->config->use_resolvconf
1091 && (access(RESOLVCONF_PATH, F_OK) == 0)) {
1092 int resolvconf_call_len;
1093 char *resolvconf_call;
1094
1095 log_debug("Attempting to run %s.\n", RESOLVCONF_PATH);
1096 resolvconf_call_len = strlen(RESOLVCONF_PATH) + 20
1097 + strlen(tunnel->ppp_iface);
1098 resolvconf_call = malloc(resolvconf_call_len);
1099 if (resolvconf_call == NULL) {
1100 log_warn("Could not create command to run resolvconf (%s).\n",
1101 strerror(errno));
1102 return 1;
1103 }
1104
1105 snprintf(resolvconf_call, resolvconf_call_len,
1106 "%s -a \"%s.openfortivpn\"",
1107 RESOLVCONF_PATH,
1108 tunnel->ppp_iface);
1109
1110 use_resolvconf = 1;
1111 log_debug("resolvconf_call: %s\n", resolvconf_call);
1112 file = popen(resolvconf_call, "w");
1113 if (file == NULL) {
1114 log_warn("Could not open pipe %s (%s).\n",
1115 resolvconf_call,
1116 strerror(errno));
1117 free(resolvconf_call);
1118 return 1;
1119 }
1120 free(resolvconf_call);
1121 } else {
1122 #endif
1123 log_debug("Attempting to modify /etc/resolv.conf directly.\n");
1124 file = fopen("/etc/resolv.conf", "r+");
1125 if (file == NULL) {
1126 log_warn("Could not open /etc/resolv.conf (%s).\n",
1127 strerror(errno));
1128 return 1;
1129 }
1130
1131 if (fstat(fileno(file), &stat) == -1) {
1132 log_warn("Could not stat /etc/resolv.conf (%s).\n",
1133 strerror(errno));
1134 goto err_close;
1135 }
1136
1137 if (stat.st_size == 0) {
1138 log_warn("Could not read /etc/resolv.conf (%s).\n",
1139 "Empty file");
1140 goto err_close;
1141 }
1142
1143 buffer = malloc(stat.st_size + 1);
1144 if (buffer == NULL) {
1145 log_warn("Could not read /etc/resolv.conf (%s).\n",
1146 strerror(errno));
1147 goto err_close;
1148 }
1149
1150 // Copy all file contents at once
1151 if (fread(buffer, stat.st_size, 1, file) != 1) {
1152 log_warn("Could not read /etc/resolv.conf.\n");
1153 goto err_free;
1154 }
1155
1156 buffer[stat.st_size] = '\0';
1157 #if HAVE_RESOLVCONF
1158 }
1159 #endif
1160 if (tunnel->ipv4.ns1_addr.s_addr != 0) {
1161 strcpy(ns1, "nameserver ");
1162 strncat(ns1, inet_ntoa(tunnel->ipv4.ns1_addr), 15);
1163 } else {
1164 ns1[0] = '\0';
1165 }
1166
1167 if (tunnel->ipv4.ns2_addr.s_addr != 0) {
1168 strcpy(ns2, "nameserver ");
1169 strncat(ns2, inet_ntoa(tunnel->ipv4.ns2_addr), 15);
1170 } else {
1171 ns2[0] = '\0';
1172 }
1173
1174 if (tunnel->ipv4.dns_suffix != NULL) {
1175 strcpy(dns_suffix, "search ");
1176 strncat(dns_suffix, tunnel->ipv4.dns_suffix, MAX_DOMAIN_LENGTH);
1177 replace_char(dns_suffix, ';', ' ');
1178 } else {
1179 dns_suffix[0] = '\0';
1180 }
1181
1182 #if HAVE_RESOLVCONF
1183 if (use_resolvconf == 0) {
1184 #endif
1185 char *saveptr = NULL;
1186
1187 for (const char *line = strtok_r(buffer, "\n", &saveptr);
1188 line != NULL;
1189 line = strtok_r(NULL, "\n", &saveptr)) {
1190 if (strcmp(line, ns1) == 0) {
1191 tunnel->ipv4.ns1_was_there = 1;
1192 log_debug("ns1 already present in /etc/resolv.conf.\n");
1193 }
1194 }
1195
1196 if (tunnel->ipv4.ns1_was_there == 0)
1197 log_debug("Adding \"%s\", to /etc/resolv.conf.\n", ns1);
1198
1199 for (const char *line = strtok_r(buffer, "\n", &saveptr);
1200 line != NULL;
1201 line = strtok_r(NULL, "\n", &saveptr)) {
1202 if (strcmp(line, ns2) == 0) {
1203 tunnel->ipv4.ns2_was_there = 1;
1204 log_debug("ns2 already present in /etc/resolv.conf.\n");
1205 }
1206 }
1207
1208 if (tunnel->ipv4.ns2_was_there == 0)
1209 log_debug("Adding \"%s\", to /etc/resolv.conf.\n", ns2);
1210
1211 if (dns_suffix[0] == '\0') {
1212 tunnel->ipv4.dns_suffix_was_there = -1;
1213 } else {
1214 for (const char *line = strtok_r(buffer, "\n", &saveptr);
1215 line != NULL;
1216 line = strtok_r(NULL, "\n", &saveptr)) {
1217 if (dns_suffix[0] != '\0'
1218 && strcmp(line, dns_suffix) == 0) {
1219 tunnel->ipv4.dns_suffix_was_there = 1;
1220 log_debug("dns_suffix already present in /etc/resolv.conf.\n");
1221 }
1222 }
1223 }
1224
1225 if (tunnel->ipv4.dns_suffix_was_there == 0)
1226 log_debug("Adding \"%s\", to /etc/resolv.conf.\n", dns_suffix);
1227
1228 rewind(file);
1229 if (fread(buffer, stat.st_size, 1, file) != 1) {
1230 log_warn("Could not read /etc/resolv.conf.\n");
1231 goto err_free;
1232 }
1233
1234 buffer[stat.st_size] = '\0';
1235
1236 rewind(file);
1237 #if HAVE_RESOLVCONF
1238 }
1239 #endif
1240 if (tunnel->ipv4.ns1_was_there == 0) {
1241 strcat(ns1, "\n");
1242 fputs(ns1, file);
1243 }
1244 if (tunnel->ipv4.ns2_was_there == 0) {
1245 strcat(ns2, "\n");
1246 fputs(ns2, file);
1247 }
1248 if (tunnel->ipv4.dns_suffix_was_there == 0) {
1249 strcat(dns_suffix, "\n");
1250 fputs(dns_suffix, file);
1251 }
1252 #if HAVE_RESOLVCONF
1253 if (use_resolvconf == 0)
1254 #endif
1255 fwrite(buffer, stat.st_size, 1, file);
1256
1257 ret = 0;
1258
1259 err_free:
1260 free(buffer);
1261 err_close:
1262 #if HAVE_RESOLVCONF
1263 if (use_resolvconf == 0) {
1264 #endif
1265 if (fclose(file))
1266 log_warn("Could not close /etc/resolv.conf: %s\n",
1267 strerror(errno));
1268 #if HAVE_RESOLVCONF
1269 } else {
1270 if (pclose(file) == -1)
1271 log_warn("Could not close resolvconf pipe: %s\n",
1272 strerror(errno));
1273 }
1274 #endif
1275
1276 return ret;
1277 }
1278
ipv4_del_nameservers_from_resolv_conf(struct tunnel * tunnel)1279 int ipv4_del_nameservers_from_resolv_conf(struct tunnel *tunnel)
1280 {
1281 int ret = -1;
1282 FILE *file;
1283 struct stat stat;
1284 #define NS_SIZE ARRAY_SIZE("nameserver xxx.xxx.xxx.xxx")
1285 char ns1[NS_SIZE], ns2[NS_SIZE];
1286 #undef NS_SIZE
1287 #define DNS_SUFFIX_SIZE (ARRAY_SIZE("search ") + MAX_DOMAIN_LENGTH)
1288 char dns_suffix[DNS_SUFFIX_SIZE];
1289 #undef DNS_SUFFIX_SIZE
1290 char *buffer = NULL;
1291 char *saveptr = NULL;
1292
1293 #if HAVE_RESOLVCONF
1294 if (tunnel->config->use_resolvconf
1295 && (access(RESOLVCONF_PATH, F_OK) == 0)) {
1296 int resolvconf_call_len;
1297 char *resolvconf_call;
1298
1299 resolvconf_call_len = strlen(RESOLVCONF_PATH) + 20
1300 + strlen(tunnel->ppp_iface);
1301 resolvconf_call = malloc(resolvconf_call_len);
1302 if (resolvconf_call == NULL) {
1303 log_warn("Could not create command to run resolvconf (%s).\n",
1304 strerror(errno));
1305 return ERR_IPV4_SEE_ERRNO;
1306 }
1307
1308 snprintf(resolvconf_call,
1309 resolvconf_call_len,
1310 "%s -d \"%s.openfortivpn\"",
1311 RESOLVCONF_PATH,
1312 tunnel->ppp_iface
1313 );
1314
1315 log_debug("resolvconf_call: %s\n", resolvconf_call);
1316 ret = system(resolvconf_call);
1317 free(resolvconf_call);
1318 if (ret == -1)
1319 return ERR_IPV4_SEE_ERRNO;
1320 return 0;
1321 }
1322 #endif
1323
1324 file = fopen("/etc/resolv.conf", "r+");
1325 if (file == NULL) {
1326 log_warn("Could not open /etc/resolv.conf (%s).\n",
1327 strerror(errno));
1328 return 1;
1329 }
1330
1331 if (fstat(fileno(file), &stat) == -1) {
1332 log_warn("Could not stat /etc/resolv.conf (%s).\n",
1333 strerror(errno));
1334 goto err_close;
1335 }
1336
1337 buffer = malloc(stat.st_size + 1);
1338 if (buffer == NULL) {
1339 log_warn("Could not read /etc/resolv.conf (%s).\n",
1340 strerror(errno));
1341 goto err_close;
1342 }
1343
1344 // Copy all file contents at once
1345 if (fread(buffer, stat.st_size, 1, file) != 1) {
1346 log_warn("Could not read /etc/resolv.conf.\n");
1347 goto err_free;
1348 }
1349
1350 buffer[stat.st_size] = '\0';
1351
1352 ns1[0] = '\0';
1353 if (tunnel->ipv4.ns1_addr.s_addr != 0) {
1354 strcpy(ns1, "nameserver ");
1355 strncat(ns1, inet_ntoa(tunnel->ipv4.ns1_addr), 15);
1356 }
1357 ns2[0] = '\0';
1358 if (tunnel->ipv4.ns2_addr.s_addr != 0) {
1359 strcpy(ns2, "nameserver ");
1360 strncat(ns2, inet_ntoa(tunnel->ipv4.ns2_addr), 15);
1361 }
1362 dns_suffix[0] = '\0';
1363 if (tunnel->ipv4.dns_suffix != NULL && tunnel->ipv4.dns_suffix[0] != '\0') {
1364 strcpy(dns_suffix, "search ");
1365 strncat(dns_suffix, tunnel->ipv4.dns_suffix, MAX_DOMAIN_LENGTH);
1366 }
1367
1368 file = freopen("/etc/resolv.conf", "w", file);
1369 if (file == NULL) {
1370 log_warn("Could not reopen /etc/resolv.conf (%s).\n",
1371 strerror(errno));
1372 goto err_free;
1373 }
1374
1375 for (const char *line = strtok_r(buffer, "\n", &saveptr);
1376 line != NULL;
1377 line = strtok_r(NULL, "\n", &saveptr)) {
1378 if (ns1[0] != '\0' && strcmp(line, ns1) == 0
1379 && (tunnel->ipv4.ns1_was_there == 0)) {
1380 log_debug("Deleting \"%s\" from /etc/resolv.conf.\n", ns1);
1381 } else if (ns2[0] != '\0' && strcmp(line, ns2) == 0
1382 && (tunnel->ipv4.ns2_was_there == 0)) {
1383 log_debug("Deleting \"%s\" from /etc/resolv.conf.\n", ns2);
1384 } else if (dns_suffix[0] != '\0' && strcmp(line, dns_suffix) == 0
1385 && (tunnel->ipv4.dns_suffix_was_there == 0)) {
1386 log_debug("Deleting \"%s\" from /etc/resolv.conf.\n", dns_suffix);
1387 } else {
1388 fputs(line, file);
1389 fputs("\n", file);
1390 }
1391 }
1392
1393 ret = 0;
1394
1395 err_free:
1396 free(buffer);
1397 err_close:
1398 if (file && fclose(file))
1399 log_warn("Could not close /etc/resolv.conf (%s).\n",
1400 strerror(errno));
1401 return ret;
1402 }
1403