]>
Commit | Line | Data |
---|---|---|
55699f03 | 1 | /* |
4437914a | 2 | * Copyright (C) 2010-2011 Tobias Brunner |
55699f03 | 3 | * Copyright (C) 2010 Martin Willi |
55699f03 MW |
4 | * 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 | ||
71070c88 | 17 | #include "android_handler.h" |
55699f03 MW |
18 | |
19 | #include <utils/linked_list.h> | |
20 | ||
21 | #include <cutils/properties.h> | |
22 | ||
71070c88 | 23 | typedef struct private_android_handler_t private_android_handler_t; |
55699f03 MW |
24 | |
25 | /** | |
71070c88 | 26 | * Private data of an android_handler_t object. |
55699f03 | 27 | */ |
71070c88 | 28 | struct private_android_handler_t { |
55699f03 MW |
29 | |
30 | /** | |
71070c88 | 31 | * Public android_handler_t interface. |
55699f03 | 32 | */ |
71070c88 | 33 | android_handler_t public; |
55699f03 MW |
34 | |
35 | /** | |
36 | * List of registered DNS servers | |
37 | */ | |
38 | linked_list_t *dns; | |
4437914a TB |
39 | |
40 | /** | |
41 | * Whether the VPN frontend is used | |
42 | */ | |
43 | bool frontend; | |
55699f03 MW |
44 | }; |
45 | ||
4437914a TB |
46 | /** |
47 | * Prefixes to be used when installing DNS servers | |
48 | */ | |
49 | #define DNS_PREFIX_DEFAULT "net" | |
50 | #define DNS_PREFIX_FRONTEND "vpn" | |
51 | ||
55699f03 MW |
52 | /** |
53 | * Struct to store a pair of old and installed DNS servers | |
54 | */ | |
55 | typedef struct { | |
56 | /** installed dns server */ | |
57 | host_t *dns; | |
58 | /** old dns server */ | |
59 | host_t *old; | |
60 | } dns_pair_t; | |
61 | ||
62 | /** | |
63 | * Destroy a pair of old and installed DNS servers | |
64 | */ | |
65 | void destroy_dns_pair(dns_pair_t *this) | |
66 | { | |
67 | DESTROY_IF(this->dns); | |
68 | DESTROY_IF(this->old); | |
69 | free(this); | |
70 | } | |
71 | ||
72 | /** | |
73 | * Filter pairs of DNS servers | |
74 | */ | |
75 | bool filter_dns_pair(void *data, dns_pair_t **in, host_t **out) | |
76 | { | |
77 | *out = (*in)->dns; | |
78 | return TRUE; | |
79 | } | |
80 | ||
81 | /** | |
82 | * Read DNS server property with a given index | |
83 | */ | |
4437914a | 84 | host_t *get_dns_server(private_android_handler_t *this, int index) |
55699f03 MW |
85 | { |
86 | host_t *dns = NULL; | |
4437914a TB |
87 | char key[10], value[PROPERTY_VALUE_MAX], |
88 | *prefix = this->frontend ? DNS_PREFIX_FRONTEND : DNS_PREFIX_DEFAULT; | |
55699f03 | 89 | |
4437914a | 90 | if (snprintf(key, sizeof(key), "%s.dns%d", prefix, index) >= sizeof(key)) |
55699f03 MW |
91 | { |
92 | return NULL; | |
93 | } | |
94 | ||
95 | if (property_get(key, value, NULL) > 0) | |
96 | { | |
97 | dns = host_create_from_string(value, 0); | |
98 | } | |
99 | return dns; | |
100 | } | |
101 | ||
102 | /** | |
103 | * Set DNS server property with a given index | |
104 | */ | |
4437914a | 105 | bool set_dns_server(private_android_handler_t *this, int index, host_t *dns) |
55699f03 | 106 | { |
4437914a TB |
107 | char key[10], value[PROPERTY_VALUE_MAX], |
108 | *prefix = this->frontend ? DNS_PREFIX_FRONTEND : DNS_PREFIX_DEFAULT; | |
55699f03 | 109 | |
4437914a | 110 | if (snprintf(key, sizeof(key), "%s.dns%d", prefix, index) >= sizeof(key)) |
55699f03 MW |
111 | { |
112 | return FALSE; | |
113 | } | |
114 | ||
115 | if (dns) | |
116 | { | |
117 | if (snprintf(value, sizeof(value), "%H", dns) >= sizeof(value)) | |
118 | { | |
119 | return FALSE; | |
120 | } | |
121 | } | |
122 | else | |
123 | { | |
124 | value[0] = '\0'; | |
125 | } | |
126 | ||
127 | if (property_set(key, value) != 0) | |
128 | { | |
129 | return FALSE; | |
130 | } | |
131 | return TRUE; | |
132 | } | |
133 | ||
134 | METHOD(attribute_handler_t, handle, bool, | |
71070c88 | 135 | private_android_handler_t *this, identification_t *id, |
55699f03 MW |
136 | configuration_attribute_type_t type, chunk_t data) |
137 | { | |
138 | switch (type) | |
139 | { | |
140 | case INTERNAL_IP4_DNS: | |
141 | { | |
142 | host_t *dns; | |
143 | dns_pair_t *pair; | |
144 | int index; | |
145 | ||
146 | dns = host_create_from_chunk(AF_INET, data, 0); | |
147 | if (dns) | |
148 | { | |
149 | pair = malloc_thing(dns_pair_t); | |
150 | pair->dns = dns; | |
151 | index = this->dns->get_count(this->dns) + 1; | |
4437914a TB |
152 | pair->old = get_dns_server(this, index); |
153 | set_dns_server(this, index, dns); | |
55699f03 MW |
154 | this->dns->insert_last(this->dns, pair); |
155 | return TRUE; | |
156 | } | |
157 | return FALSE; | |
71070c88 | 158 | } |
55699f03 MW |
159 | default: |
160 | return FALSE; | |
161 | } | |
162 | } | |
163 | ||
164 | METHOD(attribute_handler_t, release, void, | |
71070c88 | 165 | private_android_handler_t *this, identification_t *server, |
55699f03 MW |
166 | configuration_attribute_type_t type, chunk_t data) |
167 | { | |
168 | if (type == INTERNAL_IP4_DNS) | |
169 | { | |
170 | enumerator_t *enumerator; | |
171 | dns_pair_t *pair; | |
172 | int index; | |
173 | ||
174 | enumerator = this->dns->create_enumerator(this->dns); | |
175 | for (index = 1; enumerator->enumerate(enumerator, &pair); index++) | |
176 | { | |
177 | if (chunk_equals(pair->dns->get_address(pair->dns), data)) | |
178 | { | |
179 | this->dns->remove_at(this->dns, enumerator); | |
4437914a | 180 | set_dns_server(this, index, pair->old); |
55699f03 MW |
181 | destroy_dns_pair(pair); |
182 | } | |
183 | } | |
184 | enumerator->destroy(enumerator); | |
185 | } | |
186 | } | |
187 | ||
188 | METHOD(enumerator_t, enumerate_dns, bool, | |
189 | enumerator_t *this, configuration_attribute_type_t *type, chunk_t *data) | |
190 | { | |
191 | *type = INTERNAL_IP4_DNS; | |
192 | *data = chunk_empty; | |
193 | /* stop enumeration */ | |
194 | this->enumerate = (void*)return_false; | |
195 | return TRUE; | |
196 | } | |
197 | ||
198 | METHOD(attribute_handler_t, create_attribute_enumerator, enumerator_t *, | |
71070c88 | 199 | android_handler_t *this, identification_t *id, host_t *vip) |
55699f03 MW |
200 | { |
201 | enumerator_t *enumerator; | |
202 | ||
203 | INIT(enumerator, | |
204 | .enumerate = (void*)_enumerate_dns, | |
205 | .destroy = (void*)free, | |
206 | ); | |
207 | return enumerator; | |
208 | } | |
209 | ||
71070c88 MW |
210 | METHOD(android_handler_t, destroy, void, |
211 | private_android_handler_t *this) | |
55699f03 MW |
212 | { |
213 | this->dns->destroy_function(this->dns, (void*)destroy_dns_pair); | |
214 | free(this); | |
215 | } | |
216 | ||
217 | /** | |
218 | * See header | |
219 | */ | |
4437914a | 220 | android_handler_t *android_handler_create(bool frontend) |
55699f03 | 221 | { |
71070c88 | 222 | private_android_handler_t *this; |
55699f03 MW |
223 | |
224 | INIT(this, | |
225 | .public = { | |
226 | .handler = { | |
227 | .handle = _handle, | |
228 | .release = _release, | |
229 | .create_attribute_enumerator = _create_attribute_enumerator, | |
230 | }, | |
231 | .destroy = _destroy, | |
232 | }, | |
233 | .dns = linked_list_create(), | |
4437914a | 234 | .frontend = frontend, |
55699f03 MW |
235 | ); |
236 | ||
237 | return &this->public; | |
238 | } | |
239 |