1 /*
2 * Simplified Interface To NetLink
3 *
4 * Copyright (C) 2016-2018 Antonio Quartulli <a@unstable.cc>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2
8 * as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program (see the file COPYING included with this
17 * distribution); if not, write to the Free Software Foundation, Inc.,
18 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #elif defined(_MSC_VER)
24 #include "config-msvc.h"
25 #endif
26
27 #ifdef TARGET_LINUX
28
29 #include "syshead.h"
30
31 #include "errlevel.h"
32 #include "buffer.h"
33 #include "networking.h"
34
35 #include <errno.h>
36 #include <string.h>
37 #include <unistd.h>
38 #include <sys/types.h>
39 #include <sys/socket.h>
40 #include <linux/netlink.h>
41 #include <linux/rtnetlink.h>
42
43 #define SNDBUF_SIZE (1024 * 2)
44 #define RCVBUF_SIZE (1024 * 4)
45
46 #define SITNL_ADDATTR(_msg, _max_size, _attr, _data, _size) \
47 { \
48 if (sitnl_addattr(_msg, _max_size, _attr, _data, _size) < 0) \
49 { \
50 goto err; \
51 } \
52 }
53
54 #define NLMSG_TAIL(nmsg) \
55 ((struct rtattr *)(((uint8_t *)(nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
56
57 /**
58 * Generic address data structure used to pass addresses and prefixes as
59 * argument to AF family agnostic functions
60 */
61 typedef union {
62 in_addr_t ipv4;
63 struct in6_addr ipv6;
64 } inet_address_t;
65
66 /**
67 * Link state request message
68 */
69 struct sitnl_link_req {
70 struct nlmsghdr n;
71 struct ifinfomsg i;
72 char buf[256];
73 };
74
75 /**
76 * Address request message
77 */
78 struct sitnl_addr_req {
79 struct nlmsghdr n;
80 struct ifaddrmsg i;
81 char buf[256];
82 };
83
84 /**
85 * Route request message
86 */
87 struct sitnl_route_req {
88 struct nlmsghdr n;
89 struct rtmsg r;
90 char buf[256];
91 };
92
93 typedef int (*sitnl_parse_reply_cb)(struct nlmsghdr *msg, void *arg);
94
95 /**
96 * Object returned by route request operation
97 */
98 struct sitnl_route_data_cb {
99 unsigned int iface;
100 inet_address_t gw;
101 };
102
103 /**
104 * Helper function used to easily add attributes to a rtnl message
105 */
106 static int
sitnl_addattr(struct nlmsghdr * n,int maxlen,int type,const void * data,int alen)107 sitnl_addattr(struct nlmsghdr *n, int maxlen, int type, const void *data,
108 int alen)
109 {
110 int len = RTA_LENGTH(alen);
111 struct rtattr *rta;
112
113 if ((int)(NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len)) > maxlen)
114 {
115 msg(M_WARN, "%s: rtnl: message exceeded bound of %d", __func__,
116 maxlen);
117 return -EMSGSIZE;
118 }
119
120 rta = NLMSG_TAIL(n);
121 rta->rta_type = type;
122 rta->rta_len = len;
123
124 if (!data)
125 {
126 memset(RTA_DATA(rta), 0, alen);
127 }
128 else
129 {
130 memcpy(RTA_DATA(rta), data, alen);
131 }
132
133 n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
134
135 return 0;
136 }
137
138 /**
139 * Open RTNL socket
140 */
141 static int
sitnl_socket(void)142 sitnl_socket(void)
143 {
144 int sndbuf = SNDBUF_SIZE;
145 int rcvbuf = RCVBUF_SIZE;
146 int fd;
147
148 fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
149 if (fd < 0)
150 {
151 msg(M_WARN, "%s: cannot open netlink socket", __func__);
152 return fd;
153 }
154
155 if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)) < 0)
156 {
157 msg(M_WARN | M_ERRNO, "%s: SO_SNDBUF", __func__);
158 close(fd);
159 return -1;
160 }
161
162 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)) < 0)
163 {
164 msg(M_WARN | M_ERRNO, "%s: SO_RCVBUF", __func__);
165 close(fd);
166 return -1;
167 }
168
169 return fd;
170 }
171
172 /**
173 * Bind socket to Netlink subsystem
174 */
175 static int
sitnl_bind(int fd,uint32_t groups)176 sitnl_bind(int fd, uint32_t groups)
177 {
178 socklen_t addr_len;
179 struct sockaddr_nl local;
180
181 CLEAR(local);
182
183 local.nl_family = AF_NETLINK;
184 local.nl_groups = groups;
185
186 if (bind(fd, (struct sockaddr *)&local, sizeof(local)) < 0)
187 {
188 msg(M_WARN | M_ERRNO, "%s: cannot bind netlink socket", __func__);
189 return -errno;
190 }
191
192 addr_len = sizeof(local);
193 if (getsockname(fd, (struct sockaddr *)&local, &addr_len) < 0)
194 {
195 msg(M_WARN | M_ERRNO, "%s: cannot getsockname", __func__);
196 return -errno;
197 }
198
199 if (addr_len != sizeof(local))
200 {
201 msg(M_WARN, "%s: wrong address length %d", __func__, addr_len);
202 return -EINVAL;
203 }
204
205 if (local.nl_family != AF_NETLINK)
206 {
207 msg(M_WARN, "%s: wrong address family %d", __func__, local.nl_family);
208 return -EINVAL;
209 }
210
211 return 0;
212 }
213
214 /**
215 * Send Netlink message and run callback on reply (if specified)
216 */
217 static int
sitnl_send(struct nlmsghdr * payload,pid_t peer,unsigned int groups,sitnl_parse_reply_cb cb,void * arg_cb)218 sitnl_send(struct nlmsghdr *payload, pid_t peer, unsigned int groups,
219 sitnl_parse_reply_cb cb, void *arg_cb)
220 {
221 int len, rem_len, fd, ret, rcv_len;
222 struct sockaddr_nl nladdr;
223 struct nlmsgerr *err;
224 struct nlmsghdr *h;
225 unsigned int seq;
226 char buf[1024 * 16];
227 struct iovec iov =
228 {
229 .iov_base = payload,
230 .iov_len = payload->nlmsg_len,
231 };
232 struct msghdr nlmsg =
233 {
234 .msg_name = &nladdr,
235 .msg_namelen = sizeof(nladdr),
236 .msg_iov = &iov,
237 .msg_iovlen = 1,
238 };
239
240 CLEAR(nladdr);
241
242 nladdr.nl_family = AF_NETLINK;
243 nladdr.nl_pid = peer;
244 nladdr.nl_groups = groups;
245
246 payload->nlmsg_seq = seq = time(NULL);
247
248 /* no need to send reply */
249 if (!cb)
250 {
251 payload->nlmsg_flags |= NLM_F_ACK;
252 }
253
254 fd = sitnl_socket();
255 if (fd < 0)
256 {
257 msg(M_WARN | M_ERRNO, "%s: can't open rtnl socket", __func__);
258 return -errno;
259 }
260
261 ret = sitnl_bind(fd, 0);
262 if (ret < 0)
263 {
264 msg(M_WARN | M_ERRNO, "%s: can't bind rtnl socket", __func__);
265 ret = -errno;
266 goto out;
267 }
268
269 ret = sendmsg(fd, &nlmsg, 0);
270 if (ret < 0)
271 {
272 msg(M_WARN | M_ERRNO, "%s: rtnl: error on sendmsg()", __func__);
273 ret = -errno;
274 goto out;
275 }
276
277 /* prepare buffer to store RTNL replies */
278 memset(buf, 0, sizeof(buf));
279 iov.iov_base = buf;
280
281 while (1)
282 {
283 /*
284 * iov_len is modified by recvmsg(), therefore has to be initialized before
285 * using it again
286 */
287 msg(D_RTNL, "%s: checking for received messages", __func__);
288 iov.iov_len = sizeof(buf);
289 rcv_len = recvmsg(fd, &nlmsg, 0);
290 msg(D_RTNL, "%s: rtnl: received %d bytes", __func__, rcv_len);
291 if (rcv_len < 0)
292 {
293 if ((errno == EINTR) || (errno == EAGAIN))
294 {
295 msg(D_RTNL, "%s: interrupted call", __func__);
296 continue;
297 }
298 msg(M_WARN | M_ERRNO, "%s: rtnl: error on recvmsg()", __func__);
299 ret = -errno;
300 goto out;
301 }
302
303 if (rcv_len == 0)
304 {
305 msg(M_WARN, "%s: rtnl: socket reached unexpected EOF", __func__);
306 ret = -EIO;
307 goto out;
308 }
309
310 if (nlmsg.msg_namelen != sizeof(nladdr))
311 {
312 msg(M_WARN, "%s: sender address length: %u (expected %zu)",
313 __func__, nlmsg.msg_namelen, sizeof(nladdr));
314 ret = -EIO;
315 goto out;
316 }
317
318 h = (struct nlmsghdr *)buf;
319 while (rcv_len >= (int)sizeof(*h))
320 {
321 len = h->nlmsg_len;
322 rem_len = len - sizeof(*h);
323
324 if ((rem_len < 0) || (len > rcv_len))
325 {
326 if (nlmsg.msg_flags & MSG_TRUNC)
327 {
328 msg(M_WARN, "%s: truncated message", __func__);
329 ret = -EIO;
330 goto out;
331 }
332 msg(M_WARN, "%s: malformed message: len=%d", __func__, len);
333 ret = -EIO;
334 goto out;
335 }
336
337 /* if (((int)nladdr.nl_pid != peer) || (h->nlmsg_pid != nladdr.nl_pid)
338 * || (h->nlmsg_seq != seq))
339 * {
340 * rcv_len -= NLMSG_ALIGN(len);
341 * h = (struct nlmsghdr *)((char *)h + NLMSG_ALIGN(len));
342 * msg(M_DEBUG, "%s: skipping unrelated message. nl_pid:%d (peer:%d) nl_msg_pid:%d nl_seq:%d seq:%d",
343 * __func__, (int)nladdr.nl_pid, peer, h->nlmsg_pid,
344 * h->nlmsg_seq, seq);
345 * continue;
346 * }
347 */
348
349 if (h->nlmsg_type == NLMSG_DONE)
350 {
351 ret = 0;
352 goto out;
353 }
354
355 if (h->nlmsg_type == NLMSG_ERROR)
356 {
357 err = (struct nlmsgerr *)NLMSG_DATA(h);
358 if (rem_len < (int)sizeof(struct nlmsgerr))
359 {
360 msg(M_WARN, "%s: ERROR truncated", __func__);
361 ret = -EIO;
362 }
363 else
364 {
365 if (!err->error)
366 {
367 ret = 0;
368 if (cb)
369 {
370 int r = cb(h, arg_cb);
371 if (r <= 0)
372 {
373 ret = r;
374 }
375 }
376 }
377 else
378 {
379 msg(M_WARN, "%s: rtnl: generic error (%d): %s",
380 __func__, err->error, strerror(-err->error));
381 ret = err->error;
382 }
383 }
384 goto out;
385 }
386
387 if (cb)
388 {
389 int r = cb(h, arg_cb);
390 if (r <= 0)
391 {
392 ret = r;
393 goto out;
394 }
395 }
396 else
397 {
398 msg(M_WARN, "%s: RTNL: unexpected reply", __func__);
399 }
400
401 rcv_len -= NLMSG_ALIGN(len);
402 h = (struct nlmsghdr *)((char *)h + NLMSG_ALIGN(len));
403 }
404
405 if (nlmsg.msg_flags & MSG_TRUNC)
406 {
407 msg(M_WARN, "%s: message truncated", __func__);
408 continue;
409 }
410
411 if (rcv_len)
412 {
413 msg(M_WARN, "%s: rtnl: %d not parsed bytes", __func__, rcv_len);
414 ret = -1;
415 goto out;
416 }
417 }
418 out:
419 close(fd);
420
421 return ret;
422 }
423
424 typedef struct {
425 int addr_size;
426 inet_address_t gw;
427 char iface[IFNAMSIZ];
428 bool default_only;
429 unsigned int table;
430 } route_res_t;
431
432 static int
sitnl_route_save(struct nlmsghdr * n,void * arg)433 sitnl_route_save(struct nlmsghdr *n, void *arg)
434 {
435 route_res_t *res = arg;
436 struct rtmsg *r = NLMSG_DATA(n);
437 struct rtattr *rta = RTM_RTA(r);
438 int len = n->nlmsg_len - NLMSG_LENGTH(sizeof(*r));
439 unsigned int table, ifindex = 0;
440 void *gw = NULL;
441
442 /* filter-out non-zero dst prefixes */
443 if (res->default_only && r->rtm_dst_len != 0)
444 {
445 return 1;
446 }
447
448 /* route table, ignored with RTA_TABLE */
449 table = r->rtm_table;
450
451 while (RTA_OK(rta, len))
452 {
453 switch (rta->rta_type)
454 {
455 /* route interface */
456 case RTA_OIF:
457 ifindex = *(unsigned int *)RTA_DATA(rta);
458 break;
459
460 /* route prefix */
461 case RTA_DST:
462 break;
463
464 /* GW for the route */
465 case RTA_GATEWAY:
466 gw = RTA_DATA(rta);
467 break;
468
469 /* route table */
470 case RTA_TABLE:
471 table = *(unsigned int *)RTA_DATA(rta);
472 break;
473 }
474
475 rta = RTA_NEXT(rta, len);
476 }
477
478 /* filter out any route not coming from the selected table */
479 if (res->table && res->table != table)
480 {
481 return 1;
482 }
483
484 if (!if_indextoname(ifindex, res->iface))
485 {
486 msg(M_WARN | M_ERRNO, "%s: rtnl: can't get ifname for index %d",
487 __func__, ifindex);
488 return -1;
489 }
490
491 if (gw)
492 {
493 memcpy(&res->gw, gw, res->addr_size);
494 }
495
496 return 0;
497 }
498
499 static int
sitnl_route_best_gw(sa_family_t af_family,const inet_address_t * dst,void * best_gw,char * best_iface)500 sitnl_route_best_gw(sa_family_t af_family, const inet_address_t *dst,
501 void *best_gw, char *best_iface)
502 {
503 struct sitnl_route_req req;
504 route_res_t res;
505 int ret = -EINVAL;
506
507 ASSERT(best_gw);
508 ASSERT(best_iface);
509
510 CLEAR(req);
511 CLEAR(res);
512
513 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.r));
514 req.n.nlmsg_type = RTM_GETROUTE;
515 req.n.nlmsg_flags = NLM_F_REQUEST;
516
517 req.r.rtm_family = af_family;
518
519 switch (af_family)
520 {
521 case AF_INET:
522 res.addr_size = sizeof(in_addr_t);
523 /*
524 * kernel can't return 0.0.0.0/8 host route, dump all
525 * the routes and filter for 0.0.0.0/0 in cb()
526 */
527 if (!dst || !dst->ipv4)
528 {
529 req.n.nlmsg_flags |= NLM_F_DUMP;
530 res.default_only = true;
531 res.table = RT_TABLE_MAIN;
532 }
533 else
534 {
535 req.r.rtm_dst_len = 32;
536 }
537 break;
538
539 case AF_INET6:
540 res.addr_size = sizeof(struct in6_addr);
541 /* kernel can return ::/128 host route */
542 req.r.rtm_dst_len = 128;
543 break;
544
545 default:
546 /* unsupported */
547 return -EINVAL;
548 }
549
550 SITNL_ADDATTR(&req.n, sizeof(req), RTA_DST, dst, res.addr_size);
551
552 ret = sitnl_send(&req.n, 0, 0, sitnl_route_save, &res);
553 if (ret < 0)
554 {
555 goto err;
556 }
557
558 /* save result in output variables */
559 memcpy(best_gw, &res.gw, res.addr_size);
560 strncpy(best_iface, res.iface, IFNAMSIZ);
561 err:
562 return ret;
563
564 }
565
566 /* used by iproute2 implementation too */
567 int
net_route_v6_best_gw(openvpn_net_ctx_t * ctx,const struct in6_addr * dst,struct in6_addr * best_gw,char * best_iface)568 net_route_v6_best_gw(openvpn_net_ctx_t *ctx, const struct in6_addr *dst,
569 struct in6_addr *best_gw, char *best_iface)
570 {
571 inet_address_t dst_v6 = {0};
572 char buf[INET6_ADDRSTRLEN];
573 int ret;
574
575 if (dst)
576 {
577 dst_v6.ipv6 = *dst;
578 }
579
580 msg(D_ROUTE, "%s query: dst %s", __func__,
581 inet_ntop(AF_INET6, &dst_v6.ipv6, buf, sizeof(buf)));
582
583 ret = sitnl_route_best_gw(AF_INET6, &dst_v6, best_gw, best_iface);
584 if (ret < 0)
585 {
586 return ret;
587 }
588
589 msg(D_ROUTE, "%s result: via %s dev %s", __func__,
590 inet_ntop(AF_INET6, best_gw, buf, sizeof(buf)), best_iface);
591
592 return ret;
593
594 }
595
596 #ifdef ENABLE_SITNL
597
598 int
net_ctx_init(struct context * c,openvpn_net_ctx_t * ctx)599 net_ctx_init(struct context *c, openvpn_net_ctx_t *ctx)
600 {
601 (void)c;
602 (void)ctx;
603
604 return 0;
605 }
606
607 void
net_ctx_reset(openvpn_net_ctx_t * ctx)608 net_ctx_reset(openvpn_net_ctx_t *ctx)
609 {
610 (void)ctx;
611 }
612
613 void
net_ctx_free(openvpn_net_ctx_t * ctx)614 net_ctx_free(openvpn_net_ctx_t *ctx)
615 {
616 (void)ctx;
617 }
618
619 int
net_route_v4_best_gw(openvpn_net_ctx_t * ctx,const in_addr_t * dst,in_addr_t * best_gw,char * best_iface)620 net_route_v4_best_gw(openvpn_net_ctx_t *ctx, const in_addr_t *dst,
621 in_addr_t *best_gw, char *best_iface)
622 {
623 inet_address_t dst_v4 = {0};
624 char buf[INET_ADDRSTRLEN];
625 int ret;
626
627 if (dst)
628 {
629 dst_v4.ipv4 = htonl(*dst);
630 }
631
632 msg(D_ROUTE, "%s query: dst %s", __func__,
633 inet_ntop(AF_INET, &dst_v4.ipv4, buf, sizeof(buf)));
634
635 ret = sitnl_route_best_gw(AF_INET, &dst_v4, best_gw, best_iface);
636 if (ret < 0)
637 {
638 return ret;
639 }
640
641 msg(D_ROUTE, "%s result: via %s dev %s", __func__,
642 inet_ntop(AF_INET, best_gw, buf, sizeof(buf)), best_iface);
643
644 /* result is expected in Host Order */
645 *best_gw = ntohl(*best_gw);
646
647 return ret;
648 }
649
650 int
net_iface_up(openvpn_net_ctx_t * ctx,const char * iface,bool up)651 net_iface_up(openvpn_net_ctx_t *ctx, const char *iface, bool up)
652 {
653 struct sitnl_link_req req;
654 int ifindex;
655
656 CLEAR(req);
657
658 if (!iface)
659 {
660 msg(M_WARN, "%s: passed NULL interface", __func__);
661 return -EINVAL;
662 }
663
664 ifindex = if_nametoindex(iface);
665 if (ifindex == 0)
666 {
667 msg(M_WARN, "%s: rtnl: cannot get ifindex for %s: %s", __func__, iface,
668 strerror(errno));
669 return -ENOENT;
670 }
671
672 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.i));
673 req.n.nlmsg_flags = NLM_F_REQUEST;
674 req.n.nlmsg_type = RTM_NEWLINK;
675
676 req.i.ifi_family = AF_PACKET;
677 req.i.ifi_index = ifindex;
678 req.i.ifi_change |= IFF_UP;
679 if (up)
680 {
681 req.i.ifi_flags |= IFF_UP;
682 }
683 else
684 {
685 req.i.ifi_flags &= ~IFF_UP;
686 }
687
688 msg(M_INFO, "%s: set %s %s", __func__, iface, up ? "up" : "down");
689
690 return sitnl_send(&req.n, 0, 0, NULL, NULL);
691 }
692
693 int
net_iface_mtu_set(openvpn_net_ctx_t * ctx,const char * iface,uint32_t mtu)694 net_iface_mtu_set(openvpn_net_ctx_t *ctx, const char *iface,
695 uint32_t mtu)
696 {
697 struct sitnl_link_req req;
698 int ifindex, ret = -1;
699
700 CLEAR(req);
701
702 ifindex = if_nametoindex(iface);
703 if (ifindex == 0)
704 {
705 msg(M_WARN | M_ERRNO, "%s: rtnl: cannot get ifindex for %s", __func__,
706 iface);
707 return -1;
708 }
709
710 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.i));
711 req.n.nlmsg_flags = NLM_F_REQUEST;
712 req.n.nlmsg_type = RTM_NEWLINK;
713
714 req.i.ifi_family = AF_PACKET;
715 req.i.ifi_index = ifindex;
716
717 SITNL_ADDATTR(&req.n, sizeof(req), IFLA_MTU, &mtu, 4);
718
719 msg(M_INFO, "%s: mtu %u for %s", __func__, mtu, iface);
720
721 ret = sitnl_send(&req.n, 0, 0, NULL, NULL);
722 err:
723 return ret;
724 }
725
726 static int
sitnl_addr_set(int cmd,uint32_t flags,int ifindex,sa_family_t af_family,const inet_address_t * local,const inet_address_t * remote,int prefixlen)727 sitnl_addr_set(int cmd, uint32_t flags, int ifindex, sa_family_t af_family,
728 const inet_address_t *local, const inet_address_t *remote,
729 int prefixlen)
730 {
731 struct sitnl_addr_req req;
732 uint32_t size;
733 int ret = -EINVAL;
734
735 CLEAR(req);
736
737 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.i));
738 req.n.nlmsg_type = cmd;
739 req.n.nlmsg_flags = NLM_F_REQUEST | flags;
740
741 req.i.ifa_index = ifindex;
742 req.i.ifa_family = af_family;
743
744 switch (af_family)
745 {
746 case AF_INET:
747 size = sizeof(struct in_addr);
748 break;
749
750 case AF_INET6:
751 size = sizeof(struct in6_addr);
752 break;
753
754 default:
755 msg(M_WARN, "%s: rtnl: unknown address family %d", __func__,
756 af_family);
757 return -EINVAL;
758 }
759
760 /* if no prefixlen has been specified, assume host address */
761 if (prefixlen == 0)
762 {
763 prefixlen = size * 8;
764 }
765 req.i.ifa_prefixlen = prefixlen;
766
767 if (remote)
768 {
769 SITNL_ADDATTR(&req.n, sizeof(req), IFA_ADDRESS, remote, size);
770 }
771
772 if (local)
773 {
774 SITNL_ADDATTR(&req.n, sizeof(req), IFA_LOCAL, local, size);
775 }
776
777 ret = sitnl_send(&req.n, 0, 0, NULL, NULL);
778 if (ret == -EEXIST)
779 {
780 ret = 0;
781 }
782 err:
783 return ret;
784 }
785
786 static int
sitnl_addr_ptp_add(sa_family_t af_family,const char * iface,const inet_address_t * local,const inet_address_t * remote)787 sitnl_addr_ptp_add(sa_family_t af_family, const char *iface,
788 const inet_address_t *local,
789 const inet_address_t *remote)
790 {
791 int ifindex;
792
793 switch (af_family)
794 {
795 case AF_INET:
796 case AF_INET6:
797 break;
798
799 default:
800 return -EINVAL;
801 }
802
803 if (!iface)
804 {
805 msg(M_WARN, "%s: passed NULL interface", __func__);
806 return -EINVAL;
807 }
808
809 ifindex = if_nametoindex(iface);
810 if (ifindex == 0)
811 {
812 msg(M_WARN, "%s: cannot get ifindex for %s: %s", __func__, np(iface),
813 strerror(errno));
814 return -ENOENT;
815 }
816
817 return sitnl_addr_set(RTM_NEWADDR, NLM_F_CREATE | NLM_F_REPLACE, ifindex,
818 af_family, local, remote, 0);
819 }
820
821 static int
sitnl_addr_ptp_del(sa_family_t af_family,const char * iface,const inet_address_t * local)822 sitnl_addr_ptp_del(sa_family_t af_family, const char *iface,
823 const inet_address_t *local)
824 {
825 int ifindex;
826
827 switch (af_family)
828 {
829 case AF_INET:
830 case AF_INET6:
831 break;
832
833 default:
834 return -EINVAL;
835 }
836
837 if (!iface)
838 {
839 msg(M_WARN, "%s: passed NULL interface", __func__);
840 return -EINVAL;
841 }
842
843 ifindex = if_nametoindex(iface);
844 if (ifindex == 0)
845 {
846 msg(M_WARN | M_ERRNO, "%s: cannot get ifindex for %s", __func__, iface);
847 return -ENOENT;
848 }
849
850 return sitnl_addr_set(RTM_DELADDR, 0, ifindex, af_family, local, NULL, 0);
851 }
852
853 static int
sitnl_route_set(int cmd,uint32_t flags,int ifindex,sa_family_t af_family,const void * dst,int prefixlen,const void * gw,enum rt_class_t table,int metric,enum rt_scope_t scope,int protocol,int type)854 sitnl_route_set(int cmd, uint32_t flags, int ifindex, sa_family_t af_family,
855 const void *dst, int prefixlen,
856 const void *gw, enum rt_class_t table, int metric,
857 enum rt_scope_t scope, int protocol, int type)
858 {
859 struct sitnl_route_req req;
860 int ret = -1, size;
861
862 CLEAR(req);
863
864 switch (af_family)
865 {
866 case AF_INET:
867 size = sizeof(in_addr_t);
868 break;
869
870 case AF_INET6:
871 size = sizeof(struct in6_addr);
872 break;
873
874 default:
875 return -EINVAL;
876 }
877
878 req.n.nlmsg_len = NLMSG_LENGTH(sizeof(req.r));
879 req.n.nlmsg_type = cmd;
880 req.n.nlmsg_flags = NLM_F_REQUEST | flags;
881
882 req.r.rtm_family = af_family;
883 req.r.rtm_scope = scope;
884 req.r.rtm_protocol = protocol;
885 req.r.rtm_type = type;
886 req.r.rtm_dst_len = prefixlen;
887
888 if (table < 256)
889 {
890 req.r.rtm_table = table;
891 }
892 else
893 {
894 req.r.rtm_table = RT_TABLE_UNSPEC;
895 SITNL_ADDATTR(&req.n, sizeof(req), RTA_TABLE, &table, 4);
896 }
897
898 if (dst)
899 {
900 SITNL_ADDATTR(&req.n, sizeof(req), RTA_DST, dst, size);
901 }
902
903 if (gw)
904 {
905 SITNL_ADDATTR(&req.n, sizeof(req), RTA_GATEWAY, gw, size);
906 }
907
908 if (ifindex > 0)
909 {
910 SITNL_ADDATTR(&req.n, sizeof(req), RTA_OIF, &ifindex, 4);
911 }
912
913 if (metric > 0)
914 {
915 SITNL_ADDATTR(&req.n, sizeof(req), RTA_PRIORITY, &metric, 4);
916 }
917
918 ret = sitnl_send(&req.n, 0, 0, NULL, NULL);
919 if (ret == -EEXIST)
920 {
921 ret = 0;
922 }
923 err:
924 return ret;
925 }
926
927 static int
sitnl_addr_add(sa_family_t af_family,const char * iface,const inet_address_t * addr,int prefixlen)928 sitnl_addr_add(sa_family_t af_family, const char *iface,
929 const inet_address_t *addr, int prefixlen)
930 {
931 int ifindex;
932
933 switch (af_family)
934 {
935 case AF_INET:
936 case AF_INET6:
937 break;
938
939 default:
940 return -EINVAL;
941 }
942
943 if (!iface)
944 {
945 msg(M_WARN, "%s: passed NULL interface", __func__);
946 return -EINVAL;
947 }
948
949 ifindex = if_nametoindex(iface);
950 if (ifindex == 0)
951 {
952 msg(M_WARN | M_ERRNO, "%s: rtnl: cannot get ifindex for %s", __func__,
953 iface);
954 return -ENOENT;
955 }
956
957 return sitnl_addr_set(RTM_NEWADDR, NLM_F_CREATE | NLM_F_REPLACE, ifindex,
958 af_family, addr, NULL, prefixlen);
959 }
960
961 static int
sitnl_addr_del(sa_family_t af_family,const char * iface,inet_address_t * addr,int prefixlen)962 sitnl_addr_del(sa_family_t af_family, const char *iface, inet_address_t *addr,
963 int prefixlen)
964 {
965 int ifindex;
966
967 switch (af_family)
968 {
969 case AF_INET:
970 case AF_INET6:
971 break;
972
973 default:
974 return -EINVAL;
975 }
976
977 if (!iface)
978 {
979 msg(M_WARN, "%s: passed NULL interface", __func__);
980 return -EINVAL;
981 }
982
983 ifindex = if_nametoindex(iface);
984 if (ifindex == 0)
985 {
986 msg(M_WARN | M_ERRNO, "%s: rtnl: cannot get ifindex for %s", __func__,
987 iface);
988 return -ENOENT;
989 }
990
991 return sitnl_addr_set(RTM_DELADDR, 0, ifindex, af_family, addr, NULL,
992 prefixlen);
993 }
994
995 int
net_addr_v4_add(openvpn_net_ctx_t * ctx,const char * iface,const in_addr_t * addr,int prefixlen)996 net_addr_v4_add(openvpn_net_ctx_t *ctx, const char *iface,
997 const in_addr_t *addr, int prefixlen)
998 {
999 inet_address_t addr_v4 = { 0 };
1000 char buf[INET_ADDRSTRLEN];
1001
1002 if (!addr)
1003 {
1004 return -EINVAL;
1005 }
1006
1007 addr_v4.ipv4 = htonl(*addr);
1008
1009 msg(M_INFO, "%s: %s/%d dev %s", __func__,
1010 inet_ntop(AF_INET, &addr_v4.ipv4, buf, sizeof(buf)), prefixlen,iface);
1011
1012 return sitnl_addr_add(AF_INET, iface, &addr_v4, prefixlen);
1013 }
1014
1015 int
net_addr_v6_add(openvpn_net_ctx_t * ctx,const char * iface,const struct in6_addr * addr,int prefixlen)1016 net_addr_v6_add(openvpn_net_ctx_t *ctx, const char *iface,
1017 const struct in6_addr *addr, int prefixlen)
1018 {
1019 inet_address_t addr_v6 = { 0 };
1020 char buf[INET6_ADDRSTRLEN];
1021
1022 if (!addr)
1023 {
1024 return -EINVAL;
1025 }
1026
1027 addr_v6.ipv6 = *addr;
1028
1029 msg(M_INFO, "%s: %s/%d dev %s", __func__,
1030 inet_ntop(AF_INET6, &addr_v6.ipv6, buf, sizeof(buf)), prefixlen, iface);
1031
1032 return sitnl_addr_add(AF_INET6, iface, &addr_v6, prefixlen);
1033 }
1034
1035 int
net_addr_v4_del(openvpn_net_ctx_t * ctx,const char * iface,const in_addr_t * addr,int prefixlen)1036 net_addr_v4_del(openvpn_net_ctx_t *ctx, const char *iface,
1037 const in_addr_t *addr, int prefixlen)
1038 {
1039 inet_address_t addr_v4 = { 0 };
1040 char buf[INET_ADDRSTRLEN];
1041
1042 if (!addr)
1043 {
1044 return -EINVAL;
1045 }
1046
1047 addr_v4.ipv4 = htonl(*addr);
1048
1049 msg(M_INFO, "%s: %s dev %s", __func__,
1050 inet_ntop(AF_INET, &addr_v4.ipv4, buf, sizeof(buf)), iface);
1051
1052 return sitnl_addr_del(AF_INET, iface, &addr_v4, prefixlen);
1053 }
1054
1055 int
net_addr_v6_del(openvpn_net_ctx_t * ctx,const char * iface,const struct in6_addr * addr,int prefixlen)1056 net_addr_v6_del(openvpn_net_ctx_t *ctx, const char *iface,
1057 const struct in6_addr *addr, int prefixlen)
1058 {
1059 inet_address_t addr_v6 = { 0 };
1060 char buf[INET6_ADDRSTRLEN];
1061
1062 if (!addr)
1063 {
1064 return -EINVAL;
1065 }
1066
1067 addr_v6.ipv6 = *addr;
1068
1069 msg(M_INFO, "%s: %s/%d dev %s", __func__,
1070 inet_ntop(AF_INET6, &addr_v6.ipv6, buf, sizeof(buf)), prefixlen, iface);
1071
1072 return sitnl_addr_del(AF_INET6, iface, &addr_v6, prefixlen);
1073 }
1074
1075 int
net_addr_ptp_v4_add(openvpn_net_ctx_t * ctx,const char * iface,const in_addr_t * local,const in_addr_t * remote)1076 net_addr_ptp_v4_add(openvpn_net_ctx_t *ctx, const char *iface,
1077 const in_addr_t *local, const in_addr_t *remote)
1078 {
1079 inet_address_t local_v4 = { 0 };
1080 inet_address_t remote_v4 = { 0 };
1081 char buf1[INET_ADDRSTRLEN];
1082 char buf2[INET_ADDRSTRLEN];
1083
1084 if (!local)
1085 {
1086 return -EINVAL;
1087 }
1088
1089 local_v4.ipv4 = htonl(*local);
1090
1091 if (remote)
1092 {
1093 remote_v4.ipv4 = htonl(*remote);
1094 }
1095
1096 msg(M_INFO, "%s: %s peer %s dev %s", __func__,
1097 inet_ntop(AF_INET, &local_v4.ipv4, buf1, sizeof(buf1)),
1098 inet_ntop(AF_INET, &remote_v4.ipv4, buf2, sizeof(buf2)), iface);
1099
1100 return sitnl_addr_ptp_add(AF_INET, iface, &local_v4, &remote_v4);
1101 }
1102
1103 int
net_addr_ptp_v4_del(openvpn_net_ctx_t * ctx,const char * iface,const in_addr_t * local,const in_addr_t * remote)1104 net_addr_ptp_v4_del(openvpn_net_ctx_t *ctx, const char *iface,
1105 const in_addr_t *local, const in_addr_t *remote)
1106 {
1107 inet_address_t local_v4 = { 0 };
1108 char buf[INET6_ADDRSTRLEN];
1109
1110
1111 if (!local)
1112 {
1113 return -EINVAL;
1114 }
1115
1116 local_v4.ipv4 = htonl(*local);
1117
1118 msg(M_INFO, "%s: %s dev %s", __func__,
1119 inet_ntop(AF_INET, &local_v4.ipv4, buf, sizeof(buf)), iface);
1120
1121 return sitnl_addr_ptp_del(AF_INET, iface, &local_v4);
1122 }
1123
1124 static int
sitnl_route_add(const char * iface,sa_family_t af_family,const void * dst,int prefixlen,const void * gw,uint32_t table,int metric)1125 sitnl_route_add(const char *iface, sa_family_t af_family, const void *dst,
1126 int prefixlen, const void *gw, uint32_t table, int metric)
1127 {
1128 enum rt_scope_t scope = RT_SCOPE_UNIVERSE;
1129 int ifindex = 0;
1130
1131 if (iface)
1132 {
1133 ifindex = if_nametoindex(iface);
1134 if (ifindex == 0)
1135 {
1136 msg(M_WARN | M_ERRNO, "%s: rtnl: can't get ifindex for %s",
1137 __func__, iface);
1138 return -ENOENT;
1139 }
1140 }
1141
1142 if (table == 0)
1143 {
1144 table = RT_TABLE_MAIN;
1145 }
1146
1147 if (!gw && iface)
1148 {
1149 scope = RT_SCOPE_LINK;
1150 }
1151
1152 return sitnl_route_set(RTM_NEWROUTE, NLM_F_CREATE | NLM_F_REPLACE, ifindex,
1153 af_family, dst, prefixlen, gw, table, metric, scope,
1154 RTPROT_BOOT, RTN_UNICAST);
1155 }
1156
1157 int
net_route_v4_add(openvpn_net_ctx_t * ctx,const in_addr_t * dst,int prefixlen,const in_addr_t * gw,const char * iface,uint32_t table,int metric)1158 net_route_v4_add(openvpn_net_ctx_t *ctx, const in_addr_t *dst, int prefixlen,
1159 const in_addr_t *gw, const char *iface,
1160 uint32_t table, int metric)
1161 {
1162 in_addr_t *dst_ptr = NULL, *gw_ptr = NULL;
1163 in_addr_t dst_be = 0, gw_be = 0;
1164 char dst_str[INET_ADDRSTRLEN];
1165 char gw_str[INET_ADDRSTRLEN];
1166
1167 if (dst)
1168 {
1169 dst_be = htonl(*dst);
1170 dst_ptr = &dst_be;
1171 }
1172
1173 if (gw)
1174 {
1175 gw_be = htonl(*gw);
1176 gw_ptr = &gw_be;
1177 }
1178
1179 msg(D_ROUTE, "%s: %s/%d via %s dev %s table %d metric %d", __func__,
1180 inet_ntop(AF_INET, &dst_be, dst_str, sizeof(dst_str)),
1181 prefixlen, inet_ntop(AF_INET, &gw_be, gw_str, sizeof(gw_str)),
1182 np(iface), table, metric);
1183
1184 return sitnl_route_add(iface, AF_INET, dst_ptr, prefixlen, gw_ptr, table,
1185 metric);
1186 }
1187
1188 int
net_route_v6_add(openvpn_net_ctx_t * ctx,const struct in6_addr * dst,int prefixlen,const struct in6_addr * gw,const char * iface,uint32_t table,int metric)1189 net_route_v6_add(openvpn_net_ctx_t *ctx, const struct in6_addr *dst,
1190 int prefixlen, const struct in6_addr *gw,
1191 const char *iface, uint32_t table, int metric)
1192 {
1193 inet_address_t dst_v6 = { 0 };
1194 inet_address_t gw_v6 = { 0 };
1195 char dst_str[INET6_ADDRSTRLEN];
1196 char gw_str[INET6_ADDRSTRLEN];
1197
1198 if (dst)
1199 {
1200 dst_v6.ipv6 = *dst;
1201 }
1202
1203 if (gw)
1204 {
1205 gw_v6.ipv6 = *gw;
1206 }
1207
1208 msg(D_ROUTE, "%s: %s/%d via %s dev %s table %d metric %d", __func__,
1209 inet_ntop(AF_INET6, &dst_v6.ipv6, dst_str, sizeof(dst_str)),
1210 prefixlen, inet_ntop(AF_INET6, &gw_v6.ipv6, gw_str, sizeof(gw_str)),
1211 np(iface), table, metric);
1212
1213 return sitnl_route_add(iface, AF_INET6, dst, prefixlen, gw, table,
1214 metric);
1215 }
1216
1217 static int
sitnl_route_del(const char * iface,sa_family_t af_family,inet_address_t * dst,int prefixlen,inet_address_t * gw,uint32_t table,int metric)1218 sitnl_route_del(const char *iface, sa_family_t af_family, inet_address_t *dst,
1219 int prefixlen, inet_address_t *gw, uint32_t table,
1220 int metric)
1221 {
1222 int ifindex = 0;
1223
1224 if (iface)
1225 {
1226 ifindex = if_nametoindex(iface);
1227 if (ifindex == 0)
1228 {
1229 msg(M_WARN | M_ERRNO, "%s: rtnl: can't get ifindex for %s",
1230 __func__, iface);
1231 return -ENOENT;
1232 }
1233 }
1234
1235 if (table == 0)
1236 {
1237 table = RT_TABLE_MAIN;
1238 }
1239
1240 return sitnl_route_set(RTM_DELROUTE, 0, ifindex, af_family, dst, prefixlen,
1241 gw, table, metric, RT_SCOPE_NOWHERE, 0, 0);
1242 }
1243
1244 int
net_route_v4_del(openvpn_net_ctx_t * ctx,const in_addr_t * dst,int prefixlen,const in_addr_t * gw,const char * iface,uint32_t table,int metric)1245 net_route_v4_del(openvpn_net_ctx_t *ctx, const in_addr_t *dst, int prefixlen,
1246 const in_addr_t *gw, const char *iface, uint32_t table,
1247 int metric)
1248 {
1249 inet_address_t dst_v4 = { 0 };
1250 inet_address_t gw_v4 = { 0 };
1251 char dst_str[INET_ADDRSTRLEN];
1252 char gw_str[INET_ADDRSTRLEN];
1253
1254 if (dst)
1255 {
1256 dst_v4.ipv4 = htonl(*dst);
1257 }
1258
1259 if (gw)
1260 {
1261 gw_v4.ipv4 = htonl(*gw);
1262 }
1263
1264 msg(D_ROUTE, "%s: %s/%d via %s dev %s table %d metric %d", __func__,
1265 inet_ntop(AF_INET, &dst_v4.ipv4, dst_str, sizeof(dst_str)),
1266 prefixlen, inet_ntop(AF_INET, &gw_v4.ipv4, gw_str, sizeof(gw_str)),
1267 np(iface), table, metric);
1268
1269 return sitnl_route_del(iface, AF_INET, &dst_v4, prefixlen, &gw_v4, table,
1270 metric);
1271 }
1272
1273 int
net_route_v6_del(openvpn_net_ctx_t * ctx,const struct in6_addr * dst,int prefixlen,const struct in6_addr * gw,const char * iface,uint32_t table,int metric)1274 net_route_v6_del(openvpn_net_ctx_t *ctx, const struct in6_addr *dst,
1275 int prefixlen, const struct in6_addr *gw,
1276 const char *iface, uint32_t table, int metric)
1277 {
1278 inet_address_t dst_v6 = { 0 };
1279 inet_address_t gw_v6 = { 0 };
1280 char dst_str[INET6_ADDRSTRLEN];
1281 char gw_str[INET6_ADDRSTRLEN];
1282
1283 if (dst)
1284 {
1285 dst_v6.ipv6 = *dst;
1286 }
1287
1288 if (gw)
1289 {
1290 gw_v6.ipv6 = *gw;
1291 }
1292
1293 msg(D_ROUTE, "%s: %s/%d via %s dev %s table %d metric %d", __func__,
1294 inet_ntop(AF_INET6, &dst_v6.ipv6, dst_str, sizeof(dst_str)),
1295 prefixlen, inet_ntop(AF_INET6, &gw_v6.ipv6, gw_str, sizeof(gw_str)),
1296 np(iface), table, metric);
1297
1298 return sitnl_route_del(iface, AF_INET6, &dst_v6, prefixlen, &gw_v6,
1299 table, metric);
1300 }
1301
1302 #endif /* !ENABLE_SITNL */
1303
1304 #endif /* TARGET_LINUX */
1305