]> git.ipfire.org Git - thirdparty/strongswan.git/blame - src/libhydra/plugins/resolve/resolve_handler.c
Use thread save settings alloc_str function where appropriate
[thirdparty/strongswan.git] / src / libhydra / plugins / resolve / resolve_handler.c
CommitLineData
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 24typedef 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 29struct 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 50static 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 115static 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 */
175typedef 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 */
185static 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 */
208static 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 228static 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 238resolve_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