Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(707)

Side by Side Diff: plugins/vpn.c

Issue 6513009: flimflam: Add L2TP/IPsec VPN plugin (Closed) Base URL: ssh://git@gitrw.chromium.org:9222/flimflam.git@master
Patch Set: rebase on ToT, fix style issues in connect-vpn Created 9 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * 2 *
3 * Connection Manager 3 * Connection Manager
4 * 4 *
5 * Copyright (C) 2007-2010 Intel Corporation. All rights reserved. 5 * Copyright (C) 2007-2010 Intel Corporation. All rights reserved.
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation. 9 * published by the Free Software Foundation.
10 * 10 *
11 * This program is distributed in the hope that it will be useful, 11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details. 14 * GNU General Public License for more details.
15 * 15 *
16 * You should have received a copy of the GNU General Public License 16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software 17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 * 19 *
20 */ 20 */
21 21
22 /* 22 /*
23 * Support for vpn plugins. Common code to manage a provider object, 23 * Support for vpn plugins. Common code to manage a provider object,
24 * tun device and a task associated with an external vpn process. The 24 * tun device and a task associated with an external vpn process. The
25 * vpn plugin is responsible for launching the external process and 25 * vpn plugin is responsible for launching the external process and
26 * handling notification callbacks to clock the provider state machine. 26 * handling notification callbacks to clock the provider state machine.
27 * 27 *
28 * TODO(sleffler) currently assumes extern vpn service uses tun but not all do
29 * TODO(sleffler) seems to make more sense in src than plugins 28 * TODO(sleffler) seems to make more sense in src than plugins
30 */ 29 */
31 30
32 #ifdef HAVE_CONFIG_H 31 #ifdef HAVE_CONFIG_H
33 #include <config.h> 32 #include <config.h>
34 #endif 33 #endif
35 34
36 #include <string.h> 35 #include <string.h>
37 #include <fcntl.h> 36 #include <fcntl.h>
38 #include <unistd.h> 37 #include <unistd.h>
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 69
71 struct vpn_driver_data { 70 struct vpn_driver_data {
72 const char *name; 71 const char *name;
73 const char *program; 72 const char *program;
74 struct vpn_driver *vpn_driver; 73 struct vpn_driver *vpn_driver;
75 struct connman_provider_driver provider_driver; 74 struct connman_provider_driver provider_driver;
76 }; 75 };
77 76
78 static GHashTable *driver_hash = NULL; 77 static GHashTable *driver_hash = NULL;
79 78
80 static int kill_tun(char *tun_name) 79 static int kill_tun(struct connman_provider *provider)
81 { 80 {
81 struct vpn_data *data = connman_provider_get_data(provider);
82 struct vpn_driver_data *vpn_driver_data;
83 const char *name;
82 struct ifreq ifr; 84 struct ifreq ifr;
83 int fd, err; 85 int fd, err;
84 86
87 if (data == NULL)
88 return -1;
89
90 name = connman_provider_get_driver_name(provider);
91 vpn_driver_data = g_hash_table_lookup(driver_hash, name);
92
93 if (vpn_driver_data != NULL && vpn_driver_data->vpn_driver !=NULL &&
94 vpn_driver_data->vpn_driver->flags == VPN_FLAG_NO_TUN)
95 return 0;
96
85 memset(&ifr, 0, sizeof(ifr)); 97 memset(&ifr, 0, sizeof(ifr));
86 ifr.ifr_flags = IFF_TUN | IFF_NO_PI; 98 ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
87 » strncpy(ifr.ifr_name, tun_name, sizeof(ifr.ifr_name)); 99 » strncpy(ifr.ifr_name, data->if_name, sizeof(ifr.ifr_name));
thutt 2011/03/17 15:02:21 (nit) It looks like you are adding tabs in a file
kmixter1 2011/03/17 17:52:20 It's the latter. The file is mostly tabs but I di
88 100
89 fd = open("/dev/net/tun", O_RDWR); 101 fd = open("/dev/net/tun", O_RDWR);
90 if (fd < 0) { 102 if (fd < 0) {
91 err = -errno; 103 err = -errno;
92 connman_error("Failed to open /dev/net/tun to device %s: %s", 104 connman_error("Failed to open /dev/net/tun to device %s: %s",
93 » » » tun_name, strerror(errno)); 105 » » » data->if_name, strerror(errno));
94 return err; 106 return err;
95 } 107 }
96 108
97 if (ioctl(fd, TUNSETIFF, (void *)&ifr)) { 109 if (ioctl(fd, TUNSETIFF, (void *)&ifr)) {
98 err = -errno; 110 err = -errno;
99 connman_error("Failed to TUNSETIFF for device %s to it: %s", 111 connman_error("Failed to TUNSETIFF for device %s to it: %s",
100 » » » tun_name, strerror(errno)); 112 » » » data->if_name, strerror(errno));
101 close(fd); 113 close(fd);
102 return err; 114 return err;
103 } 115 }
104 116
105 if (ioctl(fd, TUNSETPERSIST, 0)) { 117 if (ioctl(fd, TUNSETPERSIST, 0)) {
106 err = -errno; 118 err = -errno;
107 connman_error("Failed to set tun device %s nonpersistent: %s", 119 connman_error("Failed to set tun device %s nonpersistent: %s",
108 » » » tun_name, strerror(errno)); 120 » » » data->if_name, strerror(errno));
109 close(fd); 121 close(fd);
110 return err; 122 return err;
111 } 123 }
112 close(fd); 124 close(fd);
113 » _DBG_VPN("Killed tun device %s", tun_name); 125 » _DBG_VPN("Killed tun device %s", data->if_name);
114 return 0; 126 return 0;
115 } 127 }
116 128
117 void vpn_died(struct connman_task *task, void *user_data) 129 void vpn_died(struct connman_task *task, void *user_data)
118 { 130 {
119 struct connman_provider *provider = user_data; 131 struct connman_provider *provider = user_data;
120 struct vpn_data *data = connman_provider_get_data(provider); 132 struct vpn_data *data = connman_provider_get_data(provider);
121 int state = data->state; 133 int state = data->state;
122 134
123 _DBG_VPN("provider %p data %p", provider, data); 135 _DBG_VPN("provider %p data %p", provider, data);
124 136
125 if (!data) 137 if (!data)
126 goto vpn_exit; 138 goto vpn_exit;
127 139
128 » kill_tun(data->if_name); 140 » kill_tun(provider);
129 connman_provider_set_data(provider, NULL); 141 connman_provider_set_data(provider, NULL);
130 connman_rtnl_remove_watch(data->watch); 142 connman_rtnl_remove_watch(data->watch);
131 143
132 vpn_exit: 144 vpn_exit:
133 if (state != VPN_STATE_READY && state != VPN_STATE_DISCONNECT) 145 if (state != VPN_STATE_READY && state != VPN_STATE_DISCONNECT)
134 connman_provider_set_state(provider, 146 connman_provider_set_state(provider,
135 CONNMAN_PROVIDER_STATE_FAILURE); 147 CONNMAN_PROVIDER_STATE_FAILURE);
136 else 148 else
137 connman_provider_set_state(provider, 149 connman_provider_set_state(provider,
138 CONNMAN_PROVIDER_STATE_IDLE); 150 CONNMAN_PROVIDER_STATE_IDLE);
139 151
140 connman_provider_set_index(provider, -1); 152 connman_provider_set_index(provider, -1);
141 connman_provider_unref(data->provider); 153 connman_provider_unref(data->provider);
142 g_free(data); 154 g_free(data);
143 155
144 connman_task_destroy(task); 156 connman_task_destroy(task);
145 } 157 }
146 158
159 int vpn_set_ifname(struct connman_provider *provider, const char *ifname)
160 {
161 struct vpn_data *data = connman_provider_get_data(provider);
162 int index;
163
164 if (data == NULL) {
165 _DBG_VPN("%s: provider data not accessible", __func__);
166 return -EIO;
167 }
168
169 if (ifname == NULL) {
170 _DBG_VPN("%s: ifname not provided", __func__);
171 return -EIO;
172 }
173
174 index = connman_inet_ifindex(ifname);
175 if (index < 0) {
176 _DBG_VPN("%s: could not get ifindex from %s", __func__, ifname);
177 return -EIO;
178 }
179
180 data->if_name = (char *)g_strdup(ifname);
181 connman_provider_set_index(provider, index);
182
183 /* Set connect state to retry creating ipconfig with index above. */
184 connman_provider_set_state(provider, CONNMAN_PROVIDER_STATE_CONNECT);
185
186 return 0;
187 }
188
147 static void vpn_newlink(const char *ifname, unsigned flags, unsigned change, void *user_data) 189 static void vpn_newlink(const char *ifname, unsigned flags, unsigned change, void *user_data)
148 { 190 {
149 struct connman_provider *provider = user_data; 191 struct connman_provider *provider = user_data;
150 struct vpn_data *data = connman_provider_get_data(provider); 192 struct vpn_data *data = connman_provider_get_data(provider);
151 193
152 if ((data->flags & IFF_UP) != (flags & IFF_UP)) { 194 if ((data->flags & IFF_UP) != (flags & IFF_UP)) {
153 if (flags & IFF_UP) { 195 if (flags & IFF_UP) {
154 data->state = VPN_STATE_READY; 196 data->state = VPN_STATE_READY;
155 connman_provider_set_state(provider, 197 connman_provider_set_state(provider,
156 CONNMAN_PROVIDER_STATE_READY); 198 CONNMAN_PROVIDER_STATE_READY);
157 } 199 }
158 } 200 }
159 data->flags = flags; 201 data->flags = flags;
160 } 202 }
161 203
162 static void vpn_notify(struct connman_task *task, 204 static DBusMessage *vpn_notify(struct connman_task *task,
thutt 2011/03/17 15:02:21 I don't understand why you changed this function t
kmixter1 2011/03/17 17:52:20 This is the default notification function if the p
163 DBusMessage *msg, void *user_data) 205 DBusMessage *msg, void *user_data)
164 { 206 {
165 struct connman_provider *provider = user_data; 207 struct connman_provider *provider = user_data;
166 struct vpn_data *data; 208 struct vpn_data *data;
167 struct vpn_driver_data *vpn_driver_data; 209 struct vpn_driver_data *vpn_driver_data;
168 const char *name; 210 const char *name;
169 int state, index; 211 int state, index;
170 212
171 data = connman_provider_get_data(provider); 213 data = connman_provider_get_data(provider);
172 214
173 name = connman_provider_get_driver_name(provider); 215 name = connman_provider_get_driver_name(provider);
174 vpn_driver_data = g_hash_table_lookup(driver_hash, name); 216 vpn_driver_data = g_hash_table_lookup(driver_hash, name);
175 if (vpn_driver_data == NULL) 217 if (vpn_driver_data == NULL)
176 » » return; 218 » » return NULL;
177 219
178 state = vpn_driver_data->vpn_driver->notify(msg, provider); 220 state = vpn_driver_data->vpn_driver->notify(msg, provider);
179 switch (state) { 221 switch (state) {
180 case VPN_STATE_CONNECT: 222 case VPN_STATE_CONNECT:
181 case VPN_STATE_READY: 223 case VPN_STATE_READY:
182 index = connman_provider_get_index(provider); 224 index = connman_provider_get_index(provider);
183 data->watch = connman_rtnl_add_newlink_watch(index, 225 data->watch = connman_rtnl_add_newlink_watch(index,
184 vpn_newlink, provider); 226 vpn_newlink, provider);
185 connman_inet_ifup(index); 227 connman_inet_ifup(index);
186 break; 228 break;
187 229
188 case VPN_STATE_UNKNOWN: 230 case VPN_STATE_UNKNOWN:
189 case VPN_STATE_IDLE: 231 case VPN_STATE_IDLE:
190 case VPN_STATE_DISCONNECT: 232 case VPN_STATE_DISCONNECT:
191 case VPN_STATE_FAILURE: 233 case VPN_STATE_FAILURE:
192 connman_provider_set_state(provider, 234 connman_provider_set_state(provider,
193 CONNMAN_PROVIDER_STATE_DISCONNECT); 235 CONNMAN_PROVIDER_STATE_DISCONNECT);
194 break; 236 break;
195 } 237 }
238
239 return NULL;
196 } 240 }
197 241
198 static int vpn_connect(struct connman_provider *provider) 242 static int vpn_create_tun(struct connman_provider *provider)
199 { 243 {
200 struct vpn_data *data = connman_provider_get_data(provider); 244 struct vpn_data *data = connman_provider_get_data(provider);
201 struct vpn_driver_data *vpn_driver_data;
202 struct ifreq ifr; 245 struct ifreq ifr;
203 const char *name;
204 int i, fd, index; 246 int i, fd, index;
205 int ret = 0; 247 int ret = 0;
206 248
207 » if (data != NULL) 249 » if (data == NULL)
thutt 2011/03/17 15:02:21 I'm not a networking person, but is this returning
kmixter1 2011/03/17 17:52:20 Done and added a message.
208 return -EISCONN; 250 return -EISCONN;
209 251
210 data = g_try_new0(struct vpn_data, 1);
211 if (data == NULL)
212 return -ENOMEM;
213
214 data->provider = connman_provider_ref(provider);
215 data->watch = 0;
216 data->flags = 0;
217 data->task = NULL;
218 data->state = VPN_STATE_IDLE;
219
220 connman_provider_set_data(provider, data);
221
222 name = connman_provider_get_driver_name(provider);
223 vpn_driver_data = g_hash_table_lookup(driver_hash, name);
224
225 fd = open("/dev/net/tun", O_RDWR); 252 fd = open("/dev/net/tun", O_RDWR);
226 if (fd < 0) { 253 if (fd < 0) {
227 i = -errno; 254 i = -errno;
228 connman_error("%s: failed to open /dev/net/tun: %s", 255 connman_error("%s: failed to open /dev/net/tun: %s",
229 __func__, strerror(errno)); 256 __func__, strerror(errno));
230 ret = i; 257 ret = i;
231 goto exist_err; 258 goto exist_err;
232 } 259 }
233 260
234 memset(&ifr, 0, sizeof(ifr)); 261 memset(&ifr, 0, sizeof(ifr));
(...skipping 27 matching lines...) Expand all
262 close(fd); 289 close(fd);
263 ret = i; 290 ret = i;
264 goto exist_err; 291 goto exist_err;
265 } 292 }
266 293
267 close(fd); 294 close(fd);
268 295
269 index = connman_inet_ifindex(data->if_name); 296 index = connman_inet_ifindex(data->if_name);
270 if (index < 0) { 297 if (index < 0) {
271 connman_error("%s: failed to get tun ifindex", __func__); 298 connman_error("%s: failed to get tun ifindex", __func__);
272 » » kill_tun(data->if_name); 299 » » kill_tun(provider);
273 ret = -EIO; 300 ret = -EIO;
274 goto exist_err; 301 goto exist_err;
275 } 302 }
276 connman_provider_set_index(provider, index); 303 connman_provider_set_index(provider, index);
277 304
305 return 0;
306
307 exist_err:
308 return ret;
309 }
310
311 static int vpn_connect(struct connman_provider *provider)
312 {
313 struct vpn_data *data = connman_provider_get_data(provider);
314 struct vpn_driver_data *vpn_driver_data;
315 const char *name;
316 int ret = 0;
317
318 if (data != NULL) {
thutt 2011/03/17 15:02:21 I'm puzzled by the condition -vs- the message here
kmixter1 2011/03/17 17:52:20 Updated the error message - I copy and pasted wron
319 _DBG_VPN("%s: unable to access provider data", __func__);
320 return -EISCONN;
321 }
322
323 data = g_try_new0(struct vpn_data, 1);
324 if (data == NULL)
325 return -ENOMEM;
326
327 data->provider = connman_provider_ref(provider);
328 data->watch = 0;
329 data->flags = 0;
330 data->task = NULL;
331 data->state = VPN_STATE_IDLE;
332
333 connman_provider_set_data(provider, data);
334
335 name = connman_provider_get_driver_name(provider);
336 vpn_driver_data = g_hash_table_lookup(driver_hash, name);
337
338 if (vpn_driver_data != NULL && vpn_driver_data->vpn_driver != NULL &&
339 vpn_driver_data->vpn_driver->flags != VPN_FLAG_NO_TUN) {
340
341 ret = vpn_create_tun(provider);
342 if (ret < 0)
343 goto exist_err;
344 }
345
278 data->task = connman_task_create(vpn_driver_data->program); 346 data->task = connman_task_create(vpn_driver_data->program);
279 347
280 if (data->task == NULL) { 348 if (data->task == NULL) {
281 ret = -ENOMEM; 349 ret = -ENOMEM;
282 » » kill_tun(data->if_name); 350 » » kill_tun(provider);
283 goto exist_err; 351 goto exist_err;
284 } 352 }
285 353
286 if (connman_task_set_notify(data->task, "notify", 354 if (connman_task_set_notify(data->task, "notify",
287 vpn_notify, provider)) { 355 vpn_notify, provider)) {
288 ret = -ENOMEM; 356 ret = -ENOMEM;
289 » » kill_tun(data->if_name); 357 » » kill_tun(provider);
290 connman_task_destroy(data->task); 358 connman_task_destroy(data->task);
291 data->task = NULL; 359 data->task = NULL;
292 goto exist_err; 360 goto exist_err;
293 } 361 }
294 362
295 ret = vpn_driver_data->vpn_driver->connect(provider, data->task, 363 ret = vpn_driver_data->vpn_driver->connect(provider, data->task,
296 data->if_name); 364 data->if_name);
297 if (ret < 0) { 365 if (ret < 0) {
298 » » kill_tun(data->if_name); 366 » » kill_tun(provider);
299 connman_task_destroy(data->task); 367 connman_task_destroy(data->task);
300 data->task = NULL; 368 data->task = NULL;
301 goto exist_err; 369 goto exist_err;
302 } 370 }
303 371
304 _DBG_VPN("%s started with dev %s", 372 _DBG_VPN("%s started with dev %s",
305 vpn_driver_data->provider_driver.name, data->if_name); 373 vpn_driver_data->provider_driver.name, data->if_name);
306 374
307 data->state = VPN_STATE_CONNECT; 375 data->state = VPN_STATE_CONNECT;
308 376
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 connman_task_stop(data->task); 416 connman_task_stop(data->task);
349 417
350 return 0; 418 return 0;
351 } 419 }
352 420
353 static int vpn_remove(struct connman_provider *provider) 421 static int vpn_remove(struct connman_provider *provider)
354 { 422 {
355 struct vpn_data *data; 423 struct vpn_data *data;
356 424
357 data = connman_provider_get_data(provider); 425 data = connman_provider_get_data(provider);
358 connman_provider_set_data(provider, NULL);
359 if (data == NULL) 426 if (data == NULL)
360 return 0; 427 return 0;
361 428
362 if (data->watch != 0) 429 if (data->watch != 0)
363 connman_rtnl_remove_watch(data->watch); 430 connman_rtnl_remove_watch(data->watch);
364 data->watch = 0; 431 data->watch = 0;
365 connman_task_stop(data->task); 432 connman_task_stop(data->task);
366 433
367 g_usleep(G_USEC_PER_SEC); 434 g_usleep(G_USEC_PER_SEC);
368 » kill_tun(data->if_name); 435 » kill_tun(provider);
436 » connman_provider_set_data(provider, NULL);
369 return 0; 437 return 0;
370 } 438 }
371 439
372 int vpn_register(const char *name, struct vpn_driver *vpn_driver, 440 int vpn_register(const char *name, struct vpn_driver *vpn_driver,
373 const char *program) 441 const char *program)
374 { 442 {
375 struct vpn_driver_data *data; 443 struct vpn_driver_data *data;
376 444
377 _DBG_VPN("name %s program %s", name, program); 445 _DBG_VPN("name %s program %s", name, program);
378 446
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 if (data == NULL) 480 if (data == NULL)
413 return; 481 return;
414 482
415 connman_provider_driver_unregister(&data->provider_driver); 483 connman_provider_driver_unregister(&data->provider_driver);
416 484
417 g_hash_table_remove(driver_hash, name); 485 g_hash_table_remove(driver_hash, name);
418 486
419 if (g_hash_table_size(driver_hash) == 0) 487 if (g_hash_table_size(driver_hash) == 0)
420 g_hash_table_destroy(driver_hash); 488 g_hash_table_destroy(driver_hash);
421 } 489 }
OLDNEW
« no previous file with comments | « plugins/vpn.h ('k') | scripts/libppp-plugin.c » ('j') | test/connect-vpn » ('J')

Powered by Google App Engine
This is Rietveld 408576698