]>
Commit | Line | Data |
---|---|---|
7f56b494 MW |
1 | /* |
2 | * Copyright (C) 2009 Martin Willi | |
3 | * 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. | |
7f56b494 MW |
14 | */ |
15 | ||
4819ec6a | 16 | #include "resolve_handler.h" |
7f56b494 MW |
17 | |
18 | #include <unistd.h> | |
19 | ||
9a0333fa AS |
20 | #include <hydra.h> |
21 | #include <debug.h> | |
eba64cef | 22 | #include <threading/mutex.h> |
7f56b494 | 23 | |
4819ec6a | 24 | typedef struct private_resolve_handler_t private_resolve_handler_t; |
7f56b494 MW |
25 | |
26 | /** | |
4819ec6a | 27 | * Private data of an resolve_handler_t object. |
7f56b494 | 28 | */ |
4819ec6a | 29 | struct private_resolve_handler_t { |
7daf5226 | 30 | |
7f56b494 | 31 | /** |
4819ec6a | 32 | * Public resolve_handler_t interface. |
7f56b494 | 33 | */ |
4819ec6a | 34 | resolve_handler_t public; |
7daf5226 | 35 | |
7f56b494 MW |
36 | /** |
37 | * resolv.conf file to use | |
38 | */ | |
39 | char *file; | |
7daf5226 | 40 | |
7f56b494 MW |
41 | /** |
42 | * Mutex to access file exclusively | |
43 | */ | |
44 | mutex_t *mutex; | |
45 | }; | |
46 | ||
47 | /** | |
48 | * Implementation of attribute_handler_t.handle | |
49 | */ | |
930443af | 50 | static bool handle(private_resolve_handler_t *this, identification_t *server, |
7f56b494 MW |
51 | configuration_attribute_type_t type, chunk_t data) |
52 | { | |
53 | FILE *in, *out; | |
54 | char buf[1024]; | |
55 | host_t *addr; | |
7f56b494 MW |
56 | size_t len; |
57 | bool handled = FALSE; | |
7daf5226 | 58 | |
7f56b494 MW |
59 | switch (type) |
60 | { | |
61 | case INTERNAL_IP4_DNS: | |
376a11db | 62 | addr = host_create_from_chunk(AF_INET, data, 0); |
7f56b494 MW |
63 | break; |
64 | case INTERNAL_IP6_DNS: | |
376a11db | 65 | addr = host_create_from_chunk(AF_INET6, data, 0); |
7f56b494 MW |
66 | break; |
67 | default: | |
68 | return FALSE; | |
69 | } | |
7daf5226 | 70 | |
376a11db MW |
71 | if (!addr || addr->is_anyaddr(addr)) |
72 | { | |
73 | DESTROY_IF(addr); | |
74 | return FALSE; | |
75 | } | |
7f56b494 | 76 | this->mutex->lock(this->mutex); |
7daf5226 | 77 | |
7f56b494 MW |
78 | in = fopen(this->file, "r"); |
79 | /* allows us to stream from in to out */ | |
80 | unlink(this->file); | |
81 | out = fopen(this->file, "w"); | |
82 | if (out) | |
83 | { | |
376a11db | 84 | fprintf(out, "nameserver %H # by strongSwan, from %Y\n", addr, server); |
7f56b494 | 85 | DBG1(DBG_IKE, "installing DNS server %H to %s", addr, this->file); |
7f56b494 | 86 | handled = TRUE; |
7daf5226 | 87 | |
7f56b494 MW |
88 | /* copy rest of the file */ |
89 | if (in) | |
90 | { | |
91 | while ((len = fread(buf, 1, sizeof(buf), in))) | |
92 | { | |
93 | ignore_result(fwrite(buf, 1, len, out)); | |
94 | } | |
7f56b494 MW |
95 | } |
96 | fclose(out); | |
97 | } | |
376a11db MW |
98 | if (in) |
99 | { | |
100 | fclose(in); | |
101 | } | |
102 | this->mutex->unlock(this->mutex); | |
103 | addr->destroy(addr); | |
7daf5226 | 104 | |
7f56b494 MW |
105 | if (!handled) |
106 | { | |
107 | DBG1(DBG_IKE, "adding DNS server failed", this->file); | |
108 | } | |
7f56b494 MW |
109 | return handled; |
110 | } | |
111 | ||
112 | /** | |
113 | * Implementation of attribute_handler_t.release | |
114 | */ | |
930443af | 115 | static void release(private_resolve_handler_t *this, identification_t *server, |
7f56b494 MW |
116 | configuration_attribute_type_t type, chunk_t data) |
117 | { | |
118 | FILE *in, *out; | |
24e05954 | 119 | char line[1024], matcher[512]; |
7f56b494 MW |
120 | host_t *addr; |
121 | int family; | |
7daf5226 | 122 | |
7f56b494 MW |
123 | switch (type) |
124 | { | |
125 | case INTERNAL_IP4_DNS: | |
126 | family = AF_INET; | |
127 | break; | |
128 | case INTERNAL_IP6_DNS: | |
129 | family = AF_INET6; | |
130 | break; | |
131 | default: | |
132 | return; | |
133 | } | |
7daf5226 | 134 | |
7f56b494 | 135 | this->mutex->lock(this->mutex); |
7daf5226 | 136 | |
7f56b494 MW |
137 | in = fopen(this->file, "r"); |
138 | if (in) | |
139 | { | |
140 | /* allows us to stream from in to out */ | |
141 | unlink(this->file); | |
142 | out = fopen(this->file, "w"); | |
143 | if (out) | |
144 | { | |
145 | addr = host_create_from_chunk(family, data, 0); | |
146 | snprintf(matcher, sizeof(matcher), | |
d24a74c5 | 147 | "nameserver %H # by strongSwan, from %Y\n", |
930443af | 148 | addr, server); |
7daf5226 | 149 | |
7f56b494 | 150 | /* copy all, but matching line */ |
24e05954 | 151 | while (fgets(line, sizeof(line), in)) |
7f56b494 MW |
152 | { |
153 | if (strneq(line, matcher, strlen(matcher))) | |
154 | { | |
155 | DBG1(DBG_IKE, "removing DNS server %H from %s", | |
156 | addr, this->file); | |
157 | } | |
158 | else | |
159 | { | |
160 | fputs(line, out); | |
161 | } | |
162 | } | |
163 | addr->destroy(addr); | |
164 | fclose(out); | |
165 | } | |
166 | fclose(in); | |
167 | } | |
7daf5226 | 168 | |
7f56b494 MW |
169 | this->mutex->unlock(this->mutex); |
170 | } | |
171 | ||
b5a2055f MW |
172 | /** |
173 | * Attribute enumerator implementation | |
174 | */ | |
175 | typedef struct { | |
176 | /** implements enumerator_t interface */ | |
177 | enumerator_t public; | |
178 | /** virtual IP we are requesting */ | |
179 | host_t *vip; | |
180 | } attribute_enumerator_t; | |
181 | ||
182 | /** | |
183 | * Implementation of create_attribute_enumerator().enumerate() | |
184 | */ | |
185 | static bool attribute_enumerate(attribute_enumerator_t *this, | |
186 | configuration_attribute_type_t *type, chunk_t *data) | |
187 | { | |
188 | switch (this->vip->get_family(this->vip)) | |
189 | { | |
190 | case AF_INET: | |
191 | *type = INTERNAL_IP4_DNS; | |
192 | break; | |
193 | case AF_INET6: | |
194 | *type = INTERNAL_IP6_DNS; | |
195 | break; | |
196 | default: | |
197 | return FALSE; | |
198 | } | |
199 | *data = chunk_empty; | |
200 | /* enumerate only once */ | |
201 | this->public.enumerate = (void*)return_false; | |
202 | return TRUE; | |
203 | } | |
204 | ||
205 | /** | |
206 | * Implementation of attribute_handler_t.create_attribute_enumerator | |
207 | */ | |
208 | static enumerator_t* create_attribute_enumerator(private_resolve_handler_t *this, | |
209 | identification_t *server, host_t *vip) | |
210 | { | |
211 | if (vip) | |
212 | { | |
213 | attribute_enumerator_t *enumerator; | |
214 | ||
215 | enumerator = malloc_thing(attribute_enumerator_t); | |
216 | enumerator->public.enumerate = (void*)attribute_enumerate; | |
217 | enumerator->public.destroy = (void*)free; | |
218 | enumerator->vip = vip; | |
219 | ||
220 | return &enumerator->public; | |
221 | } | |
222 | return enumerator_create_empty(); | |
223 | } | |
224 | ||
7f56b494 | 225 | /** |
4819ec6a | 226 | * Implementation of resolve_handler_t.destroy. |
7f56b494 | 227 | */ |
4819ec6a | 228 | static void destroy(private_resolve_handler_t *this) |
7f56b494 MW |
229 | { |
230 | this->mutex->destroy(this->mutex); | |
3e2419eb | 231 | free(this->file); |
7f56b494 MW |
232 | free(this); |
233 | } | |
234 | ||
235 | /** | |
236 | * See header | |
237 | */ | |
4819ec6a | 238 | resolve_handler_t *resolve_handler_create() |
7f56b494 | 239 | { |
4819ec6a | 240 | private_resolve_handler_t *this = malloc_thing(private_resolve_handler_t); |
7daf5226 | 241 | |
930443af AS |
242 | this->public.handler.handle = (bool(*)(attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))handle; |
243 | this->public.handler.release = (void(*)(attribute_handler_t*, identification_t*, configuration_attribute_type_t, chunk_t))release; | |
b5a2055f | 244 | this->public.handler.create_attribute_enumerator = (enumerator_t*(*)(attribute_handler_t*, identification_t *server, host_t *vip))create_attribute_enumerator; |
4819ec6a | 245 | this->public.destroy = (void(*)(resolve_handler_t*))destroy; |
7daf5226 | 246 | |
3901937d | 247 | this->mutex = mutex_create(MUTEX_TYPE_DEFAULT); |
3e2419eb | 248 | this->file = lib->settings->alloc_str(lib->settings, |
9a0333fa | 249 | "%s.plugins.resolve.file", RESOLV_CONF, hydra->daemon); |
7daf5226 | 250 | |
7f56b494 MW |
251 | return &this->public; |
252 | } | |
253 |