Be a little more verbose why a peer_cfg is inacceptable
[strongswan.git] / src / libtnccs / tnc / tnc.c
1 /*
2 * Copyright (C) 2011 Andreas Steffen
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 "tnc.h"
17
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #include <sys/mman.h>
21 #include <unistd.h>
22 #include <errno.h>
23 #include <fcntl.h>
24
25 #include <utils/lexparser.h>
26 #include <utils/debug.h>
27
28 typedef struct private_tnc_t private_tnc_t;
29
30 typedef tnccs_manager_t *(*tnc_create_tnccs_manager_t)(void);
31 typedef imc_manager_t *(*tnc_create_imc_manager_t)(void);
32 typedef imv_manager_t *(*tnc_create_imv_manager_t)(void);
33
34 /**
35 * Private additions to tnc_t.
36 */
37 struct private_tnc_t {
38
39 /**
40 * Public members of tnc_t.
41 */
42 tnc_t public;
43
44 /**
45 * Number of times we have been initialized
46 */
47 refcount_t ref;
48 };
49
50 /**
51 * Single instance of tnc_t.
52 */
53 tnc_t *tnc;
54
55 /**
56 * Described in header.
57 */
58 void libtnccs_init(void)
59 {
60 private_tnc_t *this;
61
62 if (tnc)
63 { /* already initialized, increase refcount */
64 this = (private_tnc_t*)tnc;
65 ref_get(&this->ref);
66 return;
67 }
68
69 INIT(this,
70 .public = {
71 },
72 .ref = 1,
73 );
74
75 tnc = &this->public;
76 }
77
78 /**
79 * Described in header.
80 */
81 void libtnccs_deinit(void)
82 {
83 private_tnc_t *this = (private_tnc_t*)tnc;
84
85 if (!this || !ref_put(&this->ref))
86 { /* have more users */
87 return;
88 }
89
90 free(this);
91 tnc = NULL;
92 }
93
94 static bool load_imcvs_from_config(char *filename, bool is_imc)
95 {
96 bool success = FALSE;
97 int fd, line_nr = 0;
98 chunk_t src, line;
99 struct stat sb;
100 void *addr;
101 char *label;
102
103 label = is_imc ? "IMC" : "IMV";
104
105 DBG1(DBG_TNC, "loading %ss from '%s'", label, filename);
106 fd = open(filename, O_RDONLY);
107 if (fd == -1)
108 {
109 DBG1(DBG_TNC, "opening configuration file '%s' failed: %s", filename,
110 strerror(errno));
111 return FALSE;
112 }
113 if (fstat(fd, &sb) == -1)
114 {
115 DBG1(DBG_LIB, "getting file size of '%s' failed: %s", filename,
116 strerror(errno));
117 close(fd);
118 return FALSE;
119 }
120 addr = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
121 if (addr == MAP_FAILED)
122 {
123 DBG1(DBG_LIB, "mapping '%s' failed: %s", filename, strerror(errno));
124 close(fd);
125 return FALSE;
126 }
127 src = chunk_create(addr, sb.st_size);
128
129 while (fetchline(&src, &line))
130 {
131 char *name, *path;
132 chunk_t token;
133
134 line_nr++;
135
136 /* skip comments or empty lines */
137 if (*line.ptr == '#' || !eat_whitespace(&line))
138 {
139 continue;
140 }
141
142 /* determine keyword */
143 if (!extract_token(&token, ' ', &line))
144 {
145 DBG1(DBG_TNC, "line %d: keyword must be followed by a space",
146 line_nr);
147 break;
148 }
149
150 /* only interested in IMCs or IMVs depending on label */
151 if (!match(label, &token))
152 {
153 continue;
154 }
155
156 /* advance to the IMC/IMV name and extract it */
157 if (!extract_token(&token, '"', &line) ||
158 !extract_token(&token, '"', &line))
159 {
160 DBG1(DBG_TNC, "line %d: %s name must be set in double quotes",
161 line_nr, label);
162 break;
163 }
164
165 /* copy the IMC/IMV name */
166 name = strndup(token.ptr, token.len);
167
168 /* advance to the IMC/IMV path and extract it */
169 if (!eat_whitespace(&line))
170 {
171 DBG1(DBG_TNC, "line %d: %s path is missing", line_nr, label);
172 free(name);
173 break;
174 }
175 if (!extract_token(&token, ' ', &line))
176 {
177 token = line;
178 }
179
180 /* copy the IMC/IMV path */
181 path = strndup(token.ptr, token.len);
182
183 /* load and register an IMC/IMV instance */
184 if (is_imc)
185 {
186 success = tnc->imcs->load(tnc->imcs, name, path);
187 }
188 else
189 {
190 success = tnc->imvs->load(tnc->imvs, name, path);
191 }
192 free(name);
193 free(path);
194 if (!success)
195 {
196 break;
197 }
198 }
199 munmap(addr, sb.st_size);
200 close(fd);
201 return success;
202 }
203
204 /**
205 * Described in header.
206 */
207 bool tnc_manager_register(plugin_t *plugin, plugin_feature_t *feature,
208 bool reg, void *data)
209 {
210 bool load_imcvs = FALSE;
211 bool is_imc = FALSE;
212
213 if (feature->type == FEATURE_CUSTOM)
214 {
215 if (streq(feature->arg.custom, "tnccs-manager"))
216 {
217 if (reg)
218 {
219 tnc->tnccs = ((tnc_create_tnccs_manager_t)data)();
220 }
221 else
222 {
223 tnc->tnccs->destroy(tnc->tnccs);
224 tnc->tnccs = NULL;
225 }
226 }
227 else if (streq(feature->arg.custom, "imc-manager"))
228 {
229 if (reg)
230 {
231 tnc->imcs = ((tnc_create_imc_manager_t)data)();
232 is_imc = TRUE;
233 load_imcvs = TRUE;
234 }
235 else
236 {
237 tnc->imcs->destroy(tnc->imcs);
238 tnc->imcs = NULL;
239 }
240 }
241 else if (streq(feature->arg.custom, "imv-manager"))
242 {
243 if (reg)
244 {
245 tnc->imvs = ((tnc_create_imv_manager_t)data)();
246 is_imc = FALSE;
247 load_imcvs = TRUE;
248 }
249 else
250 {
251 tnc->imvs->destroy(tnc->imvs);
252 tnc->imvs = NULL;
253 }
254 }
255 else
256 {
257 return FALSE;
258 }
259
260 if (load_imcvs)
261 {
262 load_imcvs_from_config(
263 lib->settings->get_str(lib->settings,
264 "libtnccs.tnc_config", "/etc/tnc_config"),
265 is_imc);
266 }
267 }
268 return TRUE;
269 }
270