Annotation of embedaddon/strongswan/src/libcharon/plugins/kernel_netlink/kernel_netlink_net.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2008-2019 Tobias Brunner
3: * Copyright (C) 2005-2008 Martin Willi
4: * HSR Hochschule fuer Technik Rapperswil
5: *
6: * This program is free software; you can redistribute it and/or modify it
7: * under the terms of the GNU General Public License as published by the
8: * Free Software Foundation; either version 2 of the License, or (at your
9: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10: *
11: * This program is distributed in the hope that it will be useful, but
12: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14: * for more details.
15: */
16:
17: /*
18: * Copyright (C) 2010 secunet Security Networks AG
19: * Copyright (C) 2010 Thomas Egerer
20: *
21: * Permission is hereby granted, free of charge, to any person obtaining a copy
22: * of this software and associated documentation files (the "Software"), to deal
23: * in the Software without restriction, including without limitation the rights
24: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25: * copies of the Software, and to permit persons to whom the Software is
26: * furnished to do so, subject to the following conditions:
27: *
28: * The above copyright notice and this permission notice shall be included in
29: * all copies or substantial portions of the Software.
30: *
31: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
37: * THE SOFTWARE.
38: */
39:
40: #include <sys/socket.h>
41: #include <sys/utsname.h>
42: #include <linux/netlink.h>
43: #include <linux/rtnetlink.h>
44: #include <linux/if_addrlabel.h>
45: #include <unistd.h>
46: #include <errno.h>
47: #include <net/if.h>
48: #ifdef HAVE_LINUX_FIB_RULES_H
49: #include <linux/fib_rules.h>
50: #endif
51:
52: #include "kernel_netlink_net.h"
53: #include "kernel_netlink_shared.h"
54:
55: #include <daemon.h>
56: #include <utils/debug.h>
57: #include <threading/mutex.h>
58: #include <threading/rwlock.h>
59: #include <threading/rwlock_condvar.h>
60: #include <threading/spinlock.h>
61: #include <collections/hashtable.h>
62: #include <collections/linked_list.h>
63: #include <processing/jobs/callback_job.h>
64:
65: /** delay before firing roam events (ms) */
66: #define ROAM_DELAY 100
67:
68: /** delay before reinstalling routes (ms) */
69: #define ROUTE_DELAY 100
70:
71: /** maximum recursion when searching for addresses in get_route() */
72: #define MAX_ROUTE_RECURSION 2
73:
74: #ifndef ROUTING_TABLE
75: #define ROUTING_TABLE 0
76: #endif
77:
78: #ifndef ROUTING_TABLE_PRIO
79: #define ROUTING_TABLE_PRIO 0
80: #endif
81:
82: /** multicast groups (for groups > 31 setsockopt has to be used) */
83: #define nl_group(group) (1 << (group - 1))
84:
85: ENUM(rt_msg_names, RTM_NEWLINK, RTM_GETRULE,
86: "RTM_NEWLINK",
87: "RTM_DELLINK",
88: "RTM_GETLINK",
89: "RTM_SETLINK",
90: "RTM_NEWADDR",
91: "RTM_DELADDR",
92: "RTM_GETADDR",
93: "23",
94: "RTM_NEWROUTE",
95: "RTM_DELROUTE",
96: "RTM_GETROUTE",
97: "27",
98: "RTM_NEWNEIGH",
99: "RTM_DELNEIGH",
100: "RTM_GETNEIGH",
101: "31",
102: "RTM_NEWRULE",
103: "RTM_DELRULE",
104: "RTM_GETRULE",
105: );
106:
107: typedef struct addr_entry_t addr_entry_t;
108:
109: /**
110: * IP address in an iface_entry_t
111: */
112: struct addr_entry_t {
113:
114: /** the ip address */
115: host_t *ip;
116:
117: /** address flags */
118: u_char flags;
119:
120: /** scope of the address */
121: u_char scope;
122:
123: /** number of times this IP is used, if virtual (i.e. managed by us) */
124: u_int refcount;
125:
126: /** TRUE once it is installed, if virtual */
127: bool installed;
128: };
129:
130: /**
131: * destroy a addr_entry_t object
132: */
133: static void addr_entry_destroy(addr_entry_t *this)
134: {
135: this->ip->destroy(this->ip);
136: free(this);
137: }
138:
139: typedef struct iface_entry_t iface_entry_t;
140:
141: /**
142: * A network interface on this system, containing addr_entry_t's
143: */
144: struct iface_entry_t {
145:
146: /** interface index */
147: int ifindex;
148:
149: /** name of the interface */
150: char ifname[IFNAMSIZ];
151:
152: /** interface flags, as in netdevice(7) SIOCGIFFLAGS */
153: u_int flags;
154:
155: /** list of addresses as host_t */
156: linked_list_t *addrs;
157:
158: /** TRUE if usable by config */
159: bool usable;
160: };
161:
162: /**
163: * destroy an interface entry
164: */
165: static void iface_entry_destroy(iface_entry_t *this)
166: {
167: this->addrs->destroy_function(this->addrs, (void*)addr_entry_destroy);
168: free(this);
169: }
170:
171: CALLBACK(iface_entry_by_index, bool,
172: iface_entry_t *this, va_list args)
173: {
174: int ifindex;
175:
176: VA_ARGS_VGET(args, ifindex);
177: return this->ifindex == ifindex;
178: }
179:
180: CALLBACK(iface_entry_by_name, bool,
181: iface_entry_t *this, va_list args)
182: {
183: char *ifname;
184:
185: VA_ARGS_VGET(args, ifname);
186: return streq(this->ifname, ifname);
187: }
188:
189: /**
190: * check if an interface is up
191: */
192: static inline bool iface_entry_up(iface_entry_t *iface)
193: {
194: return (iface->flags & IFF_UP) == IFF_UP;
195: }
196:
197: /**
198: * check if an interface is up and usable
199: */
200: static inline bool iface_entry_up_and_usable(iface_entry_t *iface)
201: {
202: return iface->usable && iface_entry_up(iface);
203: }
204:
205: typedef struct addr_map_entry_t addr_map_entry_t;
206:
207: /**
208: * Entry that maps an IP address to an interface entry
209: */
210: struct addr_map_entry_t {
211: /** The IP address */
212: host_t *ip;
213:
214: /** The address entry for this IP address */
215: addr_entry_t *addr;
216:
217: /** The interface this address is installed on */
218: iface_entry_t *iface;
219: };
220:
221: /**
222: * Hash a addr_map_entry_t object, all entries with the same IP address
223: * are stored in the same bucket
224: */
225: static u_int addr_map_entry_hash(addr_map_entry_t *this)
226: {
227: return chunk_hash(this->ip->get_address(this->ip));
228: }
229:
230: /**
231: * Compare two addr_map_entry_t objects, two entries are equal if they are
232: * installed on the same interface
233: */
234: static bool addr_map_entry_equals(addr_map_entry_t *a, addr_map_entry_t *b)
235: {
236: return a->iface->ifindex == b->iface->ifindex &&
237: a->ip->ip_equals(a->ip, b->ip);
238: }
239:
240: /**
241: * Used with get_match this finds an address entry if it is installed on
242: * an up and usable interface
243: */
244: static bool addr_map_entry_match_up_and_usable(addr_map_entry_t *a,
245: addr_map_entry_t *b)
246: {
247: return iface_entry_up_and_usable(b->iface) &&
248: a->ip->ip_equals(a->ip, b->ip);
249: }
250:
251: /**
252: * Used with get_match this finds an address entry if it is installed on
253: * any active local interface
254: */
255: static bool addr_map_entry_match_up(addr_map_entry_t *a, addr_map_entry_t *b)
256: {
257: return iface_entry_up(b->iface) && a->ip->ip_equals(a->ip, b->ip);
258: }
259:
260: /**
261: * Used with get_match this finds an address entry if it is installed on
262: * any local interface
263: */
264: static bool addr_map_entry_match(addr_map_entry_t *a, addr_map_entry_t *b)
265: {
266: return a->ip->ip_equals(a->ip, b->ip);
267: }
268:
269: typedef struct net_change_t net_change_t;
270:
271: /**
272: * Queued network changes
273: */
274: struct net_change_t {
275: /** Name of the interface that got activated (or an IP appeared on) */
276: char *if_name;
277: };
278:
279: /**
280: * Destroy a net_change_t object
281: */
282: static void net_change_destroy(net_change_t *this)
283: {
284: free(this->if_name);
285: free(this);
286: }
287:
288: /**
289: * Hash a net_change_t object
290: */
291: static u_int net_change_hash(net_change_t *this)
292: {
293: return chunk_hash(chunk_create(this->if_name, strlen(this->if_name)));
294: }
295:
296: /**
297: * Compare two net_change_t objects
298: */
299: static bool net_change_equals(net_change_t *a, net_change_t *b)
300: {
301: return streq(a->if_name, b->if_name);
302: }
303:
304: typedef struct private_kernel_netlink_net_t private_kernel_netlink_net_t;
305:
306: /**
307: * Private variables and functions of kernel_netlink_net class.
308: */
309: struct private_kernel_netlink_net_t {
310: /**
311: * Public part of the kernel_netlink_net_t object.
312: */
313: kernel_netlink_net_t public;
314:
315: /**
316: * lock to access various lists and maps
317: */
318: rwlock_t *lock;
319:
320: /**
321: * condition variable to signal virtual IP add/removal
322: */
323: rwlock_condvar_t *condvar;
324:
325: /**
326: * Cached list of interfaces and its addresses (iface_entry_t)
327: */
328: linked_list_t *ifaces;
329:
330: /**
331: * Map for IP addresses to iface_entry_t objects (addr_map_entry_t)
332: */
333: hashtable_t *addrs;
334:
335: /**
336: * Map for virtual IP addresses to iface_entry_t objects (addr_map_entry_t)
337: */
338: hashtable_t *vips;
339:
340: /**
341: * netlink rt socket (routing)
342: */
343: netlink_socket_t *socket;
344:
345: /**
346: * Netlink rt socket to receive address change events
347: */
348: int socket_events;
349:
350: /**
351: * earliest time of the next roam event
352: */
353: timeval_t next_roam;
354:
355: /**
356: * roam event due to address change
357: */
358: bool roam_address;
359:
360: /**
361: * lock to check and update roam event time
362: */
363: spinlock_t *roam_lock;
364:
365: /**
366: * routing table to install routes
367: */
368: uint32_t routing_table;
369:
370: /**
371: * priority of used routing table
372: */
373: uint32_t routing_table_prio;
374:
375: /**
376: * installed routes
377: */
378: hashtable_t *routes;
379:
380: /**
381: * mutex for routes
382: */
383: mutex_t *routes_lock;
384:
385: /**
386: * interface changes which may trigger route reinstallation
387: */
388: hashtable_t *net_changes;
389:
390: /**
391: * mutex for route reinstallation triggers
392: */
393: mutex_t *net_changes_lock;
394:
395: /**
396: * time of last route reinstallation
397: */
398: timeval_t last_route_reinstall;
399:
400: /**
401: * whether to react to RTM_NEWROUTE or RTM_DELROUTE events
402: */
403: bool process_route;
404:
405: /**
406: * whether to react to RTM_NEWRULE or RTM_DELRULE events
407: */
408: bool process_rules;
409:
410: /**
411: * whether to trigger roam events
412: */
413: bool roam_events;
414:
415: /**
416: * whether to install IPsec policy routes
417: */
418: bool install_routes;
419:
420: /**
421: * whether to actually install virtual IPs
422: */
423: bool install_virtual_ip;
424:
425: /**
426: * the name of the interface virtual IP addresses are installed on
427: */
428: char *install_virtual_ip_on;
429:
430: /**
431: * whether preferred source addresses can be specified for IPv6 routes
432: */
433: bool rta_prefsrc_for_ipv6;
434:
435: /**
436: * whether marks can be used in route lookups
437: */
438: bool rta_mark;
439:
440: /**
441: * the mark excluded from the routing rule used for virtual IPs
442: */
443: mark_t routing_mark;
444:
445: /**
446: * whether to prefer temporary IPv6 addresses over public ones
447: */
448: bool prefer_temporary_addrs;
449:
450: /**
451: * list with routing tables to be excluded from route lookup
452: */
453: linked_list_t *rt_exclude;
454:
455: /**
456: * MTU to set on installed routes
457: */
458: uint32_t mtu;
459:
460: /**
461: * MSS to set on installed routes
462: */
463: uint32_t mss;
464: };
465:
466: /**
467: * Forward declaration
468: */
469: static status_t manage_srcroute(private_kernel_netlink_net_t *this,
470: int nlmsg_type, int flags, chunk_t dst_net,
471: uint8_t prefixlen, host_t *gateway,
472: host_t *src_ip, char *if_name, bool pass);
473:
474: /**
475: * Clear the queued network changes.
476: */
477: static void net_changes_clear(private_kernel_netlink_net_t *this)
478: {
479: enumerator_t *enumerator;
480: net_change_t *change;
481:
482: enumerator = this->net_changes->create_enumerator(this->net_changes);
483: while (enumerator->enumerate(enumerator, NULL, (void**)&change))
484: {
485: this->net_changes->remove_at(this->net_changes, enumerator);
486: net_change_destroy(change);
487: }
488: enumerator->destroy(enumerator);
489: }
490:
491: /**
492: * Act upon queued network changes.
493: */
494: static job_requeue_t reinstall_routes(private_kernel_netlink_net_t *this)
495: {
496: enumerator_t *enumerator;
497: route_entry_t *route;
498:
499: this->net_changes_lock->lock(this->net_changes_lock);
500: this->routes_lock->lock(this->routes_lock);
501:
502: enumerator = this->routes->create_enumerator(this->routes);
503: while (enumerator->enumerate(enumerator, NULL, (void**)&route))
504: {
505: net_change_t *change, lookup = {
506: .if_name = route->if_name,
507: };
508: if (route->pass || !route->if_name)
509: { /* no need to reinstall these, they don't reference interfaces */
510: continue;
511: }
512: /* check if a change for the outgoing interface is queued */
513: change = this->net_changes->get(this->net_changes, &lookup);
514: if (!change)
515: { /* in case src_ip is not on the outgoing interface */
516: if (this->public.interface.get_interface(&this->public.interface,
517: route->src_ip, &lookup.if_name))
518: {
519: if (!streq(lookup.if_name, route->if_name))
520: {
521: change = this->net_changes->get(this->net_changes, &lookup);
522: }
523: free(lookup.if_name);
524: }
525: }
526: if (change)
527: {
528: manage_srcroute(this, RTM_NEWROUTE, NLM_F_CREATE | NLM_F_EXCL,
529: route->dst_net, route->prefixlen, route->gateway,
530: route->src_ip, route->if_name, route->pass);
531: }
532: }
533: enumerator->destroy(enumerator);
534: this->routes_lock->unlock(this->routes_lock);
535:
536: net_changes_clear(this);
537: this->net_changes_lock->unlock(this->net_changes_lock);
538: return JOB_REQUEUE_NONE;
539: }
540:
541: /**
542: * Queue route reinstallation caused by network changes for a given interface.
543: *
544: * The route reinstallation is delayed for a while and only done once for
545: * several calls during this delay, in order to avoid doing it too often.
546: * The interface name is freed.
547: */
548: static void queue_route_reinstall(private_kernel_netlink_net_t *this,
549: char *if_name)
550: {
551: net_change_t *update, *found;
552: timeval_t now;
553: job_t *job;
554:
555: INIT(update,
556: .if_name = if_name
557: );
558:
559: this->net_changes_lock->lock(this->net_changes_lock);
560: found = this->net_changes->put(this->net_changes, update, update);
561: if (found)
562: {
563: net_change_destroy(found);
564: }
565: time_monotonic(&now);
566: if (timercmp(&now, &this->last_route_reinstall, >))
567: {
568: timeval_add_ms(&now, ROUTE_DELAY);
569: this->last_route_reinstall = now;
570:
571: job = (job_t*)callback_job_create((callback_job_cb_t)reinstall_routes,
572: this, NULL, NULL);
573: lib->scheduler->schedule_job_ms(lib->scheduler, job, ROUTE_DELAY);
574: }
575: this->net_changes_lock->unlock(this->net_changes_lock);
576: }
577:
578: /**
579: * check if the given IP is known as virtual IP and currently installed
580: *
581: * this function will also return TRUE if the virtual IP entry disappeared.
582: * in that case the returned entry will be NULL.
583: *
584: * this->lock must be held when calling this function
585: */
586: static bool is_vip_installed_or_gone(private_kernel_netlink_net_t *this,
587: host_t *ip, addr_map_entry_t **entry)
588: {
589: addr_map_entry_t lookup = {
590: .ip = ip,
591: };
592:
593: *entry = this->vips->get_match(this->vips, &lookup,
594: (void*)addr_map_entry_match);
595: if (*entry == NULL)
596: { /* the virtual IP disappeared */
597: return TRUE;
598: }
599: return (*entry)->addr->installed;
600: }
601:
602: /**
603: * check if the given IP is known as virtual IP
604: *
605: * this->lock must be held when calling this function
606: */
607: static bool is_known_vip(private_kernel_netlink_net_t *this, host_t *ip)
608: {
609: addr_map_entry_t lookup = {
610: .ip = ip,
611: };
612:
613: return this->vips->get_match(this->vips, &lookup,
614: (void*)addr_map_entry_match) != NULL;
615: }
616:
617: /**
618: * Add an address map entry
619: */
620: static void addr_map_entry_add(hashtable_t *map, addr_entry_t *addr,
621: iface_entry_t *iface)
622: {
623: addr_map_entry_t *entry;
624:
625: INIT(entry,
626: .ip = addr->ip,
627: .addr = addr,
628: .iface = iface,
629: );
630: entry = map->put(map, entry, entry);
631: free(entry);
632: }
633:
634: /**
635: * Remove an address map entry
636: */
637: static void addr_map_entry_remove(hashtable_t *map, addr_entry_t *addr,
638: iface_entry_t *iface)
639: {
640: addr_map_entry_t *entry, lookup = {
641: .ip = addr->ip,
642: .addr = addr,
643: .iface = iface,
644: };
645:
646: entry = map->remove(map, &lookup);
647: free(entry);
648: }
649:
650: /**
651: * Check if an address or net (addr with prefix net bits) is in
652: * subnet (net with net_len net bits)
653: */
654: static bool addr_in_subnet(chunk_t addr, int prefix, chunk_t net, int net_len)
655: {
656: static const u_char mask[] = { 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe };
657: int byte = 0;
658:
659: if (net_len == 0)
660: { /* any address matches a /0 network */
661: return TRUE;
662: }
663: if (addr.len != net.len || net_len > 8 * net.len || prefix < net_len)
664: {
665: return FALSE;
666: }
667: /* scan through all bytes in network order */
668: while (net_len > 0)
669: {
670: if (net_len < 8)
671: {
672: return (mask[net_len] & addr.ptr[byte]) == (mask[net_len] & net.ptr[byte]);
673: }
674: else
675: {
676: if (addr.ptr[byte] != net.ptr[byte])
677: {
678: return FALSE;
679: }
680: byte++;
681: net_len -= 8;
682: }
683: }
684: return TRUE;
685: }
686:
687: /**
688: * Check if the given address is in subnet (net with net_len net bits)
689: */
690: static bool host_in_subnet(host_t *host, chunk_t net, int net_len)
691: {
692: chunk_t addr;
693:
694: addr = host->get_address(host);
695: return addr_in_subnet(addr, addr.len * 8, net, net_len);
696: }
697:
698: /**
699: * Determine the type or scope of the given unicast IP address. This is not
700: * the same thing returned in rtm_scope/ifa_scope.
701: *
702: * We use return values as defined in RFC 6724 (referring to RFC 4291).
703: */
704: static u_char get_scope(host_t *ip)
705: {
706: chunk_t addr;
707:
708: addr = ip->get_address(ip);
709: switch (addr.len)
710: {
711: case 4:
712: /* we use the mapping defined in RFC 6724, 3.2 */
713: if (addr.ptr[0] == 127)
714: { /* link-local, same as the IPv6 loopback address */
715: return 2;
716: }
717: if (addr.ptr[0] == 169 && addr.ptr[1] == 254)
718: { /* link-local */
719: return 2;
720: }
721: break;
722: case 16:
723: if (IN6_IS_ADDR_LOOPBACK((struct in6_addr*)addr.ptr))
724: { /* link-local, according to RFC 4291, 2.5.3 */
725: return 2;
726: }
727: if (IN6_IS_ADDR_LINKLOCAL((struct in6_addr*)addr.ptr))
728: {
729: return 2;
730: }
731: if (IN6_IS_ADDR_SITELOCAL((struct in6_addr*)addr.ptr))
732: { /* deprecated, according to RFC 4291, 2.5.7 */
733: return 5;
734: }
735: break;
736: default:
737: break;
738: }
739: /* global */
740: return 14;
741: }
742:
743: /**
744: * Determine the label of the given unicast IP address.
745: *
746: * We currently only support the default table given in RFC 6724:
747: *
748: * Prefix Precedence Label
749: * ::1/128 50 0
750: * ::/0 40 1
751: * ::ffff:0:0/96 35 4
752: * 2002::/16 30 2
753: * 2001::/32 5 5
754: * fc00::/7 3 13
755: * ::/96 1 3
756: * fec0::/10 1 11
757: * 3ffe::/16 1 12
758: */
759: static u_char get_label(host_t *ip)
760: {
761: struct {
762: chunk_t net;
763: u_char prefix;
764: u_char label;
765: } priorities[] = {
766: /* priority table ordered by prefix */
767: /* ::1/128 */
768: { chunk_from_chars(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
769: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01), 128, 0 },
770: /* ::ffff:0:0/96 */
771: { chunk_from_chars(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
772: 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00), 96, 4 },
773: /* ::/96 */
774: { chunk_from_chars(0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
775: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), 96, 3 },
776: /* 2001::/32 */
777: { chunk_from_chars(0x20, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
778: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), 32, 5 },
779: /* 2002::/16 */
780: { chunk_from_chars(0x20, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
781: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), 16, 2 },
782: /* 3ffe::/16 */
783: { chunk_from_chars(0x3f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
784: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), 16, 12 },
785: /* fec0::/10 */
786: { chunk_from_chars(0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
787: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), 10, 11 },
788: /* fc00::/7 */
789: { chunk_from_chars(0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
790: 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), 7, 13 },
791: };
792: int i;
793:
794: for (i = 0; i < countof(priorities); i++)
795: {
796: if (host_in_subnet(ip, priorities[i].net, priorities[i].prefix))
797: {
798: return priorities[i].label;
799: }
800: }
801: /* ::/0 */
802: return 1;
803: }
804:
805: /**
806: * Returns the length of the common prefix in bits up to the length of a's
807: * prefix, defined by RFC 6724 as the portion of the address not including the
808: * interface ID, which is 64-bit for most unicast addresses (see RFC 4291).
809: */
810: static u_char common_prefix(host_t *a, host_t *b)
811: {
812: chunk_t aa, ba;
813: u_char byte, bits = 0, match;
814:
815: aa = a->get_address(a);
816: ba = b->get_address(b);
817: for (byte = 0; byte < 8; byte++)
818: {
819: if (aa.ptr[byte] != ba.ptr[byte])
820: {
821: match = aa.ptr[byte] ^ ba.ptr[byte];
822: for (bits = 8; match; match >>= 1)
823: {
824: bits--;
825: }
826: break;
827: }
828: }
829: return byte * 8 + bits;
830: }
831:
832: /**
833: * Compare two IP addresses and return TRUE if the second address is the better
834: * choice of the two to reach the destination.
835: * For IPv6 we approximately follow RFC 6724.
836: */
837: static bool is_address_better(private_kernel_netlink_net_t *this,
838: addr_entry_t *a, addr_entry_t *b, host_t *d)
839: {
840: u_char sa, sb, sd, la, lb, ld, pa, pb;
841:
842: /* rule 2: prefer appropriate scope */
843: if (d)
844: {
845: sa = get_scope(a->ip);
846: sb = get_scope(b->ip);
847: sd = get_scope(d);
848: if (sa < sb)
849: {
850: return sa < sd;
851: }
852: else if (sb < sa)
853: {
854: return sb >= sd;
855: }
856: }
857: if (a->ip->get_family(a->ip) == AF_INET)
858: { /* stop here for IPv4, default to addresses found earlier */
859: return FALSE;
860: }
861: /* rule 3: avoid deprecated addresses (RFC 4862) */
862: if ((a->flags & IFA_F_DEPRECATED) != (b->flags & IFA_F_DEPRECATED))
863: {
864: return a->flags & IFA_F_DEPRECATED;
865: }
866: /* rule 4 is not applicable as we don't know if an address is a home or
867: * care-of addresses.
868: * rule 5 does not apply as we only compare addresses from one interface
869: */
870: /* rule 6: prefer matching label */
871: if (d)
872: {
873: la = get_label(a->ip);
874: lb = get_label(b->ip);
875: ld = get_label(d);
876: if (la == ld && lb != ld)
877: {
878: return FALSE;
879: }
880: else if (lb == ld && la != ld)
881: {
882: return TRUE;
883: }
884: }
885: /* rule 7: prefer temporary addresses (WE REVERSE THIS BY DEFAULT!) */
886: if ((a->flags & IFA_F_TEMPORARY) != (b->flags & IFA_F_TEMPORARY))
887: {
888: if (this->prefer_temporary_addrs)
889: {
890: return b->flags & IFA_F_TEMPORARY;
891: }
892: return a->flags & IFA_F_TEMPORARY;
893: }
894: /* rule 8: use longest matching prefix */
895: if (d)
896: {
897: pa = common_prefix(a->ip, d);
898: pb = common_prefix(b->ip, d);
899: if (pa != pb)
900: {
901: return pb > pa;
902: }
903: }
904: /* default to addresses found earlier */
905: return FALSE;
906: }
907:
908: /**
909: * Get a non-virtual IP address on the given interfaces and optionally in a
910: * given subnet.
911: *
912: * If a candidate address is given, we first search for that address and if not
913: * found return the address as above.
914: * Returned host is a clone, has to be freed by caller.
915: *
916: * this->lock must be held when calling this function.
917: */
918: static host_t *get_matching_address(private_kernel_netlink_net_t *this,
919: int *ifindex, int family, chunk_t net,
920: uint8_t mask, host_t *dest,
921: host_t *candidate)
922: {
923: enumerator_t *ifaces, *addrs;
924: iface_entry_t *iface;
925: addr_entry_t *addr, *best = NULL;
926: bool candidate_matched = FALSE;
927:
928: ifaces = this->ifaces->create_enumerator(this->ifaces);
929: while (ifaces->enumerate(ifaces, &iface))
930: {
931: if (iface->usable && (!ifindex || iface->ifindex == *ifindex))
932: { /* only use matching interfaces not excluded by config */
933: addrs = iface->addrs->create_enumerator(iface->addrs);
934: while (addrs->enumerate(addrs, &addr))
935: {
936: if (addr->refcount ||
937: addr->ip->get_family(addr->ip) != family)
938: { /* ignore virtual IP addresses and ensure family matches */
939: continue;
940: }
941: if (net.ptr && !host_in_subnet(addr->ip, net, mask))
942: { /* optionally match a subnet */
943: continue;
944: }
945: if (candidate && candidate->ip_equals(candidate, addr->ip))
946: { /* stop if we find the candidate */
947: best = addr;
948: candidate_matched = TRUE;
949: break;
950: }
951: else if (!best || is_address_better(this, best, addr, dest))
952: {
953: best = addr;
954: }
955: }
956: addrs->destroy(addrs);
957: if (ifindex || candidate_matched)
958: {
959: break;
960: }
961: }
962: }
963: ifaces->destroy(ifaces);
964: return best ? best->ip->clone(best->ip) : NULL;
965: }
966:
967: /**
968: * Get a non-virtual IP address on the given interface.
969: *
970: * If a candidate address is given, we first search for that address and if not
971: * found return the address as above.
972: * Returned host is a clone, has to be freed by caller.
973: *
974: * this->lock must be held when calling this function.
975: */
976: static host_t *get_interface_address(private_kernel_netlink_net_t *this,
977: int ifindex, int family, host_t *dest,
978: host_t *candidate)
979: {
980: return get_matching_address(this, &ifindex, family, chunk_empty, 0, dest,
981: candidate);
982: }
983:
984: /**
985: * Get a non-virtual IP address in the given subnet.
986: *
987: * If a candidate address is given, we first search for that address and if not
988: * found return the address as above.
989: * Returned host is a clone, has to be freed by caller.
990: *
991: * this->lock must be held when calling this function.
992: */
993: static host_t *get_subnet_address(private_kernel_netlink_net_t *this,
994: int family, chunk_t net, uint8_t mask,
995: host_t *dest, host_t *candidate)
996: {
997: return get_matching_address(this, NULL, family, net, mask, dest, candidate);
998: }
999:
1000: /**
1001: * callback function that raises the delayed roam event
1002: */
1003: static job_requeue_t roam_event(private_kernel_netlink_net_t *this)
1004: {
1005: bool address;
1006:
1007: this->roam_lock->lock(this->roam_lock);
1008: address = this->roam_address;
1009: this->roam_address = FALSE;
1010: this->roam_lock->unlock(this->roam_lock);
1011: charon->kernel->roam(charon->kernel, address);
1012: return JOB_REQUEUE_NONE;
1013: }
1014:
1015: /**
1016: * fire a roaming event. we delay it for a bit and fire only one event
1017: * for multiple calls. otherwise we would create too many events.
1018: */
1019: static void fire_roam_event(private_kernel_netlink_net_t *this, bool address)
1020: {
1021: timeval_t now;
1022: job_t *job;
1023:
1024: if (!this->roam_events)
1025: {
1026: return;
1027: }
1028:
1029: time_monotonic(&now);
1030: this->roam_lock->lock(this->roam_lock);
1031: this->roam_address |= address;
1032: if (!timercmp(&now, &this->next_roam, >))
1033: {
1034: this->roam_lock->unlock(this->roam_lock);
1035: return;
1036: }
1037: timeval_add_ms(&now, ROAM_DELAY);
1038: this->next_roam = now;
1039: this->roam_lock->unlock(this->roam_lock);
1040:
1041: job = (job_t*)callback_job_create((callback_job_cb_t)roam_event,
1042: this, NULL, NULL);
1043: lib->scheduler->schedule_job_ms(lib->scheduler, job, ROAM_DELAY);
1044: }
1045:
1046: /**
1047: * check if an interface with a given index is up and usable
1048: *
1049: * this->lock must be locked when calling this function
1050: */
1051: static bool is_interface_up_and_usable(private_kernel_netlink_net_t *this,
1052: int index)
1053: {
1054: iface_entry_t *iface;
1055:
1056: if (this->ifaces->find_first(this->ifaces, iface_entry_by_index,
1057: (void**)&iface, index))
1058: {
1059: return iface_entry_up_and_usable(iface);
1060: }
1061: return FALSE;
1062: }
1063:
1064: /**
1065: * unregister the current addr_entry_t from the hashtable it is stored in
1066: *
1067: * this->lock must be locked when calling this function
1068: */
1069: CALLBACK(addr_entry_unregister, void,
1070: addr_entry_t *addr, va_list args)
1071: {
1072: private_kernel_netlink_net_t *this;
1073: iface_entry_t *iface;
1074:
1075: VA_ARGS_VGET(args, iface, this);
1076: if (addr->refcount)
1077: {
1078: addr_map_entry_remove(this->vips, addr, iface);
1079: this->condvar->broadcast(this->condvar);
1080: return;
1081: }
1082: addr_map_entry_remove(this->addrs, addr, iface);
1083: }
1084:
1085: /**
1086: * process RTM_NEWLINK/RTM_DELLINK from kernel
1087: */
1088: static void process_link(private_kernel_netlink_net_t *this,
1089: struct nlmsghdr *hdr, bool event)
1090: {
1091: struct ifinfomsg* msg = NLMSG_DATA(hdr);
1092: struct rtattr *rta = IFLA_RTA(msg);
1093: size_t rtasize = IFLA_PAYLOAD (hdr);
1094: enumerator_t *enumerator;
1095: iface_entry_t *current, *entry = NULL;
1096: char *name = NULL;
1097: bool update = FALSE, update_routes = FALSE;
1098:
1099: while (RTA_OK(rta, rtasize))
1100: {
1101: switch (rta->rta_type)
1102: {
1103: case IFLA_IFNAME:
1104: name = RTA_DATA(rta);
1105: break;
1106: }
1107: rta = RTA_NEXT(rta, rtasize);
1108: }
1109: if (!name)
1110: {
1111: name = "(unknown)";
1112: }
1113:
1114: this->lock->write_lock(this->lock);
1115: switch (hdr->nlmsg_type)
1116: {
1117: case RTM_NEWLINK:
1118: {
1119: if (!this->ifaces->find_first(this->ifaces, iface_entry_by_index,
1120: (void**)&entry, msg->ifi_index))
1121: {
1122: INIT(entry,
1123: .ifindex = msg->ifi_index,
1124: .addrs = linked_list_create(),
1125: );
1126: this->ifaces->insert_last(this->ifaces, entry);
1127: }
1128: strncpy(entry->ifname, name, IFNAMSIZ);
1129: entry->ifname[IFNAMSIZ-1] = '\0';
1130: entry->usable = charon->kernel->is_interface_usable(charon->kernel,
1131: name);
1132: if (event && entry->usable)
1133: {
1134: if (!(entry->flags & IFF_UP) && (msg->ifi_flags & IFF_UP))
1135: {
1136: update = update_routes = TRUE;
1137: DBG1(DBG_KNL, "interface %s activated", name);
1138: }
1139: if ((entry->flags & IFF_UP) && !(msg->ifi_flags & IFF_UP))
1140: {
1141: update = TRUE;
1142: DBG1(DBG_KNL, "interface %s deactivated", name);
1143: }
1144: }
1145: entry->flags = msg->ifi_flags;
1146: break;
1147: }
1148: case RTM_DELLINK:
1149: {
1150: enumerator = this->ifaces->create_enumerator(this->ifaces);
1151: while (enumerator->enumerate(enumerator, ¤t))
1152: {
1153: if (current->ifindex == msg->ifi_index)
1154: {
1155: if (event && current->usable)
1156: {
1157: update = TRUE;
1158: DBG1(DBG_KNL, "interface %s deleted", current->ifname);
1159: }
1160: /* TODO: move virtual IPs installed on this interface to
1161: * another interface? */
1162: this->ifaces->remove_at(this->ifaces, enumerator);
1163: current->addrs->invoke_function(current->addrs,
1164: addr_entry_unregister, current, this);
1165: iface_entry_destroy(current);
1166: break;
1167: }
1168: }
1169: enumerator->destroy(enumerator);
1170: break;
1171: }
1172: }
1173: this->lock->unlock(this->lock);
1174:
1175: if (update_routes && event)
1176: {
1177: queue_route_reinstall(this, strdup(name));
1178: }
1179:
1180: if (update && event)
1181: {
1182: fire_roam_event(this, TRUE);
1183: }
1184: }
1185:
1186: /**
1187: * process RTM_NEWADDR/RTM_DELADDR from kernel
1188: */
1189: static void process_addr(private_kernel_netlink_net_t *this,
1190: struct nlmsghdr *hdr, bool event)
1191: {
1192: struct ifaddrmsg* msg = NLMSG_DATA(hdr);
1193: struct rtattr *rta = IFA_RTA(msg);
1194: size_t rtasize = IFA_PAYLOAD (hdr);
1195: host_t *host = NULL;
1196: iface_entry_t *iface;
1197: chunk_t local = chunk_empty, address = chunk_empty;
1198: char *route_ifname = NULL;
1199: bool update = FALSE, found = FALSE, changed = FALSE;
1200:
1201: while (RTA_OK(rta, rtasize))
1202: {
1203: switch (rta->rta_type)
1204: {
1205: case IFA_LOCAL:
1206: local.ptr = RTA_DATA(rta);
1207: local.len = RTA_PAYLOAD(rta);
1208: break;
1209: case IFA_ADDRESS:
1210: address.ptr = RTA_DATA(rta);
1211: address.len = RTA_PAYLOAD(rta);
1212: break;
1213: }
1214: rta = RTA_NEXT(rta, rtasize);
1215: }
1216:
1217: /* For PPP interfaces, we need the IFA_LOCAL address,
1218: * IFA_ADDRESS is the peers address. But IFA_LOCAL is
1219: * not included in all cases (IPv6?), so fallback to IFA_ADDRESS. */
1220: if (local.ptr)
1221: {
1222: host = host_create_from_chunk(msg->ifa_family, local, 0);
1223: }
1224: else if (address.ptr)
1225: {
1226: host = host_create_from_chunk(msg->ifa_family, address, 0);
1227: }
1228:
1229: if (host == NULL)
1230: { /* bad family? */
1231: return;
1232: }
1233:
1234: this->lock->write_lock(this->lock);
1235: if (this->ifaces->find_first(this->ifaces, iface_entry_by_index,
1236: (void**)&iface, msg->ifa_index))
1237: {
1238: addr_map_entry_t *entry, lookup = {
1239: .ip = host,
1240: .iface = iface,
1241: };
1242: addr_entry_t *addr;
1243:
1244: entry = this->vips->get(this->vips, &lookup);
1245: if (entry)
1246: {
1247: if (hdr->nlmsg_type == RTM_NEWADDR)
1248: { /* mark as installed and signal waiting threads */
1249: entry->addr->installed = TRUE;
1250: }
1251: else
1252: { /* the address was already marked as uninstalled */
1253: addr = entry->addr;
1254: iface->addrs->remove(iface->addrs, addr, NULL);
1255: addr_map_entry_remove(this->vips, addr, iface);
1256: addr_entry_destroy(addr);
1257: }
1258: /* no roam events etc. for virtual IPs */
1259: this->condvar->broadcast(this->condvar);
1260: this->lock->unlock(this->lock);
1261: host->destroy(host);
1262: return;
1263: }
1264: entry = this->addrs->get(this->addrs, &lookup);
1265: if (entry)
1266: {
1267: if (hdr->nlmsg_type == RTM_DELADDR)
1268: {
1269: found = TRUE;
1270: addr = entry->addr;
1271: iface->addrs->remove(iface->addrs, addr, NULL);
1272: if (iface->usable)
1273: {
1274: changed = TRUE;
1275: DBG1(DBG_KNL, "%H disappeared from %s", host,
1276: iface->ifname);
1277: }
1278: addr_map_entry_remove(this->addrs, addr, iface);
1279: addr_entry_destroy(addr);
1280: }
1281: }
1282: else
1283: {
1284: if (hdr->nlmsg_type == RTM_NEWADDR)
1285: {
1286: found = TRUE;
1287: changed = TRUE;
1288: route_ifname = strdup(iface->ifname);
1289: INIT(addr,
1290: .ip = host->clone(host),
1291: .flags = msg->ifa_flags,
1292: .scope = msg->ifa_scope,
1293: );
1294: iface->addrs->insert_last(iface->addrs, addr);
1295: addr_map_entry_add(this->addrs, addr, iface);
1296: if (event && iface->usable)
1297: {
1298: DBG1(DBG_KNL, "%H appeared on %s", host, iface->ifname);
1299: }
1300: }
1301: }
1302: if (found && (iface->flags & IFF_UP))
1303: {
1304: update = TRUE;
1305: }
1306: if (!iface->usable)
1307: { /* ignore events for interfaces excluded by config */
1308: update = changed = FALSE;
1309: }
1310: }
1311: this->lock->unlock(this->lock);
1312:
1313: if (update && event && route_ifname)
1314: {
1315: queue_route_reinstall(this, route_ifname);
1316: }
1317: else
1318: {
1319: free(route_ifname);
1320: }
1321: host->destroy(host);
1322:
1323: /* send an update to all IKE_SAs */
1324: if (update && event && changed)
1325: {
1326: fire_roam_event(this, TRUE);
1327: }
1328: }
1329:
1330: /**
1331: * process RTM_NEWROUTE and RTM_DELROUTE from kernel
1332: */
1333: static void process_route(private_kernel_netlink_net_t *this,
1334: struct nlmsghdr *hdr)
1335: {
1336: struct rtmsg* msg = NLMSG_DATA(hdr);
1337: struct rtattr *rta = RTM_RTA(msg);
1338: size_t rtasize = RTM_PAYLOAD(hdr);
1339: uint32_t rta_oif = 0;
1340: host_t *host = NULL;
1341:
1342: /* ignore routes added by us or in the local routing table (local addrs) */
1343: if (msg->rtm_table && (msg->rtm_table == this->routing_table ||
1344: msg->rtm_table == RT_TABLE_LOCAL))
1345: {
1346: return;
1347: }
1348: else if (msg->rtm_flags & RTM_F_CLONED)
1349: { /* ignore cached routes, seem to be created a lot for IPv6 */
1350: return;
1351: }
1352:
1353: while (RTA_OK(rta, rtasize))
1354: {
1355: switch (rta->rta_type)
1356: {
1357: #ifdef HAVE_RTA_TABLE
1358: case RTA_TABLE:
1359: /* also check against extended table ID */
1360: if (RTA_PAYLOAD(rta) == sizeof(uint32_t) &&
1361: this->routing_table == *(uint32_t*)RTA_DATA(rta))
1362: {
1363: return;
1364: }
1365: break;
1366: #endif /* HAVE_RTA_TABLE */
1367: case RTA_PREFSRC:
1368: DESTROY_IF(host);
1369: host = host_create_from_chunk(msg->rtm_family,
1370: chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta)), 0);
1371: break;
1372: case RTA_OIF:
1373: if (RTA_PAYLOAD(rta) == sizeof(rta_oif))
1374: {
1375: rta_oif = *(uint32_t*)RTA_DATA(rta);
1376: }
1377: break;
1378: }
1379: rta = RTA_NEXT(rta, rtasize);
1380: }
1381: this->lock->read_lock(this->lock);
1382: if (rta_oif && !is_interface_up_and_usable(this, rta_oif))
1383: { /* ignore route changes for interfaces that are ignored or down */
1384: this->lock->unlock(this->lock);
1385: DESTROY_IF(host);
1386: return;
1387: }
1388: if (!host && rta_oif)
1389: {
1390: host = get_interface_address(this, rta_oif, msg->rtm_family,
1391: NULL, NULL);
1392: }
1393: if (!host || is_known_vip(this, host))
1394: { /* ignore routes added for virtual IPs */
1395: this->lock->unlock(this->lock);
1396: DESTROY_IF(host);
1397: return;
1398: }
1399: this->lock->unlock(this->lock);
1400: fire_roam_event(this, FALSE);
1401: host->destroy(host);
1402: }
1403:
1404: /**
1405: * process RTM_NEW|DELRULE from kernel
1406: */
1407: static void process_rule(private_kernel_netlink_net_t *this,
1408: struct nlmsghdr *hdr)
1409: {
1410: #ifdef HAVE_LINUX_FIB_RULES_H
1411: struct rtmsg* msg = NLMSG_DATA(hdr);
1412: struct rtattr *rta = RTM_RTA(msg);
1413: size_t rtasize = RTM_PAYLOAD(hdr);
1414:
1415: /* ignore rules added by us or in the local routing table (local addrs) */
1416: if (msg->rtm_table && (msg->rtm_table == this->routing_table ||
1417: msg->rtm_table == RT_TABLE_LOCAL))
1418: {
1419: return;
1420: }
1421:
1422: while (RTA_OK(rta, rtasize))
1423: {
1424: switch (rta->rta_type)
1425: {
1426: case FRA_TABLE:
1427: /* also check against extended table ID */
1428: if (RTA_PAYLOAD(rta) == sizeof(uint32_t) &&
1429: this->routing_table == *(uint32_t*)RTA_DATA(rta))
1430: {
1431: return;
1432: }
1433: break;
1434: }
1435: rta = RTA_NEXT(rta, rtasize);
1436: }
1437: fire_roam_event(this, FALSE);
1438: #endif
1439: }
1440:
1441: /**
1442: * Receives events from kernel
1443: */
1444: static bool receive_events(private_kernel_netlink_net_t *this, int fd,
1445: watcher_event_t event)
1446: {
1447: char response[netlink_get_buflen()];
1448: struct nlmsghdr *hdr = (struct nlmsghdr*)response;
1449: struct sockaddr_nl addr;
1450: socklen_t addr_len = sizeof(addr);
1451: int len;
1452:
1453: len = recvfrom(this->socket_events, response, sizeof(response),
1454: MSG_DONTWAIT, (struct sockaddr*)&addr, &addr_len);
1455: if (len < 0)
1456: {
1457: switch (errno)
1458: {
1459: case EINTR:
1460: /* interrupted, try again */
1461: return TRUE;
1462: case EAGAIN:
1463: /* no data ready, select again */
1464: return TRUE;
1465: default:
1466: DBG1(DBG_KNL, "unable to receive from RT event socket %s (%d)",
1467: strerror(errno), errno);
1468: sleep(1);
1469: return TRUE;
1470: }
1471: }
1472:
1473: if (addr.nl_pid != 0)
1474: { /* not from kernel. not interested, try another one */
1475: return TRUE;
1476: }
1477:
1478: while (NLMSG_OK(hdr, len))
1479: {
1480: /* looks good so far, dispatch netlink message */
1481: switch (hdr->nlmsg_type)
1482: {
1483: case RTM_NEWADDR:
1484: case RTM_DELADDR:
1485: process_addr(this, hdr, TRUE);
1486: break;
1487: case RTM_NEWLINK:
1488: case RTM_DELLINK:
1489: process_link(this, hdr, TRUE);
1490: break;
1491: case RTM_NEWROUTE:
1492: case RTM_DELROUTE:
1493: if (this->process_route)
1494: {
1495: process_route(this, hdr);
1496: }
1497: break;
1498: case RTM_NEWRULE:
1499: case RTM_DELRULE:
1500: if (this->process_rules)
1501: {
1502: process_rule(this, hdr);
1503: }
1504: break;
1505: default:
1506: break;
1507: }
1508: hdr = NLMSG_NEXT(hdr, len);
1509: }
1510: return TRUE;
1511: }
1512:
1513: /** enumerator over addresses */
1514: typedef struct {
1515: private_kernel_netlink_net_t* this;
1516: /** which addresses to enumerate */
1517: kernel_address_type_t which;
1518: } address_enumerator_t;
1519:
1520: CALLBACK(address_enumerator_destroy, void,
1521: address_enumerator_t *data)
1522: {
1523: data->this->lock->unlock(data->this->lock);
1524: free(data);
1525: }
1526:
1527: CALLBACK(filter_addresses, bool,
1528: address_enumerator_t *data, enumerator_t *orig, va_list args)
1529: {
1530: addr_entry_t *addr;
1531: host_t **out;
1532:
1533: VA_ARGS_VGET(args, out);
1534:
1535: while (orig->enumerate(orig, &addr))
1536: {
1537: if (!(data->which & ADDR_TYPE_VIRTUAL) && addr->refcount)
1538: { /* skip virtual interfaces added by us */
1539: continue;
1540: }
1541: if (!(data->which & ADDR_TYPE_REGULAR) && !addr->refcount)
1542: { /* address is regular, but not requested */
1543: continue;
1544: }
1545: if (addr->flags & IFA_F_DEPRECATED ||
1546: addr->scope >= RT_SCOPE_LINK)
1547: { /* skip deprecated addresses or those with an unusable scope */
1548: continue;
1549: }
1550: if (addr->ip->get_family(addr->ip) == AF_INET6)
1551: { /* handle temporary IPv6 addresses according to config */
1552: bool temporary = (addr->flags & IFA_F_TEMPORARY) == IFA_F_TEMPORARY;
1553: if (data->this->prefer_temporary_addrs != temporary)
1554: {
1555: continue;
1556: }
1557: }
1558: *out = addr->ip;
1559: return TRUE;
1560: }
1561: return FALSE;
1562: }
1563:
1564: /**
1565: * enumerator constructor for interfaces
1566: */
1567: static enumerator_t *create_iface_enumerator(iface_entry_t *iface,
1568: address_enumerator_t *data)
1569: {
1570: return enumerator_create_filter(
1571: iface->addrs->create_enumerator(iface->addrs),
1572: filter_addresses, data, NULL);
1573: }
1574:
1575: CALLBACK(filter_interfaces, bool,
1576: address_enumerator_t *data, enumerator_t *orig, va_list args)
1577: {
1578: iface_entry_t *iface, **out;
1579:
1580: VA_ARGS_VGET(args, out);
1581:
1582: while (orig->enumerate(orig, &iface))
1583: {
1584: if (!(data->which & ADDR_TYPE_IGNORED) && !iface->usable)
1585: { /* skip interfaces excluded by config */
1586: continue;
1587: }
1588: if (!(data->which & ADDR_TYPE_LOOPBACK) && (iface->flags & IFF_LOOPBACK))
1589: { /* ignore loopback devices */
1590: continue;
1591: }
1592: if (!(data->which & ADDR_TYPE_DOWN) && !(iface->flags & IFF_UP))
1593: { /* skip interfaces not up */
1594: continue;
1595: }
1596: *out = iface;
1597: return TRUE;
1598: }
1599: return FALSE;
1600: }
1601:
1602: METHOD(kernel_net_t, create_address_enumerator, enumerator_t*,
1603: private_kernel_netlink_net_t *this, kernel_address_type_t which)
1604: {
1605: address_enumerator_t *data;
1606:
1607: INIT(data,
1608: .this = this,
1609: .which = which,
1610: );
1611:
1612: this->lock->read_lock(this->lock);
1613: return enumerator_create_nested(
1614: enumerator_create_filter(
1615: this->ifaces->create_enumerator(this->ifaces),
1616: filter_interfaces, data, NULL),
1617: (void*)create_iface_enumerator, data,
1618: address_enumerator_destroy);
1619: }
1620:
1621: METHOD(kernel_net_t, get_interface_name, bool,
1622: private_kernel_netlink_net_t *this, host_t* ip, char **name)
1623: {
1624: addr_map_entry_t *entry, lookup = {
1625: .ip = ip,
1626: };
1627:
1628: if (ip->is_anyaddr(ip))
1629: {
1630: return FALSE;
1631: }
1632: this->lock->read_lock(this->lock);
1633: /* first try to find it on an up and usable interface */
1634: entry = this->addrs->get_match(this->addrs, &lookup,
1635: (void*)addr_map_entry_match_up_and_usable);
1636: if (entry)
1637: {
1638: if (name)
1639: {
1640: *name = strdup(entry->iface->ifname);
1641: DBG2(DBG_KNL, "%H is on interface %s", ip, *name);
1642: }
1643: this->lock->unlock(this->lock);
1644: return TRUE;
1645: }
1646: /* in a second step, consider virtual IPs installed by us */
1647: entry = this->vips->get_match(this->vips, &lookup,
1648: (void*)addr_map_entry_match_up_and_usable);
1649: if (entry)
1650: {
1651: if (name)
1652: {
1653: *name = strdup(entry->iface->ifname);
1654: DBG2(DBG_KNL, "virtual IP %H is on interface %s", ip, *name);
1655: }
1656: this->lock->unlock(this->lock);
1657: return TRUE;
1658: }
1659: /* maybe it is installed on an ignored interface */
1660: entry = this->addrs->get_match(this->addrs, &lookup,
1661: (void*)addr_map_entry_match_up);
1662: if (!entry)
1663: {
1664: DBG2(DBG_KNL, "%H is not a local address or the interface is down", ip);
1665: }
1666: this->lock->unlock(this->lock);
1667: return FALSE;
1668: }
1669:
1670: /**
1671: * get the index of an interface by name
1672: */
1673: static int get_interface_index(private_kernel_netlink_net_t *this, char* name)
1674: {
1675: iface_entry_t *iface;
1676: int ifindex = 0;
1677:
1678: DBG2(DBG_KNL, "getting iface index for %s", name);
1679:
1680: this->lock->read_lock(this->lock);
1681: if (this->ifaces->find_first(this->ifaces, iface_entry_by_name,
1682: (void**)&iface, name))
1683: {
1684: ifindex = iface->ifindex;
1685: }
1686: this->lock->unlock(this->lock);
1687:
1688: if (ifindex == 0)
1689: {
1690: DBG1(DBG_KNL, "unable to get interface index for %s", name);
1691: }
1692: return ifindex;
1693: }
1694:
1695: /**
1696: * get the name of an interface by index (allocated)
1697: */
1698: static char *get_interface_name_by_index(private_kernel_netlink_net_t *this,
1699: int index)
1700: {
1701: iface_entry_t *iface;
1702: char *name = NULL;
1703:
1704: DBG2(DBG_KNL, "getting iface name for index %d", index);
1705:
1706: this->lock->read_lock(this->lock);
1707: if (this->ifaces->find_first(this->ifaces, iface_entry_by_index,
1708: (void**)&iface, index))
1709: {
1710: name = strdup(iface->ifname);
1711: }
1712: this->lock->unlock(this->lock);
1713:
1714: if (!name)
1715: {
1716: DBG1(DBG_KNL, "unable to get interface name for %d", index);
1717: }
1718: return name;
1719: }
1720:
1721: /**
1722: * Store information about a route retrieved via RTNETLINK
1723: */
1724: typedef struct {
1725: chunk_t gtw;
1726: chunk_t pref_src;
1727: chunk_t dst;
1728: chunk_t src;
1729: host_t *src_host;
1730: uint8_t dst_len;
1731: uint8_t src_len;
1732: uint32_t table;
1733: uint32_t oif;
1734: uint32_t priority;
1735: } rt_entry_t;
1736:
1737: /**
1738: * Free a route entry
1739: */
1740: static void rt_entry_destroy(rt_entry_t *this)
1741: {
1742: DESTROY_IF(this->src_host);
1743: free(this);
1744: }
1745:
1746: /**
1747: * Check if the route received with RTM_NEWROUTE is usable based on its type.
1748: */
1749: static bool route_usable(struct nlmsghdr *hdr, bool allow_local)
1750: {
1751: struct rtmsg *msg;
1752:
1753: msg = NLMSG_DATA(hdr);
1754: switch (msg->rtm_type)
1755: {
1756: case RTN_BLACKHOLE:
1757: case RTN_UNREACHABLE:
1758: case RTN_PROHIBIT:
1759: case RTN_THROW:
1760: return FALSE;
1761: case RTN_LOCAL:
1762: return allow_local;
1763: default:
1764: return TRUE;
1765: }
1766: }
1767:
1768: /**
1769: * Parse route received with RTM_NEWROUTE. The given rt_entry_t object will be
1770: * reused if not NULL.
1771: *
1772: * Returned chunks point to internal data of the Netlink message.
1773: */
1774: static rt_entry_t *parse_route(struct nlmsghdr *hdr, rt_entry_t *route)
1775: {
1776: struct rtattr *rta;
1777: struct rtmsg *msg;
1778: size_t rtasize;
1779:
1780: msg = NLMSG_DATA(hdr);
1781: rta = RTM_RTA(msg);
1782: rtasize = RTM_PAYLOAD(hdr);
1783:
1784: if (route)
1785: {
1786: *route = (rt_entry_t){
1787: .dst_len = msg->rtm_dst_len,
1788: .src_len = msg->rtm_src_len,
1789: .table = msg->rtm_table,
1790: };
1791: }
1792: else
1793: {
1794: INIT(route,
1795: .dst_len = msg->rtm_dst_len,
1796: .src_len = msg->rtm_src_len,
1797: .table = msg->rtm_table,
1798: );
1799: }
1800:
1801: while (RTA_OK(rta, rtasize))
1802: {
1803: switch (rta->rta_type)
1804: {
1805: case RTA_PREFSRC:
1806: route->pref_src = chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta));
1807: break;
1808: case RTA_GATEWAY:
1809: route->gtw = chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta));
1810: break;
1811: case RTA_DST:
1812: route->dst = chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta));
1813: break;
1814: case RTA_SRC:
1815: route->src = chunk_create(RTA_DATA(rta), RTA_PAYLOAD(rta));
1816: break;
1817: case RTA_OIF:
1818: if (RTA_PAYLOAD(rta) == sizeof(route->oif))
1819: {
1820: route->oif = *(uint32_t*)RTA_DATA(rta);
1821: }
1822: break;
1823: case RTA_PRIORITY:
1824: if (RTA_PAYLOAD(rta) == sizeof(route->priority))
1825: {
1826: route->priority = *(uint32_t*)RTA_DATA(rta);
1827: }
1828: break;
1829: #ifdef HAVE_RTA_TABLE
1830: case RTA_TABLE:
1831: if (RTA_PAYLOAD(rta) == sizeof(route->table))
1832: {
1833: route->table = *(uint32_t*)RTA_DATA(rta);
1834: }
1835: break;
1836: #endif /* HAVE_RTA_TABLE*/
1837: }
1838: rta = RTA_NEXT(rta, rtasize);
1839: }
1840: return route;
1841: }
1842:
1843: /**
1844: * Get a route: If "nexthop", the nexthop is returned. source addr otherwise.
1845: */
1846: static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
1847: int prefix, bool nexthop, host_t *candidate,
1848: char **iface, u_int recursion)
1849: {
1850: netlink_buf_t request;
1851: struct nlmsghdr *hdr, *out, *current;
1852: struct rtmsg *msg;
1853: chunk_t chunk;
1854: size_t len;
1855: linked_list_t *routes;
1856: rt_entry_t *route = NULL, *best = NULL;
1857: enumerator_t *enumerator;
1858: host_t *addr = NULL;
1859: bool match_net;
1860: int family;
1861:
1862: if (recursion > MAX_ROUTE_RECURSION)
1863: {
1864: return NULL;
1865: }
1866: chunk = dest->get_address(dest);
1867: len = chunk.len * 8;
1868: prefix = prefix < 0 ? len : min(prefix, len);
1869: match_net = prefix != len;
1870:
1871: memset(&request, 0, sizeof(request));
1872:
1873: family = dest->get_family(dest);
1874: hdr = &request.hdr;
1875: hdr->nlmsg_flags = NLM_F_REQUEST;
1876: hdr->nlmsg_type = RTM_GETROUTE;
1877: hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
1878:
1879: msg = NLMSG_DATA(hdr);
1880: msg->rtm_family = family;
1881: if (!match_net && this->rta_mark && this->routing_mark.value)
1882: {
1883: /* if our routing rule excludes packets with a certain mark we can
1884: * get the preferred route without having to dump all routes */
1885: chunk = chunk_from_thing(this->routing_mark.value);
1886: netlink_add_attribute(hdr, RTA_MARK, chunk, sizeof(request));
1887: }
1888: else if (family == AF_INET || this->rta_prefsrc_for_ipv6 ||
1889: this->routing_table || match_net)
1890: { /* kernels prior to 3.0 do not support RTA_PREFSRC for IPv6 routes.
1891: * as we want to ignore routes with virtual IPs we cannot use DUMP
1892: * if these routes are not installed in a separate table */
1893: if (this->install_routes)
1894: {
1895: hdr->nlmsg_flags |= NLM_F_DUMP;
1896: }
1897: }
1898: if (candidate)
1899: {
1900: chunk = candidate->get_address(candidate);
1901: if (hdr->nlmsg_flags & NLM_F_DUMP)
1902: {
1903: netlink_add_attribute(hdr, RTA_PREFSRC, chunk, sizeof(request));
1904: }
1905: else
1906: {
1907: netlink_add_attribute(hdr, RTA_SRC, chunk, sizeof(request));
1908: }
1909: }
1910: /* we use this below to match against the routes */
1911: chunk = dest->get_address(dest);
1912: if (!match_net)
1913: {
1914: netlink_add_attribute(hdr, RTA_DST, chunk, sizeof(request));
1915: }
1916:
1917: if (this->socket->send(this->socket, hdr, &out, &len) != SUCCESS)
1918: {
1919: DBG2(DBG_KNL, "getting %s to reach %H/%d failed",
1920: nexthop ? "nexthop" : "address", dest, prefix);
1921: return NULL;
1922: }
1923: routes = linked_list_create();
1924: this->lock->read_lock(this->lock);
1925:
1926: for (current = out; NLMSG_OK(current, len);
1927: current = NLMSG_NEXT(current, len))
1928: {
1929: switch (current->nlmsg_type)
1930: {
1931: case NLMSG_DONE:
1932: break;
1933: case RTM_NEWROUTE:
1934: {
1935: rt_entry_t *other;
1936: uintptr_t table;
1937:
1938: if (!route_usable(current, TRUE))
1939: {
1940: continue;
1941: }
1942: route = parse_route(current, route);
1943:
1944: table = (uintptr_t)route->table;
1945: if (this->rt_exclude->find_first(this->rt_exclude, NULL,
1946: (void**)&table))
1947: { /* route is from an excluded routing table */
1948: continue;
1949: }
1950: if (this->routing_table != 0 &&
1951: route->table == this->routing_table)
1952: { /* route is from our own ipsec routing table */
1953: continue;
1954: }
1955: if (route->oif && !is_interface_up_and_usable(this, route->oif))
1956: { /* interface is down */
1957: continue;
1958: }
1959: if (!addr_in_subnet(chunk, prefix, route->dst, route->dst_len))
1960: { /* route destination does not contain dest */
1961: continue;
1962: }
1963: if (route->pref_src.ptr)
1964: { /* verify source address, if any */
1965: host_t *src = host_create_from_chunk(msg->rtm_family,
1966: route->pref_src, 0);
1967: if (src && is_known_vip(this, src))
1968: { /* ignore routes installed by us */
1969: src->destroy(src);
1970: continue;
1971: }
1972: route->src_host = src;
1973: }
1974: /* insert route, sorted by network prefix and priority */
1975: enumerator = routes->create_enumerator(routes);
1976: while (enumerator->enumerate(enumerator, &other))
1977: {
1978: if (route->dst_len > other->dst_len)
1979: {
1980: break;
1981: }
1982: if (route->dst_len == other->dst_len &&
1983: route->priority < other->priority)
1984: {
1985: break;
1986: }
1987: }
1988: routes->insert_before(routes, enumerator, route);
1989: enumerator->destroy(enumerator);
1990: route = NULL;
1991: continue;
1992: }
1993: default:
1994: continue;
1995: }
1996: break;
1997: }
1998: if (route)
1999: {
2000: rt_entry_destroy(route);
2001: }
2002:
2003: /* now we have a list of routes matching dest, sorted by net prefix.
2004: * we will look for source addresses for these routes and select the one
2005: * with the preferred source address, if possible */
2006: enumerator = routes->create_enumerator(routes);
2007: while (enumerator->enumerate(enumerator, &route))
2008: {
2009: if (route->src_host)
2010: { /* got a source address with the route, if no preferred source
2011: * is given or it matches we are done, as this is the best route */
2012: if (!candidate || candidate->ip_equals(candidate, route->src_host))
2013: {
2014: best = route;
2015: break;
2016: }
2017: else if (route->oif)
2018: { /* no match yet, maybe it is assigned to the same interface */
2019: host_t *src = get_interface_address(this, route->oif,
2020: msg->rtm_family, dest, candidate);
2021: if (src && src->ip_equals(src, candidate))
2022: {
2023: route->src_host->destroy(route->src_host);
2024: route->src_host = src;
2025: best = route;
2026: break;
2027: }
2028: DESTROY_IF(src);
2029: }
2030: /* no luck yet with the source address. if this is the best (first)
2031: * route we store it as fallback in case we don't find a route with
2032: * the preferred source */
2033: best = best ?: route;
2034: continue;
2035: }
2036: if (route->src.ptr)
2037: { /* no src, but a source selector, try to find a matching address */
2038: route->src_host = get_subnet_address(this, msg->rtm_family,
2039: route->src, route->src_len, dest,
2040: candidate);
2041: if (route->src_host)
2042: { /* we handle this address the same as the one above */
2043: if (!candidate ||
2044: candidate->ip_equals(candidate, route->src_host))
2045: {
2046: best = route;
2047: break;
2048: }
2049: best = best ?: route;
2050: continue;
2051: }
2052: }
2053: if (route->oif)
2054: { /* no src, but an interface - get address from it */
2055: route->src_host = get_interface_address(this, route->oif,
2056: msg->rtm_family, dest, candidate);
2057: if (route->src_host)
2058: { /* more of the same */
2059: if (!candidate ||
2060: candidate->ip_equals(candidate, route->src_host))
2061: {
2062: best = route;
2063: break;
2064: }
2065: best = best ?: route;
2066: continue;
2067: }
2068: }
2069: if (route->gtw.ptr)
2070: { /* no src, no iface, but a gateway - lookup src to reach gtw */
2071: host_t *gtw;
2072:
2073: gtw = host_create_from_chunk(msg->rtm_family, route->gtw, 0);
2074: if (gtw && !gtw->ip_equals(gtw, dest))
2075: {
2076: route->src_host = get_route(this, gtw, -1, FALSE, candidate,
2077: iface, recursion + 1);
2078: }
2079: DESTROY_IF(gtw);
2080: if (route->src_host)
2081: { /* more of the same */
2082: if (!candidate ||
2083: candidate->ip_equals(candidate, route->src_host))
2084: {
2085: best = route;
2086: break;
2087: }
2088: best = best ?: route;
2089: }
2090: }
2091: }
2092: enumerator->destroy(enumerator);
2093:
2094: if (nexthop)
2095: { /* nexthop lookup, return gateway and oif if any */
2096: if (iface)
2097: {
2098: *iface = NULL;
2099: }
2100: if (best || routes->get_first(routes, (void**)&best) == SUCCESS)
2101: {
2102: addr = host_create_from_chunk(msg->rtm_family, best->gtw, 0);
2103: if (iface && best->oif)
2104: {
2105: *iface = get_interface_name_by_index(this, best->oif);
2106: }
2107: }
2108: if (!addr && !match_net)
2109: { /* fallback to destination address */
2110: addr = dest->clone(dest);
2111: }
2112: }
2113: else
2114: {
2115: if (best)
2116: {
2117: addr = best->src_host->clone(best->src_host);
2118: }
2119: }
2120: this->lock->unlock(this->lock);
2121: routes->destroy_function(routes, (void*)rt_entry_destroy);
2122: free(out);
2123:
2124: if (addr)
2125: {
2126: if (nexthop && iface && *iface)
2127: {
2128: DBG2(DBG_KNL, "using %H as nexthop and %s as dev to reach %H/%d",
2129: addr, *iface, dest, prefix);
2130: }
2131: else
2132: {
2133: DBG2(DBG_KNL, "using %H as %s to reach %H/%d", addr,
2134: nexthop ? "nexthop" : "address", dest, prefix);
2135: }
2136: }
2137: else if (!recursion)
2138: {
2139: DBG2(DBG_KNL, "no %s found to reach %H/%d",
2140: nexthop ? "nexthop" : "address", dest, prefix);
2141: }
2142: return addr;
2143: }
2144:
2145: METHOD(kernel_net_t, get_source_addr, host_t*,
2146: private_kernel_netlink_net_t *this, host_t *dest, host_t *src)
2147: {
2148: return get_route(this, dest, -1, FALSE, src, NULL, 0);
2149: }
2150:
2151: METHOD(kernel_net_t, get_nexthop, host_t*,
2152: private_kernel_netlink_net_t *this, host_t *dest, int prefix, host_t *src,
2153: char **iface)
2154: {
2155: return get_route(this, dest, prefix, TRUE, src, iface, 0);
2156: }
2157:
2158: /** enumerator over subnets */
2159: typedef struct {
2160: enumerator_t public;
2161: private_kernel_netlink_net_t *private;
2162: /** message from the kernel */
2163: struct nlmsghdr *msg;
2164: /** current message from the kernel */
2165: struct nlmsghdr *current;
2166: /** remaining length */
2167: size_t len;
2168: /** last subnet enumerated */
2169: host_t *net;
2170: /** interface of current net */
2171: char ifname[IFNAMSIZ];
2172: } subnet_enumerator_t;
2173:
2174: METHOD(enumerator_t, destroy_subnet_enumerator, void,
2175: subnet_enumerator_t *this)
2176: {
2177: DESTROY_IF(this->net);
2178: free(this->msg);
2179: free(this);
2180: }
2181:
2182: METHOD(enumerator_t, enumerate_subnets, bool,
2183: subnet_enumerator_t *this, va_list args)
2184: {
2185: host_t **net;
2186: uint8_t *mask;
2187: char **ifname;
2188:
2189: VA_ARGS_VGET(args, net, mask, ifname);
2190:
2191: if (!this->current)
2192: {
2193: this->current = this->msg;
2194: }
2195: else
2196: {
2197: this->current = NLMSG_NEXT(this->current, this->len);
2198: DESTROY_IF(this->net);
2199: this->net = NULL;
2200: }
2201:
2202: while (NLMSG_OK(this->current, this->len))
2203: {
2204: switch (this->current->nlmsg_type)
2205: {
2206: case NLMSG_DONE:
2207: break;
2208: case RTM_NEWROUTE:
2209: {
2210: rt_entry_t route;
2211:
2212: if (!route_usable(this->current, FALSE))
2213: {
2214: break;
2215: }
2216: parse_route(this->current, &route);
2217:
2218: if (route.table && (
2219: route.table == RT_TABLE_LOCAL ||
2220: route.table == this->private->routing_table))
2221: { /* ignore our own and the local routing tables */
2222: break;
2223: }
2224: else if (route.gtw.ptr)
2225: { /* ignore routes via gateway/next hop */
2226: break;
2227: }
2228:
2229: if (route.dst.ptr && route.oif &&
2230: if_indextoname(route.oif, this->ifname))
2231: {
2232: this->net = host_create_from_chunk(AF_UNSPEC, route.dst, 0);
2233: *net = this->net;
2234: *mask = route.dst_len;
2235: *ifname = this->ifname;
2236: return TRUE;
2237: }
2238: break;
2239: }
2240: default:
2241: break;
2242: }
2243: this->current = NLMSG_NEXT(this->current, this->len);
2244: }
2245: return FALSE;
2246: }
2247:
2248: METHOD(kernel_net_t, create_local_subnet_enumerator, enumerator_t*,
2249: private_kernel_netlink_net_t *this)
2250: {
2251: netlink_buf_t request;
2252: struct nlmsghdr *hdr, *out;
2253: struct rtmsg *msg;
2254: size_t len;
2255: subnet_enumerator_t *enumerator;
2256:
2257: memset(&request, 0, sizeof(request));
2258:
2259: hdr = &request.hdr;
2260: hdr->nlmsg_flags = NLM_F_REQUEST;
2261: hdr->nlmsg_type = RTM_GETROUTE;
2262: hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
2263: hdr->nlmsg_flags |= NLM_F_DUMP;
2264:
2265: msg = NLMSG_DATA(hdr);
2266: msg->rtm_scope = RT_SCOPE_LINK;
2267:
2268: if (this->socket->send(this->socket, hdr, &out, &len) != SUCCESS)
2269: {
2270: DBG2(DBG_KNL, "enumerating local subnets failed");
2271: return enumerator_create_empty();
2272: }
2273:
2274: INIT(enumerator,
2275: .public = {
2276: .enumerate = enumerator_enumerate_default,
2277: .venumerate = _enumerate_subnets,
2278: .destroy = _destroy_subnet_enumerator,
2279: },
2280: .private = this,
2281: .msg = out,
2282: .len = len,
2283: );
2284: return &enumerator->public;
2285: }
2286:
2287: /**
2288: * Manages the creation and deletion of IPv6 address labels for virtual IPs.
2289: * By setting the appropriate nlmsg_type the label is either added or removed.
2290: */
2291: static status_t manage_addrlabel(private_kernel_netlink_net_t *this,
2292: int nlmsg_type, host_t *ip)
2293: {
2294: netlink_buf_t request;
2295: struct nlmsghdr *hdr;
2296: struct ifaddrlblmsg *msg;
2297: chunk_t chunk;
2298: uint32_t label;
2299:
2300: memset(&request, 0, sizeof(request));
2301:
2302: chunk = ip->get_address(ip);
2303:
2304: hdr = &request.hdr;
2305: hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
2306: if (nlmsg_type == RTM_NEWADDRLABEL)
2307: {
2308: hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
2309: }
2310: hdr->nlmsg_type = nlmsg_type;
2311: hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrlblmsg));
2312:
2313: msg = NLMSG_DATA(hdr);
2314: msg->ifal_family = ip->get_family(ip);
2315: msg->ifal_prefixlen = chunk.len * 8;
2316:
2317: netlink_add_attribute(hdr, IFAL_ADDRESS, chunk, sizeof(request));
2318: /* doesn't really matter as default labels are < 20 but this makes it kinda
2319: * recognizable */
2320: label = 220;
2321: netlink_add_attribute(hdr, IFAL_LABEL, chunk_from_thing(label),
2322: sizeof(request));
2323:
2324: return this->socket->send_ack(this->socket, hdr);
2325: }
2326:
2327: /**
2328: * Manages the creation and deletion of ip addresses on an interface.
2329: * By setting the appropriate nlmsg_type, the ip will be set or unset.
2330: */
2331: static status_t manage_ipaddr(private_kernel_netlink_net_t *this, int nlmsg_type,
2332: int flags, int if_index, host_t *ip, int prefix)
2333: {
2334: netlink_buf_t request;
2335: struct nlmsghdr *hdr;
2336: struct ifaddrmsg *msg;
2337: chunk_t chunk;
2338:
2339: memset(&request, 0, sizeof(request));
2340:
2341: chunk = ip->get_address(ip);
2342:
2343: hdr = &request.hdr;
2344: hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags;
2345: hdr->nlmsg_type = nlmsg_type;
2346: hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
2347:
2348: msg = NLMSG_DATA(hdr);
2349: msg->ifa_family = ip->get_family(ip);
2350: msg->ifa_flags = 0;
2351: msg->ifa_prefixlen = prefix < 0 ? chunk.len * 8 : prefix;
2352: msg->ifa_scope = RT_SCOPE_UNIVERSE;
2353: msg->ifa_index = if_index;
2354:
2355: netlink_add_attribute(hdr, IFA_LOCAL, chunk, sizeof(request));
2356:
2357: if (ip->get_family(ip) == AF_INET6)
2358: {
2359: #ifdef IFA_F_NODAD
2360: msg->ifa_flags |= IFA_F_NODAD;
2361: #endif
2362: if (this->rta_prefsrc_for_ipv6)
2363: {
2364: /* if source routes are possible we set a label for this virtual IP
2365: * so it gets only used if forced by our route, and not by the
2366: * default IPv6 address selection */
2367: int labelop = nlmsg_type == RTM_NEWADDR ? RTM_NEWADDRLABEL
2368: : RTM_DELADDRLABEL;
2369: if (manage_addrlabel(this, labelop, ip) != SUCCESS)
2370: {
2371: /* if we can't use address labels we let the virtual IP get
2372: * deprecated immediately (but mark it as valid forever), which
2373: * should also avoid that it gets used by the default address
2374: * selection */
2375: struct ifa_cacheinfo cache = {
2376: .ifa_valid = 0xFFFFFFFF,
2377: .ifa_prefered = 0,
2378: };
2379: netlink_add_attribute(hdr, IFA_CACHEINFO,
2380: chunk_from_thing(cache), sizeof(request));
2381: }
2382: }
2383: }
2384: return this->socket->send_ack(this->socket, hdr);
2385: }
2386:
2387: METHOD(kernel_net_t, add_ip, status_t,
2388: private_kernel_netlink_net_t *this, host_t *virtual_ip, int prefix,
2389: char *iface_name)
2390: {
2391: addr_map_entry_t *entry, lookup = {
2392: .ip = virtual_ip,
2393: };
2394: iface_entry_t *iface = NULL;
2395:
2396: if (!this->install_virtual_ip)
2397: { /* disabled by config */
2398: return SUCCESS;
2399: }
2400:
2401: this->lock->write_lock(this->lock);
2402: /* the virtual IP might actually be installed as regular IP, in which case
2403: * we don't track it as virtual IP */
2404: entry = this->addrs->get_match(this->addrs, &lookup,
2405: (void*)addr_map_entry_match);
2406: if (!entry)
2407: { /* otherwise it might already be installed as virtual IP */
2408: entry = this->vips->get_match(this->vips, &lookup,
2409: (void*)addr_map_entry_match);
2410: if (entry)
2411: { /* the vip we found can be in one of three states: 1) installed and
2412: * ready, 2) just added by another thread, but not yet confirmed to
2413: * be installed by the kernel, 3) just deleted, but not yet gone.
2414: * Then while we wait below, several things could happen (as we
2415: * release the lock). For instance, the interface could disappear,
2416: * or the IP is finally deleted, and it reappears on a different
2417: * interface. All these cases are handled by the call below. */
2418: while (!is_vip_installed_or_gone(this, virtual_ip, &entry))
2419: {
2420: this->condvar->wait(this->condvar, this->lock);
2421: }
2422: if (entry)
2423: {
2424: entry->addr->refcount++;
2425: }
2426: }
2427: }
2428: if (entry)
2429: {
2430: DBG2(DBG_KNL, "virtual IP %H is already installed on %s", virtual_ip,
2431: entry->iface->ifname);
2432: this->lock->unlock(this->lock);
2433: return SUCCESS;
2434: }
2435: /* try to find the target interface, either by config or via src ip */
2436: if (!this->install_virtual_ip_on ||
2437: !this->ifaces->find_first(this->ifaces, iface_entry_by_name,
2438: (void**)&iface, this->install_virtual_ip_on))
2439: {
2440: if (!this->ifaces->find_first(this->ifaces, iface_entry_by_name,
2441: (void**)&iface, iface_name))
2442: { /* if we don't find the requested interface we just use the first */
2443: this->ifaces->get_first(this->ifaces, (void**)&iface);
2444: }
2445: }
2446: if (iface)
2447: {
2448: addr_entry_t *addr;
2449: char *ifname;
2450: int ifi;
2451:
2452: INIT(addr,
2453: .ip = virtual_ip->clone(virtual_ip),
2454: .refcount = 1,
2455: .scope = RT_SCOPE_UNIVERSE,
2456: );
2457: iface->addrs->insert_last(iface->addrs, addr);
2458: addr_map_entry_add(this->vips, addr, iface);
2459: ifi = iface->ifindex;
2460: this->lock->unlock(this->lock);
2461: if (manage_ipaddr(this, RTM_NEWADDR, NLM_F_CREATE | NLM_F_EXCL,
2462: ifi, virtual_ip, prefix) == SUCCESS)
2463: {
2464: this->lock->write_lock(this->lock);
2465: while (!is_vip_installed_or_gone(this, virtual_ip, &entry))
2466: { /* wait until address appears */
2467: this->condvar->wait(this->condvar, this->lock);
2468: }
2469: if (entry)
2470: { /* we fail if the interface got deleted in the meantime */
2471: ifname = strdup(entry->iface->ifname);
2472: this->lock->unlock(this->lock);
2473: DBG2(DBG_KNL, "virtual IP %H installed on %s",
2474: virtual_ip, ifname);
2475: /* during IKEv1 reauthentication, children get moved from
2476: * old the new SA before the virtual IP is available. This
2477: * kills the route for our virtual IP, reinstall. */
2478: queue_route_reinstall(this, ifname);
2479: return SUCCESS;
2480: }
2481: this->lock->unlock(this->lock);
2482: }
2483: DBG1(DBG_KNL, "adding virtual IP %H failed", virtual_ip);
2484: return FAILED;
2485: }
2486: this->lock->unlock(this->lock);
2487: DBG1(DBG_KNL, "no interface available, unable to install virtual IP %H",
2488: virtual_ip);
2489: return FAILED;
2490: }
2491:
2492: METHOD(kernel_net_t, del_ip, status_t,
2493: private_kernel_netlink_net_t *this, host_t *virtual_ip, int prefix,
2494: bool wait)
2495: {
2496: addr_map_entry_t *entry, lookup = {
2497: .ip = virtual_ip,
2498: };
2499:
2500: if (!this->install_virtual_ip)
2501: { /* disabled by config */
2502: return SUCCESS;
2503: }
2504:
2505: DBG2(DBG_KNL, "deleting virtual IP %H", virtual_ip);
2506:
2507: this->lock->write_lock(this->lock);
2508: entry = this->vips->get_match(this->vips, &lookup,
2509: (void*)addr_map_entry_match);
2510: if (!entry)
2511: { /* we didn't install this IP as virtual IP */
2512: entry = this->addrs->get_match(this->addrs, &lookup,
2513: (void*)addr_map_entry_match);
2514: if (entry)
2515: {
2516: DBG2(DBG_KNL, "not deleting existing IP %H on %s", virtual_ip,
2517: entry->iface->ifname);
2518: this->lock->unlock(this->lock);
2519: return SUCCESS;
2520: }
2521: DBG2(DBG_KNL, "virtual IP %H not cached, unable to delete", virtual_ip);
2522: this->lock->unlock(this->lock);
2523: return FAILED;
2524: }
2525: if (entry->addr->refcount == 1)
2526: {
2527: status_t status;
2528: int ifi;
2529:
2530: /* we set this flag so that threads calling add_ip will block and wait
2531: * until the entry is gone, also so we can wait below */
2532: entry->addr->installed = FALSE;
2533: ifi = entry->iface->ifindex;
2534: this->lock->unlock(this->lock);
2535: status = manage_ipaddr(this, RTM_DELADDR, 0, ifi, virtual_ip, prefix);
2536: if (status == SUCCESS && wait)
2537: { /* wait until the address is really gone */
2538: this->lock->write_lock(this->lock);
2539: while (is_known_vip(this, virtual_ip))
2540: {
2541: this->condvar->wait(this->condvar, this->lock);
2542: }
2543: this->lock->unlock(this->lock);
2544: }
2545: return status;
2546: }
2547: else
2548: {
2549: entry->addr->refcount--;
2550: }
2551: DBG2(DBG_KNL, "virtual IP %H used by other SAs, not deleting",
2552: virtual_ip);
2553: this->lock->unlock(this->lock);
2554: return SUCCESS;
2555: }
2556:
2557: /**
2558: * Manages source routes in the routing table.
2559: * By setting the appropriate nlmsg_type, the route gets added or removed.
2560: */
2561: static status_t manage_srcroute(private_kernel_netlink_net_t *this,
2562: int nlmsg_type, int flags, chunk_t dst_net,
2563: uint8_t prefixlen, host_t *gateway,
2564: host_t *src_ip, char *if_name, bool pass)
2565: {
2566: netlink_buf_t request;
2567: struct nlmsghdr *hdr;
2568: struct rtmsg *msg;
2569: struct rtattr *rta;
2570: int ifindex;
2571: chunk_t chunk;
2572:
2573: /* if route is 0.0.0.0/0, we can't install it, as it would
2574: * overwrite the default route. Instead, we add two routes:
2575: * 0.0.0.0/1 and 128.0.0.0/1 */
2576: if (this->routing_table == 0 && prefixlen == 0)
2577: {
2578: chunk_t half_net;
2579: uint8_t half_prefixlen;
2580: status_t status;
2581:
2582: half_net = chunk_alloca(dst_net.len);
2583: memset(half_net.ptr, 0, half_net.len);
2584: half_prefixlen = 1;
2585: /* no throw routes in the main table */
2586: status = manage_srcroute(this, nlmsg_type, flags, half_net,
2587: half_prefixlen, gateway, src_ip, if_name, FALSE);
2588: half_net.ptr[0] |= 0x80;
2589: status |= manage_srcroute(this, nlmsg_type, flags, half_net,
2590: half_prefixlen, gateway, src_ip, if_name, FALSE);
2591: return status;
2592: }
2593:
2594: memset(&request, 0, sizeof(request));
2595:
2596: hdr = &request.hdr;
2597: hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags;
2598: hdr->nlmsg_type = nlmsg_type;
2599: hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
2600:
2601: msg = NLMSG_DATA(hdr);
2602: msg->rtm_family = (dst_net.len == 4) ? AF_INET : AF_INET6;
2603: msg->rtm_dst_len = prefixlen;
2604: msg->rtm_protocol = RTPROT_STATIC;
2605: msg->rtm_type = pass ? RTN_THROW : RTN_UNICAST;
2606: msg->rtm_scope = RT_SCOPE_UNIVERSE;
2607:
2608: if (this->routing_table < 256)
2609: {
2610: msg->rtm_table = this->routing_table;
2611: }
2612: else
2613: {
2614: #ifdef HAVE_RTA_TABLE
2615: chunk = chunk_from_thing(this->routing_table);
2616: netlink_add_attribute(hdr, RTA_TABLE, chunk, sizeof(request));
2617: #else
2618: DBG1(DBG_KNL, "routing table IDs > 255 are not supported");
2619: return FAILED;
2620: #endif /* HAVE_RTA_TABLE */
2621: }
2622: netlink_add_attribute(hdr, RTA_DST, dst_net, sizeof(request));
2623:
2624: /* only when installing regular routes do we need all the parameters,
2625: * deletes are done by destination net (except if metrics are used, which
2626: * we don't support), for throw routes we don't need any of them either */
2627: if (nlmsg_type == RTM_NEWROUTE && !pass)
2628: {
2629: chunk = src_ip->get_address(src_ip);
2630: netlink_add_attribute(hdr, RTA_PREFSRC, chunk, sizeof(request));
2631: if (gateway && gateway->get_family(gateway) == src_ip->get_family(src_ip))
2632: {
2633: chunk = gateway->get_address(gateway);
2634: netlink_add_attribute(hdr, RTA_GATEWAY, chunk, sizeof(request));
2635: }
2636: ifindex = get_interface_index(this, if_name);
2637: chunk.ptr = (char*)&ifindex;
2638: chunk.len = sizeof(ifindex);
2639: netlink_add_attribute(hdr, RTA_OIF, chunk, sizeof(request));
2640:
2641: if (this->mtu || this->mss)
2642: {
2643: chunk = chunk_alloca(RTA_LENGTH((sizeof(struct rtattr) +
2644: sizeof(uint32_t)) * 2));
2645: chunk.len = 0;
2646: rta = (struct rtattr*)chunk.ptr;
2647: if (this->mtu)
2648: {
2649: rta->rta_type = RTAX_MTU;
2650: rta->rta_len = RTA_LENGTH(sizeof(uint32_t));
2651: memcpy(RTA_DATA(rta), &this->mtu, sizeof(uint32_t));
2652: chunk.len = rta->rta_len;
2653: }
2654: if (this->mss)
2655: {
2656: rta = (struct rtattr*)(chunk.ptr + RTA_ALIGN(chunk.len));
2657: rta->rta_type = RTAX_ADVMSS;
2658: rta->rta_len = RTA_LENGTH(sizeof(uint32_t));
2659: memcpy(RTA_DATA(rta), &this->mss, sizeof(uint32_t));
2660: chunk.len = RTA_ALIGN(chunk.len) + rta->rta_len;
2661: }
2662: netlink_add_attribute(hdr, RTA_METRICS, chunk, sizeof(request));
2663: }
2664: }
2665: return this->socket->send_ack(this->socket, hdr);
2666: }
2667:
2668: /**
2669: * Helper struct used to check routes
2670: */
2671: typedef struct {
2672: /** the entry we look for */
2673: route_entry_t route;
2674: /** kernel interface */
2675: private_kernel_netlink_net_t *this;
2676: } route_entry_lookup_t;
2677:
2678: /**
2679: * Check if a matching route entry has a VIP associated
2680: */
2681: static bool route_with_vip(route_entry_lookup_t *a, route_entry_t *b)
2682: {
2683: if (chunk_equals(a->route.dst_net, b->dst_net) &&
2684: a->route.prefixlen == b->prefixlen &&
2685: is_known_vip(a->this, b->src_ip))
2686: {
2687: return TRUE;
2688: }
2689: return FALSE;
2690: }
2691:
2692: /**
2693: * Check if there is any route entry with a matching destination
2694: */
2695: static bool route_with_dst(route_entry_lookup_t *a, route_entry_t *b)
2696: {
2697: if (chunk_equals(a->route.dst_net, b->dst_net) &&
2698: a->route.prefixlen == b->prefixlen)
2699: {
2700: return TRUE;
2701: }
2702: return FALSE;
2703: }
2704:
2705: METHOD(kernel_net_t, add_route, status_t,
2706: private_kernel_netlink_net_t *this, chunk_t dst_net, uint8_t prefixlen,
2707: host_t *gateway, host_t *src_ip, char *if_name, bool pass)
2708: {
2709: status_t status;
2710: route_entry_t *found;
2711: route_entry_lookup_t lookup = {
2712: .route = {
2713: .dst_net = dst_net,
2714: .prefixlen = prefixlen,
2715: .gateway = gateway,
2716: .src_ip = src_ip,
2717: .if_name = if_name,
2718: .pass = pass,
2719: },
2720: .this = this,
2721: };
2722:
2723: if (!this->routing_table)
2724: { /* treat these as regular routes if installing in the main table */
2725: pass = lookup.route.pass = FALSE;
2726: }
2727:
2728: this->routes_lock->lock(this->routes_lock);
2729: found = this->routes->get(this->routes, &lookup.route);
2730: if (found)
2731: {
2732: this->routes_lock->unlock(this->routes_lock);
2733: return ALREADY_DONE;
2734: }
2735:
2736: /* don't replace the route if we already have one with a VIP installed,
2737: * but keep track of it in case that other route is uninstalled */
2738: this->lock->read_lock(this->lock);
2739: if (!is_known_vip(this, src_ip))
2740: {
2741: found = this->routes->get_match(this->routes, &lookup,
2742: (void*)route_with_vip);
2743: }
2744: this->lock->unlock(this->lock);
2745: if (found)
2746: {
2747: status = SUCCESS;
2748: }
2749: else
2750: {
2751: status = manage_srcroute(this, RTM_NEWROUTE, NLM_F_CREATE|NLM_F_REPLACE,
2752: dst_net, prefixlen, gateway, src_ip, if_name,
2753: pass);
2754: }
2755: if (status == SUCCESS)
2756: {
2757: found = route_entry_clone(&lookup.route);
2758: this->routes->put(this->routes, found, found);
2759: }
2760: this->routes_lock->unlock(this->routes_lock);
2761: return status;
2762: }
2763:
2764: METHOD(kernel_net_t, del_route, status_t,
2765: private_kernel_netlink_net_t *this, chunk_t dst_net, uint8_t prefixlen,
2766: host_t *gateway, host_t *src_ip, char *if_name, bool pass)
2767: {
2768: status_t status;
2769: route_entry_t *found;
2770: route_entry_lookup_t lookup = {
2771: .route = {
2772: .dst_net = dst_net,
2773: .prefixlen = prefixlen,
2774: .gateway = gateway,
2775: .src_ip = src_ip,
2776: .if_name = if_name,
2777: .pass = pass,
2778: },
2779: .this = this,
2780: };
2781:
2782: if (!this->routing_table)
2783: { /* treat these as regular routes if installing in the main table */
2784: pass = lookup.route.pass = FALSE;
2785: }
2786:
2787: this->routes_lock->lock(this->routes_lock);
2788: found = this->routes->remove(this->routes, &lookup.route);
2789: if (!found)
2790: {
2791: this->routes_lock->unlock(this->routes_lock);
2792: return NOT_FOUND;
2793: }
2794: route_entry_destroy(found);
2795:
2796: /* check if there are any other routes for the same destination and if
2797: * so update the route, otherwise uninstall it */
2798: this->lock->read_lock(this->lock);
2799: found = this->routes->get_match(this->routes, &lookup,
2800: (void*)route_with_vip);
2801: this->lock->unlock(this->lock);
2802: if (!found)
2803: {
2804: found = this->routes->get_match(this->routes, &lookup,
2805: (void*)route_with_dst);
2806: }
2807: if (found)
2808: {
2809: status = manage_srcroute(this, RTM_NEWROUTE, NLM_F_CREATE|NLM_F_REPLACE,
2810: found->dst_net, found->prefixlen, found->gateway,
2811: found->src_ip, found->if_name, found->pass);
2812: }
2813: else
2814: {
2815: status = manage_srcroute(this, RTM_DELROUTE, 0, dst_net, prefixlen,
2816: gateway, src_ip, if_name, pass);
2817: }
2818: this->routes_lock->unlock(this->routes_lock);
2819: return status;
2820: }
2821:
2822: /**
2823: * Initialize a list of local addresses.
2824: */
2825: static status_t init_address_list(private_kernel_netlink_net_t *this)
2826: {
2827: netlink_buf_t request;
2828: struct nlmsghdr *out, *current, *in;
2829: struct rtgenmsg *msg;
2830: size_t len;
2831: enumerator_t *ifaces, *addrs;
2832: iface_entry_t *iface;
2833: addr_entry_t *addr;
2834:
2835: DBG2(DBG_KNL, "known interfaces and IP addresses:");
2836:
2837: memset(&request, 0, sizeof(request));
2838:
2839: in = &request.hdr;
2840: in->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
2841: in->nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH | NLM_F_ROOT;
2842: msg = NLMSG_DATA(in);
2843: msg->rtgen_family = AF_UNSPEC;
2844:
2845: /* get all links */
2846: in->nlmsg_type = RTM_GETLINK;
2847: if (this->socket->send(this->socket, in, &out, &len) != SUCCESS)
2848: {
2849: return FAILED;
2850: }
2851: current = out;
2852: while (NLMSG_OK(current, len))
2853: {
2854: switch (current->nlmsg_type)
2855: {
2856: case NLMSG_DONE:
2857: break;
2858: case RTM_NEWLINK:
2859: process_link(this, current, FALSE);
2860: /* fall through */
2861: default:
2862: current = NLMSG_NEXT(current, len);
2863: continue;
2864: }
2865: break;
2866: }
2867: free(out);
2868:
2869: /* get all interface addresses */
2870: in->nlmsg_type = RTM_GETADDR;
2871: if (this->socket->send(this->socket, in, &out, &len) != SUCCESS)
2872: {
2873: return FAILED;
2874: }
2875: current = out;
2876: while (NLMSG_OK(current, len))
2877: {
2878: switch (current->nlmsg_type)
2879: {
2880: case NLMSG_DONE:
2881: break;
2882: case RTM_NEWADDR:
2883: process_addr(this, current, FALSE);
2884: /* fall through */
2885: default:
2886: current = NLMSG_NEXT(current, len);
2887: continue;
2888: }
2889: break;
2890: }
2891: free(out);
2892:
2893: this->lock->read_lock(this->lock);
2894: ifaces = this->ifaces->create_enumerator(this->ifaces);
2895: while (ifaces->enumerate(ifaces, &iface))
2896: {
2897: if (iface_entry_up_and_usable(iface))
2898: {
2899: DBG2(DBG_KNL, " %s", iface->ifname);
2900: addrs = iface->addrs->create_enumerator(iface->addrs);
2901: while (addrs->enumerate(addrs, (void**)&addr))
2902: {
2903: DBG2(DBG_KNL, " %H", addr->ip);
2904: }
2905: addrs->destroy(addrs);
2906: }
2907: }
2908: ifaces->destroy(ifaces);
2909: this->lock->unlock(this->lock);
2910: return SUCCESS;
2911: }
2912:
2913: /**
2914: * create or delete a rule to use our routing table
2915: */
2916: static status_t manage_rule(private_kernel_netlink_net_t *this, int nlmsg_type,
2917: int family, uint32_t table, uint32_t prio)
2918: {
2919: netlink_buf_t request;
2920: struct nlmsghdr *hdr;
2921: struct rtmsg *msg;
2922: chunk_t chunk;
2923: char *fwmark;
2924:
2925: memset(&request, 0, sizeof(request));
2926: hdr = &request.hdr;
2927: hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
2928: hdr->nlmsg_type = nlmsg_type;
2929: if (nlmsg_type == RTM_NEWRULE)
2930: {
2931: hdr->nlmsg_flags |= NLM_F_CREATE | NLM_F_EXCL;
2932: }
2933: hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
2934:
2935: msg = NLMSG_DATA(hdr);
2936: msg->rtm_family = family;
2937: msg->rtm_protocol = RTPROT_BOOT;
2938: msg->rtm_scope = RT_SCOPE_UNIVERSE;
2939: msg->rtm_type = RTN_UNICAST;
2940:
2941: if (this->routing_table < 256)
2942: {
2943: msg->rtm_table = table;
2944: }
2945: else
2946: {
2947: #ifdef HAVE_LINUX_FIB_RULES_H
2948: chunk = chunk_from_thing(table);
2949: netlink_add_attribute(hdr, FRA_TABLE, chunk, sizeof(request));
2950: #else
2951: DBG1(DBG_KNL, "routing table IDs > 255 are not supported");
2952: return FAILED;
2953: #endif /* HAVE_LINUX_FIB_RULES_H */
2954: }
2955: chunk = chunk_from_thing(prio);
2956: netlink_add_attribute(hdr, RTA_PRIORITY, chunk, sizeof(request));
2957:
2958: fwmark = lib->settings->get_str(lib->settings,
2959: "%s.plugins.kernel-netlink.fwmark", NULL, lib->ns);
2960: if (fwmark)
2961: {
2962: #ifdef HAVE_LINUX_FIB_RULES_H
2963: mark_t mark;
2964:
2965: if (fwmark[0] == '!')
2966: {
2967: msg->rtm_flags |= FIB_RULE_INVERT;
2968: fwmark++;
2969: }
2970: if (mark_from_string(fwmark, MARK_OP_NONE, &mark))
2971: {
2972: chunk = chunk_from_thing(mark.value);
2973: netlink_add_attribute(hdr, FRA_FWMARK, chunk, sizeof(request));
2974: chunk = chunk_from_thing(mark.mask);
2975: netlink_add_attribute(hdr, FRA_FWMASK, chunk, sizeof(request));
2976: if (msg->rtm_flags & FIB_RULE_INVERT)
2977: {
2978: this->routing_mark = mark;
2979: }
2980: }
2981: #else
2982: DBG1(DBG_KNL, "setting firewall mark on routing rule is not supported");
2983: #endif /* HAVE_LINUX_FIB_RULES_H */
2984: }
2985: return this->socket->send_ack(this->socket, hdr);
2986: }
2987:
2988: /**
2989: * check for kernel features (currently only via version number)
2990: */
2991: static void check_kernel_features(private_kernel_netlink_net_t *this)
2992: {
2993: struct utsname utsname;
2994: int a, b, c;
2995:
2996: if (uname(&utsname) == 0)
2997: {
2998: switch(sscanf(utsname.release, "%d.%d.%d", &a, &b, &c))
2999: {
3000: case 3:
3001: if (a == 2)
3002: {
3003: if (b == 6 && c >= 36)
3004: {
3005: this->rta_mark = TRUE;
3006: }
3007: DBG2(DBG_KNL, "detected Linux %d.%d.%d, no support for "
3008: "RTA_PREFSRC for IPv6 routes", a, b, c);
3009: break;
3010: }
3011: /* fall-through */
3012: case 2:
3013: /* only 3.x+ uses two part version numbers */
3014: this->rta_prefsrc_for_ipv6 = TRUE;
3015: this->rta_mark = TRUE;
3016: break;
3017: default:
3018: break;
3019: }
3020: }
3021: }
3022:
3023: /**
3024: * Destroy an address to iface map
3025: */
3026: static void addr_map_destroy(hashtable_t *map)
3027: {
3028: enumerator_t *enumerator;
3029: addr_map_entry_t *addr;
3030:
3031: enumerator = map->create_enumerator(map);
3032: while (enumerator->enumerate(enumerator, NULL, (void**)&addr))
3033: {
3034: free(addr);
3035: }
3036: enumerator->destroy(enumerator);
3037: map->destroy(map);
3038: }
3039:
3040: METHOD(kernel_net_t, destroy, void,
3041: private_kernel_netlink_net_t *this)
3042: {
3043: enumerator_t *enumerator;
3044: route_entry_t *route;
3045:
3046: if (this->routing_table)
3047: {
3048: manage_rule(this, RTM_DELRULE, AF_INET, this->routing_table,
3049: this->routing_table_prio);
3050: manage_rule(this, RTM_DELRULE, AF_INET6, this->routing_table,
3051: this->routing_table_prio);
3052: }
3053: if (this->socket_events > 0)
3054: {
3055: lib->watcher->remove(lib->watcher, this->socket_events);
3056: close(this->socket_events);
3057: }
3058: enumerator = this->routes->create_enumerator(this->routes);
3059: while (enumerator->enumerate(enumerator, NULL, (void**)&route))
3060: {
3061: manage_srcroute(this, RTM_DELROUTE, 0, route->dst_net, route->prefixlen,
3062: route->gateway, route->src_ip, route->if_name,
3063: route->pass);
3064: route_entry_destroy(route);
3065: }
3066: enumerator->destroy(enumerator);
3067: this->routes->destroy(this->routes);
3068: this->routes_lock->destroy(this->routes_lock);
3069: DESTROY_IF(this->socket);
3070:
3071: net_changes_clear(this);
3072: this->net_changes->destroy(this->net_changes);
3073: this->net_changes_lock->destroy(this->net_changes_lock);
3074:
3075: addr_map_destroy(this->addrs);
3076: addr_map_destroy(this->vips);
3077:
3078: this->ifaces->destroy_function(this->ifaces, (void*)iface_entry_destroy);
3079: this->rt_exclude->destroy(this->rt_exclude);
3080: this->roam_lock->destroy(this->roam_lock);
3081: this->condvar->destroy(this->condvar);
3082: this->lock->destroy(this->lock);
3083: free(this);
3084: }
3085:
3086: /*
3087: * Described in header.
3088: */
3089: kernel_netlink_net_t *kernel_netlink_net_create()
3090: {
3091: private_kernel_netlink_net_t *this;
3092: enumerator_t *enumerator;
3093: bool register_for_events = TRUE;
3094: char *exclude;
3095:
3096: INIT(this,
3097: .public = {
3098: .interface = {
3099: .get_interface = _get_interface_name,
3100: .create_address_enumerator = _create_address_enumerator,
3101: .create_local_subnet_enumerator = _create_local_subnet_enumerator,
3102: .get_source_addr = _get_source_addr,
3103: .get_nexthop = _get_nexthop,
3104: .add_ip = _add_ip,
3105: .del_ip = _del_ip,
3106: .add_route = _add_route,
3107: .del_route = _del_route,
3108: .destroy = _destroy,
3109: },
3110: },
3111: .socket = netlink_socket_create(NETLINK_ROUTE, rt_msg_names,
3112: lib->settings->get_bool(lib->settings,
3113: "%s.plugins.kernel-netlink.parallel_route", FALSE, lib->ns)),
3114: .rt_exclude = linked_list_create(),
3115: .routes = hashtable_create((hashtable_hash_t)route_entry_hash,
3116: (hashtable_equals_t)route_entry_equals, 16),
3117: .net_changes = hashtable_create(
3118: (hashtable_hash_t)net_change_hash,
3119: (hashtable_equals_t)net_change_equals, 16),
3120: .addrs = hashtable_create(
3121: (hashtable_hash_t)addr_map_entry_hash,
3122: (hashtable_equals_t)addr_map_entry_equals, 16),
3123: .vips = hashtable_create((hashtable_hash_t)addr_map_entry_hash,
3124: (hashtable_equals_t)addr_map_entry_equals, 16),
3125: .routes_lock = mutex_create(MUTEX_TYPE_DEFAULT),
3126: .net_changes_lock = mutex_create(MUTEX_TYPE_DEFAULT),
3127: .ifaces = linked_list_create(),
3128: .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
3129: .condvar = rwlock_condvar_create(),
3130: .roam_lock = spinlock_create(),
3131: .routing_table = lib->settings->get_int(lib->settings,
3132: "%s.routing_table", ROUTING_TABLE, lib->ns),
3133: .routing_table_prio = lib->settings->get_int(lib->settings,
3134: "%s.routing_table_prio", ROUTING_TABLE_PRIO, lib->ns),
3135: .process_route = lib->settings->get_bool(lib->settings,
3136: "%s.process_route", TRUE, lib->ns),
3137: .install_routes = lib->settings->get_bool(lib->settings,
3138: "%s.install_routes", TRUE, lib->ns),
3139: .install_virtual_ip = lib->settings->get_bool(lib->settings,
3140: "%s.install_virtual_ip", TRUE, lib->ns),
3141: .install_virtual_ip_on = lib->settings->get_str(lib->settings,
3142: "%s.install_virtual_ip_on", NULL, lib->ns),
3143: .prefer_temporary_addrs = lib->settings->get_bool(lib->settings,
3144: "%s.prefer_temporary_addrs", FALSE, lib->ns),
3145: .roam_events = lib->settings->get_bool(lib->settings,
3146: "%s.plugins.kernel-netlink.roam_events", TRUE, lib->ns),
3147: .process_rules = lib->settings->get_bool(lib->settings,
3148: "%s.plugins.kernel-netlink.process_rules", FALSE, lib->ns),
3149: .mtu = lib->settings->get_int(lib->settings,
3150: "%s.plugins.kernel-netlink.mtu", 0, lib->ns),
3151: .mss = lib->settings->get_int(lib->settings,
3152: "%s.plugins.kernel-netlink.mss", 0, lib->ns),
3153: );
3154: timerclear(&this->last_route_reinstall);
3155: timerclear(&this->next_roam);
3156:
3157: check_kernel_features(this);
3158:
3159: if (streq(lib->ns, "starter"))
3160: { /* starter has no threads, so we do not register for kernel events */
3161: register_for_events = FALSE;
3162: }
3163:
3164: exclude = lib->settings->get_str(lib->settings,
3165: "%s.ignore_routing_tables", NULL, lib->ns);
3166: if (exclude)
3167: {
3168: char *token;
3169: uintptr_t table;
3170:
3171: enumerator = enumerator_create_token(exclude, " ", " ");
3172: while (enumerator->enumerate(enumerator, &token))
3173: {
3174: errno = 0;
3175: table = strtoul(token, NULL, 10);
3176:
3177: if (errno == 0)
3178: {
3179: this->rt_exclude->insert_last(this->rt_exclude, (void*)table);
3180: }
3181: }
3182: enumerator->destroy(enumerator);
3183: }
3184:
3185: if (register_for_events)
3186: {
3187: struct sockaddr_nl addr;
3188:
3189: memset(&addr, 0, sizeof(addr));
3190: addr.nl_family = AF_NETLINK;
3191:
3192: /* create and bind RT socket for events (address/interface/route changes) */
3193: this->socket_events = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
3194: if (this->socket_events < 0)
3195: {
3196: DBG1(DBG_KNL, "unable to create RT event socket: %s (%d)",
3197: strerror(errno), errno);
3198: destroy(this);
3199: return NULL;
3200: }
3201: addr.nl_groups = nl_group(RTNLGRP_IPV4_IFADDR) |
3202: nl_group(RTNLGRP_IPV6_IFADDR) |
3203: nl_group(RTNLGRP_LINK);
3204: if (this->process_route)
3205: {
3206: addr.nl_groups |= nl_group(RTNLGRP_IPV4_ROUTE) |
3207: nl_group(RTNLGRP_IPV6_ROUTE);
3208: }
3209: if (this->process_rules)
3210: {
3211: addr.nl_groups |= nl_group(RTNLGRP_IPV4_RULE) |
3212: nl_group(RTNLGRP_IPV6_RULE);
3213: }
3214: if (bind(this->socket_events, (struct sockaddr*)&addr, sizeof(addr)))
3215: {
3216: DBG1(DBG_KNL, "unable to bind RT event socket: %s (%d)",
3217: strerror(errno), errno);
3218: destroy(this);
3219: return NULL;
3220: }
3221:
3222: lib->watcher->add(lib->watcher, this->socket_events, WATCHER_READ,
3223: (watcher_cb_t)receive_events, this);
3224: }
3225:
3226: if (init_address_list(this) != SUCCESS)
3227: {
3228: DBG1(DBG_KNL, "unable to get interface list");
3229: destroy(this);
3230: return NULL;
3231: }
3232:
3233: if (this->routing_table)
3234: {
3235: if (manage_rule(this, RTM_NEWRULE, AF_INET, this->routing_table,
3236: this->routing_table_prio) != SUCCESS)
3237: {
3238: DBG1(DBG_KNL, "unable to create IPv4 routing table rule");
3239: }
3240: if (manage_rule(this, RTM_NEWRULE, AF_INET6, this->routing_table,
3241: this->routing_table_prio) != SUCCESS)
3242: {
3243: DBG1(DBG_KNL, "unable to create IPv6 routing table rule");
3244: }
3245: }
3246:
3247: return &this->public;
3248: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>