Annotation of embedaddon/strongswan/src/libcharon/plugins/kernel_pfroute/kernel_pfroute_net.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2009-2016 Tobias Brunner
3: * HSR Hochschule fuer Technik Rapperswil
4: *
5: * This program is free software; you can redistribute it and/or modify it
6: * under the terms of the GNU General Public License as published by the
7: * Free Software Foundation; either version 2 of the License, or (at your
8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9: *
10: * This program is distributed in the hope that it will be useful, but
11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13: * for more details.
14: */
15:
16: #include <sys/types.h>
17: #include <sys/socket.h>
18: #include <sys/sysctl.h>
19: #include <net/if.h>
20: #include <net/if_dl.h>
21: #include <ifaddrs.h>
22: #include <net/route.h>
23: #include <unistd.h>
24: #include <errno.h>
25:
26: #include "kernel_pfroute_net.h"
27:
28: #include <daemon.h>
29: #include <utils/debug.h>
30: #include <networking/host.h>
31: #include <networking/tun_device.h>
32: #include <threading/thread.h>
33: #include <threading/mutex.h>
34: #include <threading/condvar.h>
35: #include <threading/rwlock.h>
36: #include <threading/spinlock.h>
37: #include <collections/hashtable.h>
38: #include <collections/linked_list.h>
39: #include <processing/jobs/callback_job.h>
40:
41: #ifndef HAVE_STRUCT_SOCKADDR_SA_LEN
42: #error Cannot compile this plugin on systems where 'struct sockaddr' has no sa_len member.
43: #endif
44:
45: /** properly align sockaddrs */
46: #ifdef __APPLE__
47: /* Apple always uses 4 bytes */
48: #define SA_ALIGN 4
49: #else
50: /* while on other platforms like FreeBSD it depends on the architecture */
51: #define SA_ALIGN sizeof(long)
52: #endif
53: #define SA_LEN(len) ((len) > 0 ? (((len)+SA_ALIGN-1) & ~(SA_ALIGN-1)) : SA_ALIGN)
54:
55: /** delay before firing roam events (ms) */
56: #define ROAM_DELAY 100
57:
58: /** delay before reinstalling routes (ms) */
59: #define ROUTE_DELAY 100
60:
61: typedef struct addr_entry_t addr_entry_t;
62:
63: /**
64: * IP address in an inface_entry_t
65: */
66: struct addr_entry_t {
67:
68: /** The ip address */
69: host_t *ip;
70:
71: /** virtual IP managed by us */
72: bool virtual;
73: };
74:
75: /**
76: * destroy a addr_entry_t object
77: */
78: static void addr_entry_destroy(addr_entry_t *this)
79: {
80: this->ip->destroy(this->ip);
81: free(this);
82: }
83:
84: typedef struct iface_entry_t iface_entry_t;
85:
86: /**
87: * A network interface on this system, containing addr_entry_t's
88: */
89: struct iface_entry_t {
90:
91: /** interface index */
92: int ifindex;
93:
94: /** name of the interface */
95: char ifname[IFNAMSIZ];
96:
97: /** interface flags, as in netdevice(7) SIOCGIFFLAGS */
98: u_int flags;
99:
100: /** list of addresses as host_t */
101: linked_list_t *addrs;
102:
103: /** TRUE if usable by config */
104: bool usable;
105: };
106:
107: /**
108: * destroy an interface entry
109: */
110: static void iface_entry_destroy(iface_entry_t *this)
111: {
112: this->addrs->destroy_function(this->addrs, (void*)addr_entry_destroy);
113: free(this);
114: }
115:
116: /**
117: * check if an interface is up
118: */
119: static inline bool iface_entry_up(iface_entry_t *iface)
120: {
121: return (iface->flags & IFF_UP) == IFF_UP;
122: }
123:
124: /**
125: * check if an interface is up and usable
126: */
127: static inline bool iface_entry_up_and_usable(iface_entry_t *iface)
128: {
129: return iface->usable && iface_entry_up(iface);
130: }
131:
132: typedef struct addr_map_entry_t addr_map_entry_t;
133:
134: /**
135: * Entry that maps an IP address to an interface entry
136: */
137: struct addr_map_entry_t {
138: /** The IP address */
139: host_t *ip;
140:
141: /** The address entry for this IP address */
142: addr_entry_t *addr;
143:
144: /** The interface this address is installed on */
145: iface_entry_t *iface;
146: };
147:
148: /**
149: * Hash a addr_map_entry_t object, all entries with the same IP address
150: * are stored in the same bucket
151: */
152: static u_int addr_map_entry_hash(addr_map_entry_t *this)
153: {
154: return chunk_hash(this->ip->get_address(this->ip));
155: }
156:
157: /**
158: * Compare two addr_map_entry_t objects, two entries are equal if they are
159: * installed on the same interface
160: */
161: static bool addr_map_entry_equals(addr_map_entry_t *a, addr_map_entry_t *b)
162: {
163: return a->iface->ifindex == b->iface->ifindex &&
164: a->ip->ip_equals(a->ip, b->ip);
165: }
166:
167: /**
168: * Used with get_match this finds an address entry if it is installed on
169: * an up and usable interface
170: */
171: static bool addr_map_entry_match_up_and_usable(addr_map_entry_t *a,
172: addr_map_entry_t *b)
173: {
174: return !b->addr->virtual && iface_entry_up_and_usable(b->iface) &&
175: a->ip->ip_equals(a->ip, b->ip);
176: }
177:
178: /**
179: * Used with get_match this finds an address entry if it is installed as virtual
180: * IP address
181: */
182: static bool addr_map_entry_match_virtual(addr_map_entry_t *a, addr_map_entry_t *b)
183: {
184: return b->addr->virtual && a->ip->ip_equals(a->ip, b->ip);
185: }
186:
187: /**
188: * Used with get_match this finds an address entry if it is installed on
189: * any active local interface
190: */
191: static bool addr_map_entry_match_up(addr_map_entry_t *a, addr_map_entry_t *b)
192: {
193: return !b->addr->virtual && iface_entry_up(b->iface) &&
194: a->ip->ip_equals(a->ip, b->ip);
195: }
196:
197: typedef struct route_entry_t route_entry_t;
198:
199: /**
200: * Installed routing entry
201: */
202: struct route_entry_t {
203: /** Name of the interface the route is bound to */
204: char *if_name;
205:
206: /** Gateway for this route */
207: host_t *gateway;
208:
209: /** Destination net */
210: chunk_t dst_net;
211:
212: /** Destination net prefixlen */
213: uint8_t prefixlen;
214: };
215:
216: /**
217: * Clone a route_entry_t object.
218: */
219: static route_entry_t *route_entry_clone(route_entry_t *this)
220: {
221: route_entry_t *route;
222:
223: INIT(route,
224: .if_name = strdup(this->if_name),
225: .gateway = this->gateway ? this->gateway->clone(this->gateway) : NULL,
226: .dst_net = chunk_clone(this->dst_net),
227: .prefixlen = this->prefixlen,
228: );
229: return route;
230: }
231:
232: /**
233: * Destroy a route_entry_t object
234: */
235: static void route_entry_destroy(route_entry_t *this)
236: {
237: free(this->if_name);
238: DESTROY_IF(this->gateway);
239: chunk_free(&this->dst_net);
240: free(this);
241: }
242:
243: /**
244: * Hash a route_entry_t object
245: */
246: static u_int route_entry_hash(route_entry_t *this)
247: {
248: return chunk_hash_inc(chunk_from_thing(this->prefixlen),
249: chunk_hash(this->dst_net));
250: }
251:
252: /**
253: * Compare two route_entry_t objects
254: */
255: static bool route_entry_equals(route_entry_t *a, route_entry_t *b)
256: {
257: if (a->if_name && b->if_name && streq(a->if_name, b->if_name) &&
258: chunk_equals(a->dst_net, b->dst_net) && a->prefixlen == b->prefixlen)
259: {
260: return (!a->gateway && !b->gateway) || (a->gateway && b->gateway &&
261: a->gateway->ip_equals(a->gateway, b->gateway));
262: }
263: return FALSE;
264: }
265:
266: typedef struct net_change_t net_change_t;
267:
268: /**
269: * Queued network changes
270: */
271: struct net_change_t {
272: /** Name of the interface that got activated (or an IP appeared on) */
273: char *if_name;
274: };
275:
276: /**
277: * Destroy a net_change_t object
278: */
279: static void net_change_destroy(net_change_t *this)
280: {
281: free(this->if_name);
282: free(this);
283: }
284:
285: /**
286: * Hash a net_change_t object
287: */
288: static u_int net_change_hash(net_change_t *this)
289: {
290: return chunk_hash(chunk_create(this->if_name, strlen(this->if_name)));
291: }
292:
293: /**
294: * Compare two net_change_t objects
295: */
296: static bool net_change_equals(net_change_t *a, net_change_t *b)
297: {
298: return streq(a->if_name, b->if_name);
299: }
300:
301: typedef struct private_kernel_pfroute_net_t private_kernel_pfroute_net_t;
302:
303: /**
304: * Private variables and functions of kernel_pfroute class.
305: */
306: struct private_kernel_pfroute_net_t
307: {
308: /**
309: * Public part of the kernel_pfroute_t object.
310: */
311: kernel_pfroute_net_t public;
312:
313: /**
314: * lock to access lists and maps
315: */
316: rwlock_t *lock;
317:
318: /**
319: * Cached list of interfaces and their addresses (iface_entry_t)
320: */
321: linked_list_t *ifaces;
322:
323: /**
324: * Map for IP addresses to iface_entry_t objects (addr_map_entry_t)
325: */
326: hashtable_t *addrs;
327:
328: /**
329: * List of tun devices we installed for virtual IPs
330: */
331: linked_list_t *tuns;
332:
333: /**
334: * mutex to communicate exclusively with PF_KEY
335: */
336: mutex_t *mutex;
337:
338: /**
339: * condvar to signal if PF_KEY query got a response
340: */
341: condvar_t *condvar;
342:
343: /**
344: * installed routes
345: */
346: hashtable_t *routes;
347:
348: /**
349: * mutex for routes
350: */
351: mutex_t *routes_lock;
352:
353: /**
354: * interface changes which may trigger route reinstallation
355: */
356: hashtable_t *net_changes;
357:
358: /**
359: * mutex for route reinstallation triggers
360: */
361: mutex_t *net_changes_lock;
362:
363: /**
364: * time of last route reinstallation
365: */
366: timeval_t last_route_reinstall;
367:
368: /**
369: * pid to send PF_ROUTE messages with
370: */
371: pid_t pid;
372:
373: /**
374: * PF_ROUTE socket to communicate with the kernel
375: */
376: int socket;
377:
378: /**
379: * sequence number for messages sent to the kernel
380: */
381: int seq;
382:
383: /**
384: * Sequence number a query is waiting for
385: */
386: int waiting_seq;
387:
388: /**
389: * Allocated reply message from kernel
390: */
391: struct rt_msghdr *reply;
392:
393: /**
394: * earliest time of the next roam event
395: */
396: timeval_t next_roam;
397:
398: /**
399: * roam event due to address change
400: */
401: bool roam_address;
402:
403: /**
404: * lock to check and update roam event time
405: */
406: spinlock_t *roam_lock;
407:
408: /**
409: * Time in ms to wait for IP addresses to appear/disappear
410: */
411: int vip_wait;
412:
413: /**
414: * whether to actually install virtual IPs
415: */
416: bool install_virtual_ip;
417: };
418:
419:
420: /**
421: * Forward declaration
422: */
423: static status_t manage_route(private_kernel_pfroute_net_t *this, int op,
424: chunk_t dst_net, uint8_t prefixlen,
425: host_t *gateway, char *if_name);
426:
427: /**
428: * Clear the queued network changes.
429: */
430: static void net_changes_clear(private_kernel_pfroute_net_t *this)
431: {
432: enumerator_t *enumerator;
433: net_change_t *change;
434:
435: enumerator = this->net_changes->create_enumerator(this->net_changes);
436: while (enumerator->enumerate(enumerator, NULL, (void**)&change))
437: {
438: this->net_changes->remove_at(this->net_changes, enumerator);
439: net_change_destroy(change);
440: }
441: enumerator->destroy(enumerator);
442: }
443:
444: /**
445: * Act upon queued network changes.
446: */
447: static job_requeue_t reinstall_routes(private_kernel_pfroute_net_t *this)
448: {
449: enumerator_t *enumerator;
450: route_entry_t *route;
451:
452: this->net_changes_lock->lock(this->net_changes_lock);
453: this->routes_lock->lock(this->routes_lock);
454:
455: enumerator = this->routes->create_enumerator(this->routes);
456: while (enumerator->enumerate(enumerator, NULL, (void**)&route))
457: {
458: net_change_t *change, lookup = {
459: .if_name = route->if_name,
460: };
461: /* check if a change for the outgoing interface is queued */
462: change = this->net_changes->get(this->net_changes, &lookup);
463: if (change)
464: {
465: manage_route(this, RTM_ADD, route->dst_net, route->prefixlen,
466: route->gateway, route->if_name);
467: }
468: }
469: enumerator->destroy(enumerator);
470: this->routes_lock->unlock(this->routes_lock);
471:
472: net_changes_clear(this);
473: this->net_changes_lock->unlock(this->net_changes_lock);
474: return JOB_REQUEUE_NONE;
475: }
476:
477: /**
478: * Queue route reinstallation caused by network changes for a given interface.
479: *
480: * The route reinstallation is delayed for a while and only done once for
481: * several calls during this delay, in order to avoid doing it too often.
482: * The interface name is freed.
483: */
484: static void queue_route_reinstall(private_kernel_pfroute_net_t *this,
485: char *if_name)
486: {
487: net_change_t *update, *found;
488: timeval_t now;
489: job_t *job;
490:
491: INIT(update,
492: .if_name = if_name
493: );
494:
495: this->net_changes_lock->lock(this->net_changes_lock);
496: found = this->net_changes->put(this->net_changes, update, update);
497: if (found)
498: {
499: net_change_destroy(found);
500: }
501: time_monotonic(&now);
502: if (timercmp(&now, &this->last_route_reinstall, >))
503: {
504: timeval_add_ms(&now, ROUTE_DELAY);
505: this->last_route_reinstall = now;
506:
507: job = (job_t*)callback_job_create((callback_job_cb_t)reinstall_routes,
508: this, NULL, NULL);
509: lib->scheduler->schedule_job_ms(lib->scheduler, job, ROUTE_DELAY);
510: }
511: this->net_changes_lock->unlock(this->net_changes_lock);
512: }
513:
514: /**
515: * Add an address map entry
516: */
517: static void addr_map_entry_add(private_kernel_pfroute_net_t *this,
518: addr_entry_t *addr, iface_entry_t *iface)
519: {
520: addr_map_entry_t *entry;
521:
522: INIT(entry,
523: .ip = addr->ip,
524: .addr = addr,
525: .iface = iface,
526: );
527: entry = this->addrs->put(this->addrs, entry, entry);
528: free(entry);
529: }
530:
531: /**
532: * Remove an address map entry (the argument order is a bit strange because
533: * it is also used with linked_list_t.invoke_function)
534: */
535: static void addr_map_entry_remove(addr_entry_t *addr, iface_entry_t *iface,
536: private_kernel_pfroute_net_t *this)
537: {
538: addr_map_entry_t *entry, lookup = {
539: .ip = addr->ip,
540: .addr = addr,
541: .iface = iface,
542: };
543:
544: entry = this->addrs->remove(this->addrs, &lookup);
545: free(entry);
546: }
547:
548: /**
549: * callback function that raises the delayed roam event
550: */
551: static job_requeue_t roam_event(private_kernel_pfroute_net_t *this)
552: {
553: bool address;
554:
555: this->roam_lock->lock(this->roam_lock);
556: address = this->roam_address;
557: this->roam_address = FALSE;
558: this->roam_lock->unlock(this->roam_lock);
559: charon->kernel->roam(charon->kernel, address);
560: return JOB_REQUEUE_NONE;
561: }
562:
563: /**
564: * fire a roaming event. we delay it for a bit and fire only one event
565: * for multiple calls. otherwise we would create too many events.
566: */
567: static void fire_roam_event(private_kernel_pfroute_net_t *this, bool address)
568: {
569: timeval_t now;
570: job_t *job;
571:
572: time_monotonic(&now);
573: this->roam_lock->lock(this->roam_lock);
574: this->roam_address |= address;
575: if (!timercmp(&now, &this->next_roam, >))
576: {
577: this->roam_lock->unlock(this->roam_lock);
578: return;
579: }
580: timeval_add_ms(&now, ROAM_DELAY);
581: this->next_roam = now;
582: this->roam_lock->unlock(this->roam_lock);
583:
584: job = (job_t*)callback_job_create((callback_job_cb_t)roam_event,
585: this, NULL, NULL);
586: lib->scheduler->schedule_job_ms(lib->scheduler, job, ROAM_DELAY);
587: }
588:
589: /**
590: * Data for enumerator over rtmsg sockaddrs
591: */
592: typedef struct {
593: /** implements enumerator */
594: enumerator_t public;
595: /** copy of attribute bitfield */
596: int types;
597: /** bytes remaining in buffer */
598: int remaining;
599: /** next sockaddr to enumerate */
600: struct sockaddr *addr;
601: } rt_enumerator_t;
602:
603: METHOD(enumerator_t, rt_enumerate, bool,
604: rt_enumerator_t *this, va_list args)
605: {
606: struct sockaddr **addr;
607: int i, type, *xtype;
608:
609: VA_ARGS_VGET(args, xtype, addr);
610:
611: if (this->remaining < sizeof(this->addr->sa_len) ||
612: this->remaining < this->addr->sa_len)
613: {
614: return FALSE;
615: }
616: for (i = 0; i < RTAX_MAX; i++)
617: {
618: type = (1 << i);
619: if (this->types & type)
620: {
621: this->types &= ~type;
622: *addr = this->addr;
623: *xtype = i;
624: this->remaining -= SA_LEN(this->addr->sa_len);
625: this->addr = (struct sockaddr*)((char*)this->addr +
626: SA_LEN(this->addr->sa_len));
627: return TRUE;
628: }
629: }
630: return FALSE;
631: }
632:
633: /**
634: * Create an enumerator over sockaddrs in rt/if messages
635: */
636: static enumerator_t *create_rt_enumerator(int types, int remaining,
637: struct sockaddr *addr)
638: {
639: rt_enumerator_t *this;
640:
641: INIT(this,
642: .public = {
643: .enumerate = enumerator_enumerate_default,
644: .venumerate = _rt_enumerate,
645: .destroy = (void*)free,
646: },
647: .types = types,
648: .remaining = remaining,
649: .addr = addr,
650: );
651: return &this->public;
652: }
653:
654: /**
655: * Create a safe enumerator over sockaddrs in rt_msghdr
656: */
657: static enumerator_t *create_rtmsg_enumerator(struct rt_msghdr *hdr)
658: {
659: return create_rt_enumerator(hdr->rtm_addrs, hdr->rtm_msglen - sizeof(*hdr),
660: (struct sockaddr *)(hdr + 1));
661: }
662:
663: /**
664: * Create a safe enumerator over sockaddrs in ifa_msghdr
665: */
666: static enumerator_t *create_ifamsg_enumerator(struct ifa_msghdr *hdr)
667: {
668: return create_rt_enumerator(hdr->ifam_addrs, hdr->ifam_msglen - sizeof(*hdr),
669: (struct sockaddr *)(hdr + 1));
670: }
671:
672: /**
673: * Process an RTM_*ADDR message from the kernel
674: */
675: static void process_addr(private_kernel_pfroute_net_t *this,
676: struct ifa_msghdr *ifa)
677: {
678: struct sockaddr *sockaddr;
679: host_t *host = NULL;
680: enumerator_t *ifaces, *addrs;
681: iface_entry_t *iface;
682: addr_entry_t *addr;
683: bool found = FALSE, changed = FALSE, roam = FALSE;
684: enumerator_t *enumerator;
685: char *ifname = NULL;
686: int type;
687:
688: enumerator = create_ifamsg_enumerator(ifa);
689: while (enumerator->enumerate(enumerator, &type, &sockaddr))
690: {
691: if (type == RTAX_IFA)
692: {
693: host = host_create_from_sockaddr(sockaddr);
694: break;
695: }
696: }
697: enumerator->destroy(enumerator);
698:
699: if (!host || host->is_anyaddr(host))
700: {
701: DESTROY_IF(host);
702: return;
703: }
704:
705: this->lock->write_lock(this->lock);
706: ifaces = this->ifaces->create_enumerator(this->ifaces);
707: while (ifaces->enumerate(ifaces, &iface))
708: {
709: if (iface->ifindex == ifa->ifam_index)
710: {
711: addrs = iface->addrs->create_enumerator(iface->addrs);
712: while (addrs->enumerate(addrs, &addr))
713: {
714: if (host->ip_equals(host, addr->ip))
715: {
716: found = TRUE;
717: if (ifa->ifam_type == RTM_DELADDR)
718: {
719: iface->addrs->remove_at(iface->addrs, addrs);
720: if (!addr->virtual && iface->usable)
721: {
722: changed = TRUE;
723: DBG1(DBG_KNL, "%H disappeared from %s",
724: host, iface->ifname);
725: }
726: addr_map_entry_remove(addr, iface, this);
727: addr_entry_destroy(addr);
728: }
729: }
730: }
731: addrs->destroy(addrs);
732:
733: if (!found && ifa->ifam_type == RTM_NEWADDR)
734: {
735: INIT(addr,
736: .ip = host->clone(host),
737: );
738: changed = TRUE;
739: ifname = strdup(iface->ifname);
740: iface->addrs->insert_last(iface->addrs, addr);
741: addr_map_entry_add(this, addr, iface);
742: if (iface->usable)
743: {
744: DBG1(DBG_KNL, "%H appeared on %s", host, iface->ifname);
745: }
746: }
747:
748: if (changed && iface_entry_up_and_usable(iface))
749: {
750: roam = TRUE;
751: }
752: break;
753: }
754: }
755: ifaces->destroy(ifaces);
756: this->lock->unlock(this->lock);
757: host->destroy(host);
758:
759: if (roam && ifname)
760: {
761: queue_route_reinstall(this, ifname);
762: }
763: else
764: {
765: free(ifname);
766: }
767:
768: if (roam)
769: {
770: fire_roam_event(this, TRUE);
771: }
772: }
773:
774: /**
775: * Re-initialize address list of an interface if it changes state
776: */
777: static void repopulate_iface(private_kernel_pfroute_net_t *this,
778: iface_entry_t *iface)
779: {
780: struct ifaddrs *ifap, *ifa;
781: addr_entry_t *addr;
782:
783: while (iface->addrs->remove_last(iface->addrs, (void**)&addr) == SUCCESS)
784: {
785: addr_map_entry_remove(addr, iface, this);
786: addr_entry_destroy(addr);
787: }
788:
789: if (getifaddrs(&ifap) == 0)
790: {
791: for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next)
792: {
793: if (ifa->ifa_addr && streq(ifa->ifa_name, iface->ifname))
794: {
795: switch (ifa->ifa_addr->sa_family)
796: {
797: case AF_INET:
798: case AF_INET6:
799: INIT(addr,
800: .ip = host_create_from_sockaddr(ifa->ifa_addr),
801: );
802: iface->addrs->insert_last(iface->addrs, addr);
803: addr_map_entry_add(this, addr, iface);
804: break;
805: default:
806: break;
807: }
808: }
809: }
810: freeifaddrs(ifap);
811: }
812: }
813:
814: /**
815: * Process an RTM_IFINFO message from the kernel
816: */
817: static void process_link(private_kernel_pfroute_net_t *this,
818: struct if_msghdr *msg)
819: {
820: enumerator_t *enumerator;
821: iface_entry_t *iface;
822: bool roam = FALSE, found = FALSE, update_routes = FALSE;
823:
824: this->lock->write_lock(this->lock);
825: enumerator = this->ifaces->create_enumerator(this->ifaces);
826: while (enumerator->enumerate(enumerator, &iface))
827: {
828: if (iface->ifindex == msg->ifm_index)
829: {
830: if (iface->usable)
831: {
832: if (!(iface->flags & IFF_UP) && (msg->ifm_flags & IFF_UP))
833: {
834: roam = update_routes = TRUE;
835: DBG1(DBG_KNL, "interface %s activated", iface->ifname);
836: }
837: else if ((iface->flags & IFF_UP) && !(msg->ifm_flags & IFF_UP))
838: {
839: roam = TRUE;
840: DBG1(DBG_KNL, "interface %s deactivated", iface->ifname);
841: }
842: }
843: #ifdef __APPLE__
844: /* There seems to be a race condition on 10.10, where we get
845: * the RTM_IFINFO, but getifaddrs() does not return the virtual
846: * IP installed on a tun device, but we also don't get a
847: * RTM_NEWADDR. We therefore could miss the new address, letting
848: * virtual IP installation fail. Delaying getifaddrs() helps,
849: * but is obviously not a clean fix. */
850: usleep(50000);
851: #endif
852: iface->flags = msg->ifm_flags;
853: repopulate_iface(this, iface);
854: found = TRUE;
855: break;
856: }
857: }
858: enumerator->destroy(enumerator);
859:
860: if (!found)
861: {
862: INIT(iface,
863: .ifindex = msg->ifm_index,
864: .flags = msg->ifm_flags,
865: .addrs = linked_list_create(),
866: );
867: #ifdef __APPLE__
868: /* Similar to the issue described above, on 10.13 we need this delay as
869: * we might otherwise not be able to convert the index to a name yet. */
870: usleep(50000);
871: #endif
872: if (if_indextoname(iface->ifindex, iface->ifname))
873: {
874: DBG1(DBG_KNL, "interface %s appeared", iface->ifname);
875: iface->usable = charon->kernel->is_interface_usable(charon->kernel,
876: iface->ifname);
877: repopulate_iface(this, iface);
878: this->ifaces->insert_last(this->ifaces, iface);
879: if (iface->usable)
880: {
881: roam = update_routes = TRUE;
882: }
883: }
884: else
885: {
886: free(iface);
887: }
888: }
889: this->lock->unlock(this->lock);
890:
891: if (update_routes)
892: {
893: queue_route_reinstall(this, strdup(iface->ifname));
894: }
895:
896: if (roam)
897: {
898: fire_roam_event(this, TRUE);
899: }
900: }
901:
902: #ifdef HAVE_RTM_IFANNOUNCE
903:
904: /**
905: * Process an RTM_IFANNOUNCE message from the kernel
906: */
907: static void process_announce(private_kernel_pfroute_net_t *this,
908: struct if_announcemsghdr *msg)
909: {
910: enumerator_t *enumerator;
911: iface_entry_t *iface;
912:
913: if (msg->ifan_what != IFAN_DEPARTURE)
914: {
915: /* we handle new interfaces in process_link() */
916: return;
917: }
918:
919: this->lock->write_lock(this->lock);
920: enumerator = this->ifaces->create_enumerator(this->ifaces);
921: while (enumerator->enumerate(enumerator, &iface))
922: {
923: if (iface->ifindex == msg->ifan_index)
924: {
925: DBG1(DBG_KNL, "interface %s disappeared", iface->ifname);
926: this->ifaces->remove_at(this->ifaces, enumerator);
927: iface_entry_destroy(iface);
928: break;
929: }
930: }
931: enumerator->destroy(enumerator);
932: this->lock->unlock(this->lock);
933: }
934:
935: #endif /* HAVE_RTM_IFANNOUNCE */
936:
937: /**
938: * Process an RTM_*ROUTE message from the kernel
939: */
940: static void process_route(private_kernel_pfroute_net_t *this,
941: struct rt_msghdr *msg)
942: {
943:
944: }
945:
946: /**
947: * Receives PF_ROUTE messages from kernel
948: */
949: static bool receive_events(private_kernel_pfroute_net_t *this, int fd,
950: watcher_event_t event)
951: {
952: struct {
953: union {
954: struct rt_msghdr rtm;
955: struct if_msghdr ifm;
956: struct ifa_msghdr ifam;
957: #ifdef HAVE_RTM_IFANNOUNCE
958: struct if_announcemsghdr ifanm;
959: #endif
960: };
961: char buf[sizeof(struct sockaddr_storage) * RTAX_MAX];
962: } msg;
963: int len, hdrlen;
964:
965: len = recv(this->socket, &msg, sizeof(msg), MSG_DONTWAIT);
966: if (len < 0)
967: {
968: switch (errno)
969: {
970: case EINTR:
971: case EAGAIN:
972: return TRUE;
973: default:
974: DBG1(DBG_KNL, "unable to receive from PF_ROUTE event socket");
975: sleep(1);
976: return TRUE;
977: }
978: }
979:
980: if (len < offsetof(struct rt_msghdr, rtm_flags) || len < msg.rtm.rtm_msglen)
981: {
982: DBG1(DBG_KNL, "received invalid PF_ROUTE message");
983: return TRUE;
984: }
985: if (msg.rtm.rtm_version != RTM_VERSION)
986: {
987: DBG1(DBG_KNL, "received PF_ROUTE message with unsupported version: %d",
988: msg.rtm.rtm_version);
989: return TRUE;
990: }
991: switch (msg.rtm.rtm_type)
992: {
993: case RTM_NEWADDR:
994: case RTM_DELADDR:
995: hdrlen = sizeof(msg.ifam);
996: break;
997: case RTM_IFINFO:
998: hdrlen = sizeof(msg.ifm);
999: break;
1000: #ifdef HAVE_RTM_IFANNOUNCE
1001: case RTM_IFANNOUNCE:
1002: hdrlen = sizeof(msg.ifanm);
1003: break;
1004: #endif /* HAVE_RTM_IFANNOUNCE */
1005: case RTM_ADD:
1006: case RTM_DELETE:
1007: case RTM_GET:
1008: hdrlen = sizeof(msg.rtm);
1009: break;
1010: default:
1011: return TRUE;
1012: }
1013: if (msg.rtm.rtm_msglen < hdrlen)
1014: {
1015: DBG1(DBG_KNL, "ignoring short PF_ROUTE message");
1016: return TRUE;
1017: }
1018: switch (msg.rtm.rtm_type)
1019: {
1020: case RTM_NEWADDR:
1021: case RTM_DELADDR:
1022: process_addr(this, &msg.ifam);
1023: break;
1024: case RTM_IFINFO:
1025: process_link(this, &msg.ifm);
1026: break;
1027: #ifdef HAVE_RTM_IFANNOUNCE
1028: case RTM_IFANNOUNCE:
1029: process_announce(this, &msg.ifanm);
1030: break;
1031: #endif /* HAVE_RTM_IFANNOUNCE */
1032: case RTM_ADD:
1033: case RTM_DELETE:
1034: process_route(this, &msg.rtm);
1035: break;
1036: default:
1037: break;
1038: }
1039:
1040: this->mutex->lock(this->mutex);
1041: if (msg.rtm.rtm_pid == this->pid && msg.rtm.rtm_seq == this->waiting_seq)
1042: {
1043: /* seems like the message someone is waiting for, deliver */
1044: this->reply = realloc(this->reply, msg.rtm.rtm_msglen);
1045: memcpy(this->reply, &msg, msg.rtm.rtm_msglen);
1046: }
1047: /* signal on any event, add_ip()/del_ip() might wait for it */
1048: this->condvar->broadcast(this->condvar);
1049: this->mutex->unlock(this->mutex);
1050:
1051: return TRUE;
1052: }
1053:
1054:
1055: /** enumerator over addresses */
1056: typedef struct {
1057: private_kernel_pfroute_net_t* this;
1058: /** which addresses to enumerate */
1059: kernel_address_type_t which;
1060: } address_enumerator_t;
1061:
1062: CALLBACK(address_enumerator_destroy, void,
1063: address_enumerator_t *data)
1064: {
1065: data->this->lock->unlock(data->this->lock);
1066: free(data);
1067: }
1068:
1069: CALLBACK(filter_addresses, bool,
1070: address_enumerator_t *data, enumerator_t *orig, va_list args)
1071: {
1072: addr_entry_t *addr;
1073: host_t *ip, **out;
1074: struct sockaddr_in6 *sin6;
1075:
1076: VA_ARGS_VGET(args, out);
1077:
1078: while (orig->enumerate(orig, &addr))
1079: {
1080: if (!(data->which & ADDR_TYPE_VIRTUAL) && addr->virtual)
1081: { /* skip virtual interfaces added by us */
1082: continue;
1083: }
1084: if (!(data->which & ADDR_TYPE_REGULAR) && !addr->virtual)
1085: { /* address is regular, but not requested */
1086: continue;
1087: }
1088: ip = addr->ip;
1089: if (ip->get_family(ip) == AF_INET6)
1090: {
1091: sin6 = (struct sockaddr_in6 *)ip->get_sockaddr(ip);
1092: if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))
1093: { /* skip addresses with a unusable scope */
1094: continue;
1095: }
1096: }
1097: *out = ip;
1098: return TRUE;
1099: }
1100: return FALSE;
1101: }
1102:
1103: /**
1104: * enumerator constructor for interfaces
1105: */
1106: static enumerator_t *create_iface_enumerator(iface_entry_t *iface,
1107: address_enumerator_t *data)
1108: {
1109: return enumerator_create_filter(iface->addrs->create_enumerator(iface->addrs),
1110: filter_addresses, data, NULL);
1111: }
1112:
1113: CALLBACK(filter_interfaces, bool,
1114: address_enumerator_t *data, enumerator_t *orig, va_list args)
1115: {
1116: iface_entry_t *iface, **out;
1117:
1118: VA_ARGS_VGET(args, out);
1119:
1120: while (orig->enumerate(orig, &iface))
1121: {
1122: if (!(data->which & ADDR_TYPE_IGNORED) && !iface->usable)
1123: { /* skip interfaces excluded by config */
1124: continue;
1125: }
1126: if (!(data->which & ADDR_TYPE_LOOPBACK) && (iface->flags & IFF_LOOPBACK))
1127: { /* ignore loopback devices */
1128: continue;
1129: }
1130: if (!(data->which & ADDR_TYPE_DOWN) && !(iface->flags & IFF_UP))
1131: { /* skip interfaces not up */
1132: continue;
1133: }
1134: *out = iface;
1135: return TRUE;
1136: }
1137: return FALSE;
1138: }
1139:
1140: METHOD(kernel_net_t, create_address_enumerator, enumerator_t*,
1141: private_kernel_pfroute_net_t *this, kernel_address_type_t which)
1142: {
1143: address_enumerator_t *data;
1144:
1145: INIT(data,
1146: .this = this,
1147: .which = which,
1148: );
1149:
1150: this->lock->read_lock(this->lock);
1151: return enumerator_create_nested(
1152: enumerator_create_filter(
1153: this->ifaces->create_enumerator(this->ifaces),
1154: filter_interfaces, data, NULL),
1155: (void*)create_iface_enumerator, data,
1156: address_enumerator_destroy);
1157: }
1158:
1159: METHOD(kernel_net_t, get_features, kernel_feature_t,
1160: private_kernel_pfroute_net_t *this)
1161: {
1162: return KERNEL_REQUIRE_EXCLUDE_ROUTE;
1163: }
1164:
1165: METHOD(kernel_net_t, get_interface_name, bool,
1166: private_kernel_pfroute_net_t *this, host_t* ip, char **name)
1167: {
1168: addr_map_entry_t *entry, lookup = {
1169: .ip = ip,
1170: };
1171:
1172: if (ip->is_anyaddr(ip))
1173: {
1174: return FALSE;
1175: }
1176: this->lock->read_lock(this->lock);
1177: /* first try to find it on an up and usable interface */
1178: entry = this->addrs->get_match(this->addrs, &lookup,
1179: (void*)addr_map_entry_match_up_and_usable);
1180: if (entry)
1181: {
1182: if (name)
1183: {
1184: *name = strdup(entry->iface->ifname);
1185: DBG2(DBG_KNL, "%H is on interface %s", ip, *name);
1186: }
1187: this->lock->unlock(this->lock);
1188: return TRUE;
1189: }
1190: /* check if it is a virtual IP */
1191: entry = this->addrs->get_match(this->addrs, &lookup,
1192: (void*)addr_map_entry_match_virtual);
1193: if (entry)
1194: {
1195: if (name)
1196: {
1197: *name = strdup(entry->iface->ifname);
1198: DBG2(DBG_KNL, "virtual IP %H is on interface %s", ip, *name);
1199: }
1200: this->lock->unlock(this->lock);
1201: return TRUE;
1202: }
1203: /* maybe it is installed on an ignored interface */
1204: entry = this->addrs->get_match(this->addrs, &lookup,
1205: (void*)addr_map_entry_match_up);
1206: if (!entry)
1207: { /* the address does not exist, is on a down interface */
1208: DBG2(DBG_KNL, "%H is not a local address or the interface is down", ip);
1209: }
1210: this->lock->unlock(this->lock);
1211: return FALSE;
1212: }
1213:
1214: METHOD(kernel_net_t, add_ip, status_t,
1215: private_kernel_pfroute_net_t *this, host_t *vip, int prefix,
1216: char *ifname)
1217: {
1218: enumerator_t *ifaces, *addrs;
1219: iface_entry_t *iface;
1220: addr_entry_t *addr;
1221: tun_device_t *tun;
1222: bool timeout = FALSE;
1223:
1224: if (!this->install_virtual_ip)
1225: { /* disabled by config */
1226: return SUCCESS;
1227: }
1228:
1229: tun = tun_device_create(NULL);
1230: if (!tun)
1231: {
1232: return FAILED;
1233: }
1234: if (prefix == -1)
1235: {
1236: prefix = vip->get_address(vip).len * 8;
1237: }
1238: if (!tun->up(tun) || !tun->set_address(tun, vip, prefix))
1239: {
1240: tun->destroy(tun);
1241: return FAILED;
1242: }
1243:
1244: /* wait until address appears */
1245: this->mutex->lock(this->mutex);
1246: while (!timeout && !get_interface_name(this, vip, NULL))
1247: {
1248: timeout = this->condvar->timed_wait(this->condvar, this->mutex,
1249: this->vip_wait);
1250: }
1251: this->mutex->unlock(this->mutex);
1252: if (timeout)
1253: {
1254: DBG1(DBG_KNL, "virtual IP %H did not appear on %s",
1255: vip, tun->get_name(tun));
1256: tun->destroy(tun);
1257: return FAILED;
1258: }
1259:
1260: this->lock->write_lock(this->lock);
1261: this->tuns->insert_last(this->tuns, tun);
1262:
1263: ifaces = this->ifaces->create_enumerator(this->ifaces);
1264: while (ifaces->enumerate(ifaces, &iface))
1265: {
1266: if (streq(iface->ifname, tun->get_name(tun)))
1267: {
1268: addrs = iface->addrs->create_enumerator(iface->addrs);
1269: while (addrs->enumerate(addrs, &addr))
1270: {
1271: if (addr->ip->ip_equals(addr->ip, vip))
1272: {
1273: addr->virtual = TRUE;
1274: }
1275: }
1276: addrs->destroy(addrs);
1277: /* during IKEv1 reauthentication, children get moved from
1278: * old the new SA before the virtual IP is available. This
1279: * kills the route for our virtual IP, reinstall. */
1280: queue_route_reinstall(this, strdup(iface->ifname));
1281: break;
1282: }
1283: }
1284: ifaces->destroy(ifaces);
1285: /* lets do this while holding the lock, thus preventing another thread
1286: * from deleting the TUN device concurrently, hopefully listeners are quick
1287: * and cause no deadlocks */
1288: charon->kernel->tun(charon->kernel, tun, TRUE);
1289: this->lock->unlock(this->lock);
1290:
1291: return SUCCESS;
1292: }
1293:
1294: METHOD(kernel_net_t, del_ip, status_t,
1295: private_kernel_pfroute_net_t *this, host_t *vip, int prefix,
1296: bool wait)
1297: {
1298: enumerator_t *enumerator;
1299: tun_device_t *tun;
1300: host_t *addr;
1301: bool timeout = FALSE, found = FALSE;
1302:
1303: if (!this->install_virtual_ip)
1304: { /* disabled by config */
1305: return SUCCESS;
1306: }
1307:
1308: this->lock->write_lock(this->lock);
1309: enumerator = this->tuns->create_enumerator(this->tuns);
1310: while (enumerator->enumerate(enumerator, &tun))
1311: {
1312: addr = tun->get_address(tun, NULL);
1313: if (addr && addr->ip_equals(addr, vip))
1314: {
1315: this->tuns->remove_at(this->tuns, enumerator);
1316: charon->kernel->tun(charon->kernel, tun, FALSE);
1317: tun->destroy(tun);
1318: found = TRUE;
1319: break;
1320: }
1321: }
1322: enumerator->destroy(enumerator);
1323: this->lock->unlock(this->lock);
1324:
1325: if (!found)
1326: {
1327: return NOT_FOUND;
1328: }
1329: /* wait until address disappears */
1330: if (wait)
1331: {
1332: this->mutex->lock(this->mutex);
1333: while (!timeout && get_interface_name(this, vip, NULL))
1334: {
1335: timeout = this->condvar->timed_wait(this->condvar, this->mutex,
1336: this->vip_wait);
1337: }
1338: this->mutex->unlock(this->mutex);
1339: if (timeout)
1340: {
1341: DBG1(DBG_KNL, "virtual IP %H did not disappear from tun", vip);
1342: return FAILED;
1343: }
1344: }
1345: return SUCCESS;
1346: }
1347:
1348: /**
1349: * Append a sockaddr_in/in6 of given type to routing message
1350: */
1351: static void add_rt_addr(struct rt_msghdr *hdr, int type, host_t *addr)
1352: {
1353: if (addr)
1354: {
1355: int len;
1356:
1357: len = *addr->get_sockaddr_len(addr);
1358: memcpy((char*)hdr + hdr->rtm_msglen, addr->get_sockaddr(addr), len);
1359: hdr->rtm_msglen += SA_LEN(len);
1360: hdr->rtm_addrs |= type;
1361: }
1362: }
1363:
1364: /**
1365: * Append a subnet mask sockaddr using the given prefix to routing message
1366: */
1367: static void add_rt_mask(struct rt_msghdr *hdr, int type, int family, int prefix)
1368: {
1369: host_t *mask;
1370:
1371: mask = host_create_netmask(family, prefix);
1372: if (mask)
1373: {
1374: add_rt_addr(hdr, type, mask);
1375: mask->destroy(mask);
1376: }
1377: }
1378:
1379: /**
1380: * Append an interface name sockaddr_dl to routing message
1381: */
1382: static void add_rt_ifname(struct rt_msghdr *hdr, int type, char *name)
1383: {
1384: struct sockaddr_dl sdl = {
1385: .sdl_len = sizeof(struct sockaddr_dl),
1386: .sdl_family = AF_LINK,
1387: .sdl_nlen = strlen(name),
1388: };
1389:
1390: if (strlen(name) <= sizeof(sdl.sdl_data))
1391: {
1392: memcpy(sdl.sdl_data, name, sdl.sdl_nlen);
1393: memcpy((char*)hdr + hdr->rtm_msglen, &sdl, sdl.sdl_len);
1394: hdr->rtm_msglen += SA_LEN(sdl.sdl_len);
1395: hdr->rtm_addrs |= type;
1396: }
1397: }
1398:
1399: /**
1400: * Add or remove a route
1401: */
1402: static status_t manage_route(private_kernel_pfroute_net_t *this, int op,
1403: chunk_t dst_net, uint8_t prefixlen,
1404: host_t *gateway, char *if_name)
1405: {
1406: struct {
1407: struct rt_msghdr hdr;
1408: char buf[sizeof(struct sockaddr_storage) * RTAX_MAX];
1409: } msg = {
1410: .hdr = {
1411: .rtm_version = RTM_VERSION,
1412: .rtm_type = op,
1413: .rtm_flags = RTF_UP | RTF_STATIC,
1414: .rtm_pid = this->pid,
1415: .rtm_seq = ref_get(&this->seq),
1416: },
1417: };
1418: host_t *dst;
1419: int type;
1420:
1421: if (prefixlen == 0 && dst_net.len)
1422: {
1423: status_t status;
1424: chunk_t half;
1425:
1426: half = chunk_clonea(dst_net);
1427: half.ptr[0] |= 0x80;
1428: prefixlen = 1;
1429: status = manage_route(this, op, half, prefixlen, gateway, if_name);
1430: if (status != SUCCESS)
1431: {
1432: return status;
1433: }
1434: }
1435:
1436: dst = host_create_from_chunk(AF_UNSPEC, dst_net, 0);
1437: if (!dst)
1438: {
1439: return FAILED;
1440: }
1441:
1442: if ((dst->get_family(dst) == AF_INET && prefixlen == 32) ||
1443: (dst->get_family(dst) == AF_INET6 && prefixlen == 128))
1444: {
1445: msg.hdr.rtm_flags |= RTF_HOST | RTF_GATEWAY;
1446: }
1447:
1448: msg.hdr.rtm_msglen = sizeof(struct rt_msghdr);
1449: for (type = 0; type < RTAX_MAX; type++)
1450: {
1451: switch (type)
1452: {
1453: case RTAX_DST:
1454: add_rt_addr(&msg.hdr, RTA_DST, dst);
1455: break;
1456: case RTAX_NETMASK:
1457: if (!(msg.hdr.rtm_flags & RTF_HOST))
1458: {
1459: add_rt_mask(&msg.hdr, RTA_NETMASK,
1460: dst->get_family(dst), prefixlen);
1461: }
1462: break;
1463: case RTAX_IFP:
1464: if (if_name)
1465: {
1466: add_rt_ifname(&msg.hdr, RTA_IFP, if_name);
1467: }
1468: break;
1469: case RTAX_GATEWAY:
1470: if (gateway &&
1471: gateway->get_family(gateway) == dst->get_family(dst))
1472: {
1473: add_rt_addr(&msg.hdr, RTA_GATEWAY, gateway);
1474: }
1475: break;
1476: default:
1477: break;
1478: }
1479: }
1480: dst->destroy(dst);
1481:
1482: if (send(this->socket, &msg, msg.hdr.rtm_msglen, 0) != msg.hdr.rtm_msglen)
1483: {
1484: if (errno == EEXIST)
1485: {
1486: return ALREADY_DONE;
1487: }
1488: DBG1(DBG_KNL, "%s PF_ROUTE route failed: %s",
1489: op == RTM_ADD ? "adding" : "deleting", strerror(errno));
1490: return FAILED;
1491: }
1492: return SUCCESS;
1493: }
1494:
1495: METHOD(kernel_net_t, add_route, status_t,
1496: private_kernel_pfroute_net_t *this, chunk_t dst_net, uint8_t prefixlen,
1497: host_t *gateway, host_t *src_ip, char *if_name, bool pass)
1498: {
1499: status_t status;
1500: route_entry_t *found, route = {
1501: .dst_net = dst_net,
1502: .prefixlen = prefixlen,
1503: .gateway = gateway,
1504: .if_name = if_name,
1505: };
1506:
1507: this->routes_lock->lock(this->routes_lock);
1508: found = this->routes->get(this->routes, &route);
1509: if (found)
1510: {
1511: this->routes_lock->unlock(this->routes_lock);
1512: return ALREADY_DONE;
1513: }
1514: status = manage_route(this, RTM_ADD, dst_net, prefixlen, gateway, if_name);
1515: if (status == SUCCESS)
1516: {
1517: found = route_entry_clone(&route);
1518: this->routes->put(this->routes, found, found);
1519: }
1520: this->routes_lock->unlock(this->routes_lock);
1521: return status;
1522: }
1523:
1524: METHOD(kernel_net_t, del_route, status_t,
1525: private_kernel_pfroute_net_t *this, chunk_t dst_net, uint8_t prefixlen,
1526: host_t *gateway, host_t *src_ip, char *if_name, bool pass)
1527: {
1528: status_t status;
1529: route_entry_t *found, route = {
1530: .dst_net = dst_net,
1531: .prefixlen = prefixlen,
1532: .gateway = gateway,
1533: .if_name = if_name,
1534: };
1535:
1536: this->routes_lock->lock(this->routes_lock);
1537: found = this->routes->get(this->routes, &route);
1538: if (!found)
1539: {
1540: this->routes_lock->unlock(this->routes_lock);
1541: return NOT_FOUND;
1542: }
1543: this->routes->remove(this->routes, found);
1544: route_entry_destroy(found);
1545: status = manage_route(this, RTM_DELETE, dst_net, prefixlen, gateway,
1546: if_name);
1547: this->routes_lock->unlock(this->routes_lock);
1548: return status;
1549: }
1550:
1551: /**
1552: * Do a route lookup for dest and return either the nexthop or the source
1553: * address.
1554: */
1555: static host_t *get_route(private_kernel_pfroute_net_t *this, bool nexthop,
1556: host_t *dest, host_t *src, char **iface)
1557: {
1558: struct {
1559: struct rt_msghdr hdr;
1560: char buf[sizeof(struct sockaddr_storage) * RTAX_MAX];
1561: } msg = {
1562: .hdr = {
1563: .rtm_version = RTM_VERSION,
1564: .rtm_type = RTM_GET,
1565: .rtm_pid = this->pid,
1566: .rtm_seq = ref_get(&this->seq),
1567: },
1568: };
1569: host_t *host = NULL;
1570: enumerator_t *enumerator;
1571: struct sockaddr *addr;
1572: bool failed = FALSE;
1573: int type;
1574:
1575: retry:
1576: msg.hdr.rtm_msglen = sizeof(struct rt_msghdr);
1577: for (type = 0; type < RTAX_MAX; type++)
1578: {
1579: switch (type)
1580: {
1581: case RTAX_DST:
1582: add_rt_addr(&msg.hdr, RTA_DST, dest);
1583: break;
1584: case RTAX_IFA:
1585: add_rt_addr(&msg.hdr, RTA_IFA, src);
1586: break;
1587: case RTAX_IFP:
1588: if (!nexthop)
1589: { /* add an empty IFP to ensure we get a source address */
1590: add_rt_ifname(&msg.hdr, RTA_IFP, "");
1591: }
1592: break;
1593: default:
1594: break;
1595: }
1596: }
1597: this->mutex->lock(this->mutex);
1598:
1599: while (this->waiting_seq)
1600: {
1601: this->condvar->wait(this->condvar, this->mutex);
1602: }
1603: this->waiting_seq = msg.hdr.rtm_seq;
1604: if (send(this->socket, &msg, msg.hdr.rtm_msglen, 0) == msg.hdr.rtm_msglen)
1605: {
1606: while (TRUE)
1607: {
1608: if (this->condvar->timed_wait(this->condvar, this->mutex, 1000))
1609: { /* timed out? */
1610: break;
1611: }
1612: if (!this->reply)
1613: {
1614: continue;
1615: }
1616: enumerator = create_rtmsg_enumerator(this->reply);
1617: while (enumerator->enumerate(enumerator, &type, &addr))
1618: {
1619: if (nexthop)
1620: {
1621: if (type == RTAX_DST && this->reply->rtm_flags & RTF_HOST)
1622: { /* probably a cloned/cached direct route, only use that
1623: * as fallback if no gateway is found */
1624: host = host ?: host_create_from_sockaddr(addr);
1625: }
1626: if (type == RTAX_GATEWAY)
1627: { /* could actually be a MAC address */
1628: host_t *gtw = host_create_from_sockaddr(addr);
1629: if (gtw)
1630: {
1631: DESTROY_IF(host);
1632: host = gtw;
1633: }
1634: }
1635: if (type == RTAX_IFP && addr->sa_family == AF_LINK)
1636: {
1637: struct sockaddr_dl *sdl = (struct sockaddr_dl*)addr;
1638: if (iface)
1639: {
1640: free(*iface);
1641: *iface = strndup(sdl->sdl_data, sdl->sdl_nlen);
1642: }
1643: }
1644: }
1645: else
1646: {
1647: if (type == RTAX_IFA)
1648: {
1649: host = host_create_from_sockaddr(addr);
1650: }
1651: }
1652: }
1653: enumerator->destroy(enumerator);
1654: break;
1655: }
1656: }
1657: else
1658: {
1659: failed = TRUE;
1660: }
1661: free(this->reply);
1662: this->reply = NULL;
1663: /* signal completion of query to a waiting thread */
1664: this->waiting_seq = 0;
1665: this->condvar->signal(this->condvar);
1666: this->mutex->unlock(this->mutex);
1667:
1668: if (failed)
1669: {
1670: if (src)
1671: { /* the given source address might be gone, try again without */
1672: src = NULL;
1673: msg.hdr.rtm_seq = ref_get(&this->seq);
1674: msg.hdr.rtm_addrs = 0;
1675: memset(msg.buf, 0, sizeof(msg.buf));
1676: goto retry;
1677: }
1678: DBG1(DBG_KNL, "PF_ROUTE lookup failed: %s", strerror(errno));
1679: }
1680: if (nexthop)
1681: {
1682: host = host ?: dest->clone(dest);
1683: }
1684: else
1685: { /* make sure the source address is not virtual and usable */
1686: addr_entry_t *entry, lookup = {
1687: .ip = host,
1688: };
1689:
1690: if (!host)
1691: {
1692: return NULL;
1693: }
1694: this->lock->read_lock(this->lock);
1695: entry = this->addrs->get_match(this->addrs, &lookup,
1696: (void*)addr_map_entry_match_up_and_usable);
1697: this->lock->unlock(this->lock);
1698: if (!entry)
1699: {
1700: host->destroy(host);
1701: return NULL;
1702: }
1703: }
1704: DBG2(DBG_KNL, "using %H as %s to reach %H", host,
1705: nexthop ? "nexthop" : "address", dest);
1706: return host;
1707: }
1708:
1709: METHOD(kernel_net_t, get_source_addr, host_t*,
1710: private_kernel_pfroute_net_t *this, host_t *dest, host_t *src)
1711: {
1712: return get_route(this, FALSE, dest, src, NULL);
1713: }
1714:
1715: METHOD(kernel_net_t, get_nexthop, host_t*,
1716: private_kernel_pfroute_net_t *this, host_t *dest, int prefix, host_t *src,
1717: char **iface)
1718: {
1719: if (iface)
1720: {
1721: *iface = NULL;
1722: }
1723: return get_route(this, TRUE, dest, src, iface);
1724: }
1725:
1726: /**
1727: * Get the number of set bits in the given netmask
1728: */
1729: static uint8_t sockaddr_to_netmask(sockaddr_t *sockaddr, host_t *dst)
1730: {
1731: uint8_t len = 0, i, byte, mask = 0;
1732: struct sockaddr_storage ss;
1733: char *addr;
1734:
1735: /* at least some older FreeBSD versions send us shorter sockaddrs
1736: * with the family set to -1 (255) */
1737: if (sockaddr->sa_family == 255)
1738: {
1739: memset(&ss, 0, sizeof(ss));
1740: memcpy(&ss, sockaddr, sockaddr->sa_len);
1741: /* use the address family and length of the destination as hint */
1742: ss.ss_len = *dst->get_sockaddr_len(dst);
1743: ss.ss_family = dst->get_family(dst);
1744: sockaddr = (sockaddr_t*)&ss;
1745: }
1746:
1747: switch (sockaddr->sa_family)
1748: {
1749: case AF_INET:
1750: len = 4;
1751: addr = (char*)&((struct sockaddr_in*)sockaddr)->sin_addr;
1752: break;
1753: case AF_INET6:
1754: len = 16;
1755: addr = (char*)&((struct sockaddr_in6*)sockaddr)->sin6_addr;
1756: break;
1757: default:
1758: break;
1759: }
1760:
1761: for (i = 0; i < len; i++)
1762: {
1763: byte = addr[i];
1764:
1765: if (byte == 0x00)
1766: {
1767: break;
1768: }
1769: if (byte == 0xff)
1770: {
1771: mask += 8;
1772: }
1773: else
1774: {
1775: while (byte & 0x80)
1776: {
1777: mask++;
1778: byte <<= 1;
1779: }
1780: }
1781: }
1782: return mask;
1783: }
1784:
1785: /** enumerator over subnets */
1786: typedef struct {
1787: enumerator_t public;
1788: /** sysctl result */
1789: char *buf;
1790: /** length of the complete result */
1791: size_t len;
1792: /** start of the current route entry */
1793: char *current;
1794: /** last subnet enumerated */
1795: host_t *net;
1796: /** interface of current net */
1797: char *ifname;
1798: } subnet_enumerator_t;
1799:
1800: METHOD(enumerator_t, destroy_subnet_enumerator, void,
1801: subnet_enumerator_t *this)
1802: {
1803: DESTROY_IF(this->net);
1804: free(this->ifname);
1805: free(this->buf);
1806: free(this);
1807: }
1808:
1809: METHOD(enumerator_t, enumerate_subnets, bool,
1810: subnet_enumerator_t *this, va_list args)
1811: {
1812: enumerator_t *enumerator;
1813: host_t **net;
1814: struct rt_msghdr *rtm;
1815: struct sockaddr *addr;
1816: uint8_t *mask;
1817: char **ifname;
1818: int type;
1819:
1820: VA_ARGS_VGET(args, net, mask, ifname);
1821:
1822: if (!this->current)
1823: {
1824: this->current = this->buf;
1825: }
1826: else
1827: {
1828: rtm = (struct rt_msghdr*)this->current;
1829: this->current += rtm->rtm_msglen;
1830: DESTROY_IF(this->net);
1831: this->net = NULL;
1832: free(this->ifname);
1833: this->ifname = NULL;
1834: }
1835:
1836: for (; this->current < this->buf + this->len;
1837: this->current += rtm->rtm_msglen)
1838: {
1839: struct sockaddr *netmask = NULL;
1840: uint8_t netbits = 0;
1841:
1842: rtm = (struct rt_msghdr*)this->current;
1843:
1844: if (rtm->rtm_version != RTM_VERSION)
1845: {
1846: continue;
1847: }
1848: if (rtm->rtm_flags & RTF_GATEWAY ||
1849: rtm->rtm_flags & RTF_HOST ||
1850: rtm->rtm_flags & RTF_REJECT)
1851: {
1852: continue;
1853: }
1854: enumerator = create_rtmsg_enumerator(rtm);
1855: while (enumerator->enumerate(enumerator, &type, &addr))
1856: {
1857: if (type == RTAX_DST)
1858: {
1859: this->net = this->net ?: host_create_from_sockaddr(addr);
1860: }
1861: if (type == RTAX_NETMASK)
1862: {
1863: netmask = addr;
1864: }
1865: if (type == RTAX_IFP && addr->sa_family == AF_LINK)
1866: {
1867: struct sockaddr_dl *sdl = (struct sockaddr_dl*)addr;
1868: free(this->ifname);
1869: this->ifname = strndup(sdl->sdl_data, sdl->sdl_nlen);
1870: }
1871: }
1872: if (this->net && netmask)
1873: {
1874: netbits = sockaddr_to_netmask(netmask, this->net);
1875: }
1876: enumerator->destroy(enumerator);
1877:
1878: if (this->net && this->ifname)
1879: {
1880: *net = this->net;
1881: *mask = netbits ?: this->net->get_address(this->net).len * 8;
1882: *ifname = this->ifname;
1883: return TRUE;
1884: }
1885: }
1886: return FALSE;
1887: }
1888:
1889: METHOD(kernel_net_t, create_local_subnet_enumerator, enumerator_t*,
1890: private_kernel_pfroute_net_t *this)
1891: {
1892: subnet_enumerator_t *enumerator;
1893: char *buf;
1894: size_t len;
1895: int mib[7] = {
1896: CTL_NET, PF_ROUTE, 0, AF_UNSPEC, NET_RT_DUMP, 0, 0
1897: };
1898:
1899: if (sysctl(mib, countof(mib), NULL, &len, NULL, 0) < 0)
1900: {
1901: DBG2(DBG_KNL, "enumerating local subnets failed");
1902: return enumerator_create_empty();
1903: }
1904: buf = malloc(len);
1905: if (sysctl(mib, countof(mib), buf, &len, NULL, 0) < 0)
1906: {
1907: DBG2(DBG_KNL, "enumerating local subnets failed");
1908: free(buf);
1909: return enumerator_create_empty();
1910: }
1911:
1912: INIT(enumerator,
1913: .public = {
1914: .enumerate = enumerator_enumerate_default,
1915: .venumerate = _enumerate_subnets,
1916: .destroy = _destroy_subnet_enumerator,
1917: },
1918: .buf = buf,
1919: .len = len,
1920: );
1921: return &enumerator->public;
1922: }
1923:
1924: /**
1925: * Initialize a list of local addresses.
1926: */
1927: static status_t init_address_list(private_kernel_pfroute_net_t *this)
1928: {
1929: struct ifaddrs *ifap, *ifa;
1930: iface_entry_t *iface, *current;
1931: addr_entry_t *addr;
1932: enumerator_t *ifaces, *addrs;
1933:
1934: DBG2(DBG_KNL, "known interfaces and IP addresses:");
1935:
1936: if (getifaddrs(&ifap) < 0)
1937: {
1938: DBG1(DBG_KNL, " failed to get interfaces!");
1939: return FAILED;
1940: }
1941:
1942: for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next)
1943: {
1944: if (ifa->ifa_addr == NULL)
1945: {
1946: continue;
1947: }
1948: switch(ifa->ifa_addr->sa_family)
1949: {
1950: case AF_LINK:
1951: case AF_INET:
1952: case AF_INET6:
1953: {
1954: iface = NULL;
1955: ifaces = this->ifaces->create_enumerator(this->ifaces);
1956: while (ifaces->enumerate(ifaces, ¤t))
1957: {
1958: if (streq(current->ifname, ifa->ifa_name))
1959: {
1960: iface = current;
1961: break;
1962: }
1963: }
1964: ifaces->destroy(ifaces);
1965:
1966: if (!iface)
1967: {
1968: INIT(iface,
1969: .ifindex = if_nametoindex(ifa->ifa_name),
1970: .flags = ifa->ifa_flags,
1971: .addrs = linked_list_create(),
1972: .usable = charon->kernel->is_interface_usable(
1973: charon->kernel, ifa->ifa_name),
1974: );
1975: memcpy(iface->ifname, ifa->ifa_name, IFNAMSIZ);
1976: this->ifaces->insert_last(this->ifaces, iface);
1977: }
1978:
1979: if (ifa->ifa_addr->sa_family != AF_LINK)
1980: {
1981: INIT(addr,
1982: .ip = host_create_from_sockaddr(ifa->ifa_addr),
1983: );
1984: iface->addrs->insert_last(iface->addrs, addr);
1985: addr_map_entry_add(this, addr, iface);
1986: }
1987: }
1988: }
1989: }
1990: freeifaddrs(ifap);
1991:
1992: ifaces = this->ifaces->create_enumerator(this->ifaces);
1993: while (ifaces->enumerate(ifaces, &iface))
1994: {
1995: if (iface->usable && iface->flags & IFF_UP)
1996: {
1997: DBG2(DBG_KNL, " %s", iface->ifname);
1998: addrs = iface->addrs->create_enumerator(iface->addrs);
1999: while (addrs->enumerate(addrs, (void**)&addr))
2000: {
2001: DBG2(DBG_KNL, " %H", addr->ip);
2002: }
2003: addrs->destroy(addrs);
2004: }
2005: }
2006: ifaces->destroy(ifaces);
2007:
2008: return SUCCESS;
2009: }
2010:
2011: METHOD(kernel_net_t, destroy, void,
2012: private_kernel_pfroute_net_t *this)
2013: {
2014: enumerator_t *enumerator;
2015: route_entry_t *route;
2016: addr_entry_t *addr;
2017:
2018: enumerator = this->routes->create_enumerator(this->routes);
2019: while (enumerator->enumerate(enumerator, NULL, (void**)&route))
2020: {
2021: manage_route(this, RTM_DELETE, route->dst_net, route->prefixlen,
2022: route->gateway, route->if_name);
2023: route_entry_destroy(route);
2024: }
2025: enumerator->destroy(enumerator);
2026: this->routes->destroy(this->routes);
2027: this->routes_lock->destroy(this->routes_lock);
2028:
2029: if (this->socket != -1)
2030: {
2031: lib->watcher->remove(lib->watcher, this->socket);
2032: close(this->socket);
2033: }
2034:
2035: net_changes_clear(this);
2036: this->net_changes->destroy(this->net_changes);
2037: this->net_changes_lock->destroy(this->net_changes_lock);
2038:
2039: enumerator = this->addrs->create_enumerator(this->addrs);
2040: while (enumerator->enumerate(enumerator, NULL, (void**)&addr))
2041: {
2042: free(addr);
2043: }
2044: enumerator->destroy(enumerator);
2045: this->addrs->destroy(this->addrs);
2046: this->ifaces->destroy_function(this->ifaces, (void*)iface_entry_destroy);
2047: this->tuns->destroy(this->tuns);
2048: this->lock->destroy(this->lock);
2049: this->mutex->destroy(this->mutex);
2050: this->condvar->destroy(this->condvar);
2051: this->roam_lock->destroy(this->roam_lock);
2052: free(this->reply);
2053: free(this);
2054: }
2055:
2056: /*
2057: * Described in header.
2058: */
2059: kernel_pfroute_net_t *kernel_pfroute_net_create()
2060: {
2061: private_kernel_pfroute_net_t *this;
2062:
2063: INIT(this,
2064: .public = {
2065: .interface = {
2066: .get_features = _get_features,
2067: .get_interface = _get_interface_name,
2068: .create_address_enumerator = _create_address_enumerator,
2069: .create_local_subnet_enumerator = _create_local_subnet_enumerator,
2070: .get_source_addr = _get_source_addr,
2071: .get_nexthop = _get_nexthop,
2072: .add_ip = _add_ip,
2073: .del_ip = _del_ip,
2074: .add_route = _add_route,
2075: .del_route = _del_route,
2076: .destroy = _destroy,
2077: },
2078: },
2079: .pid = getpid(),
2080: .ifaces = linked_list_create(),
2081: .addrs = hashtable_create(
2082: (hashtable_hash_t)addr_map_entry_hash,
2083: (hashtable_equals_t)addr_map_entry_equals, 16),
2084: .routes = hashtable_create((hashtable_hash_t)route_entry_hash,
2085: (hashtable_equals_t)route_entry_equals, 16),
2086: .net_changes = hashtable_create(
2087: (hashtable_hash_t)net_change_hash,
2088: (hashtable_equals_t)net_change_equals, 16),
2089: .tuns = linked_list_create(),
2090: .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
2091: .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
2092: .condvar = condvar_create(CONDVAR_TYPE_DEFAULT),
2093: .routes_lock = mutex_create(MUTEX_TYPE_DEFAULT),
2094: .net_changes_lock = mutex_create(MUTEX_TYPE_DEFAULT),
2095: .roam_lock = spinlock_create(),
2096: .vip_wait = lib->settings->get_int(lib->settings,
2097: "%s.plugins.kernel-pfroute.vip_wait", 1000, lib->ns),
2098: .install_virtual_ip = lib->settings->get_bool(lib->settings,
2099: "%s.install_virtual_ip", TRUE, lib->ns),
2100: );
2101: timerclear(&this->last_route_reinstall);
2102: timerclear(&this->next_roam);
2103:
2104: /* create a PF_ROUTE socket to communicate with the kernel */
2105: this->socket = socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
2106: if (this->socket == -1)
2107: {
2108: DBG1(DBG_KNL, "unable to create PF_ROUTE socket");
2109: destroy(this);
2110: return NULL;
2111: }
2112:
2113: if (streq(lib->ns, "starter"))
2114: {
2115: /* starter has no threads, so we do not register for kernel events */
2116: if (shutdown(this->socket, SHUT_RD) != 0)
2117: {
2118: DBG1(DBG_KNL, "closing read end of PF_ROUTE socket failed: %s",
2119: strerror(errno));
2120: }
2121: }
2122: else
2123: {
2124: lib->watcher->add(lib->watcher, this->socket, WATCHER_READ,
2125: (watcher_cb_t)receive_events, this);
2126: }
2127: if (init_address_list(this) != SUCCESS)
2128: {
2129: DBG1(DBG_KNL, "unable to get interface list");
2130: destroy(this);
2131: return NULL;
2132: }
2133:
2134: return &this->public;
2135: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>