a36ba4d0ee0e2d5bc3df8515874e6dd6ce9fb30a
[strongswan.git] / src / charon / network / interfaces.c
1 /**
2 * @file interfaces.c
3 *
4 * @brief Implementation of interfaces_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2006 Tobias Brunner, Daniel Roethlisberger
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
20 * for more details.
21 */
22
23 #include <net/if.h>
24 #include <ifaddrs.h>
25 #include <string.h>
26
27 #include "interfaces.h"
28
29 typedef struct private_interfaces_t private_interfaces_t;
30
31 /**
32 * Private data of an interfaces_t object.
33 */
34 struct private_interfaces_t {
35
36 /**
37 * Public part of a interfaces_t object.
38 */
39 interfaces_t public;
40
41 /**
42 * port that gets added to the host_t obbjects
43 */
44 u_int16_t port;
45
46 /**
47 * list of addresses
48 */
49 linked_list_t *addresses;
50 };
51
52 /**
53 * Implements interfaces_t.get_addresses
54 */
55 static linked_list_t* get_addresses(private_interfaces_t *this)
56 {
57 return this->addresses;
58 }
59
60 /**
61 * Implements interfaces_t.is_local_address
62 */
63 static bool is_local_address(private_interfaces_t *this, host_t *host)
64 {
65 iterator_t *iterator;
66 host_t *lhost;
67
68 if (host->is_anyaddr(host))
69 {
70 return FALSE;
71 }
72
73 iterator = this->addresses->create_iterator(this->addresses, TRUE);
74 while (iterator->iterate(iterator, (void**)&lhost))
75 {
76 if (host->get_family(host) == lhost->get_family(lhost) &&
77 streq(host->get_address(host), lhost->get_address(lhost)))
78 {
79 iterator->destroy(iterator);
80 return TRUE;
81 }
82 }
83
84 iterator->destroy(iterator);
85 return FALSE;
86 }
87
88 /**
89 * Implements interfaces_t.destroy.
90 */
91 static void destroy(private_interfaces_t *this)
92 {
93 host_t *host;
94 while (this->addresses->remove_last(this->addresses, (void**)&host) == SUCCESS)
95 {
96 host->destroy(host);
97 }
98 this->addresses->destroy(this->addresses);
99 free(this);
100 }
101
102 static status_t initialize(private_interfaces_t *this)
103 {
104 struct ifaddrs *list;
105 struct ifaddrs *cur;
106 host_t *host;
107
108 if (getifaddrs(&list) < 0)
109 {
110 return FAILED;
111 }
112
113 for (cur = list; cur != NULL; cur = cur->ifa_next)
114 {
115 if (!(cur->ifa_flags & IFF_UP))
116 continue;
117
118 if (cur->ifa_addr == NULL || cur->ifa_addr->sa_family != AF_INET)
119 continue;
120
121 host = host_create_from_sockaddr(cur->ifa_addr);
122 if (host) {
123 host->set_port(host, this->port);
124 this->addresses->insert_last(this->addresses, (void*) host);
125 }
126 }
127
128 freeifaddrs(list);
129 return SUCCESS;
130 }
131
132 /*
133 * Documented in header
134 */
135 interfaces_t *interfaces_create(u_int16_t port)
136 {
137 private_interfaces_t *this = malloc_thing(private_interfaces_t);
138
139 this->port = port;
140
141 this->public.get_addresses = (linked_list_t* (*) (interfaces_t*)) get_addresses;
142 this->public.is_local_address = (bool (*) (interfaces_t*, host_t*)) is_local_address;
143 this->public.destroy = (void (*) (interfaces_t*)) destroy;
144
145 this->addresses = linked_list_create();
146
147 if (initialize(this) != SUCCESS)
148 {
149 destroy(this);
150 }
151
152 return &this->public;
153 }