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

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: checkpoint: connect fails but gets ipconfig data 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 *
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 70
71 struct vpn_driver_data { 71 struct vpn_driver_data {
72 const char *name; 72 const char *name;
73 const char *program; 73 const char *program;
74 struct vpn_driver *vpn_driver; 74 struct vpn_driver *vpn_driver;
75 struct connman_provider_driver provider_driver; 75 struct connman_provider_driver provider_driver;
76 }; 76 };
77 77
78 static GHashTable *driver_hash = NULL; 78 static GHashTable *driver_hash = NULL;
79 79
80 static int kill_tun(char *tun_name) 80 static int kill_tun(struct connman_provider *provider)
81 { 81 {
82 struct vpn_data *data = connman_provider_get_data(provider);
83 struct vpn_driver_data *vpn_driver_data;
84 const char *name;
82 struct ifreq ifr; 85 struct ifreq ifr;
83 int fd, err; 86 int fd, err;
84 87
88 if (data == NULL)
89 return -1;
90
91 name = connman_provider_get_driver_name(provider);
92 vpn_driver_data = g_hash_table_lookup(driver_hash, name);
93
94 if (vpn_driver_data && vpn_driver_data->vpn_driver &&
Sam Leffler 2011/03/04 17:47:45 check ptr's against NULL
kmixter1 2011/03/05 09:30:51 Done.
95 vpn_driver_data->vpn_driver->flags == VPN_FLAG_NO_TUN)
96 return 0;
97
85 memset(&ifr, 0, sizeof(ifr)); 98 memset(&ifr, 0, sizeof(ifr));
86 ifr.ifr_flags = IFF_TUN | IFF_NO_PI; 99 ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
87 » strncpy(ifr.ifr_name, tun_name, sizeof(ifr.ifr_name)); 100 » strncpy(ifr.ifr_name, data->if_name, sizeof(ifr.ifr_name));
88 101
89 fd = open("/dev/net/tun", O_RDWR); 102 fd = open("/dev/net/tun", O_RDWR);
90 if (fd < 0) { 103 if (fd < 0) {
91 err = -errno; 104 err = -errno;
92 connman_error("Failed to open /dev/net/tun to device %s: %s", 105 connman_error("Failed to open /dev/net/tun to device %s: %s",
93 » » » tun_name, strerror(errno)); 106 » » » data->if_name, strerror(errno));
94 return err; 107 return err;
95 } 108 }
96 109
97 if (ioctl(fd, TUNSETIFF, (void *)&ifr)) { 110 if (ioctl(fd, TUNSETIFF, (void *)&ifr)) {
98 err = -errno; 111 err = -errno;
99 connman_error("Failed to TUNSETIFF for device %s to it: %s", 112 connman_error("Failed to TUNSETIFF for device %s to it: %s",
100 » » » tun_name, strerror(errno)); 113 » » » data->if_name, strerror(errno));
101 close(fd); 114 close(fd);
102 return err; 115 return err;
103 } 116 }
104 117
105 if (ioctl(fd, TUNSETPERSIST, 0)) { 118 if (ioctl(fd, TUNSETPERSIST, 0)) {
106 err = -errno; 119 err = -errno;
107 connman_error("Failed to set tun device %s nonpersistent: %s", 120 connman_error("Failed to set tun device %s nonpersistent: %s",
108 » » » tun_name, strerror(errno)); 121 » » » data->if_name, strerror(errno));
109 close(fd); 122 close(fd);
110 return err; 123 return err;
111 } 124 }
112 close(fd); 125 close(fd);
113 » _DBG_VPN("Killed tun device %s", tun_name); 126 » _DBG_VPN("Killed tun device %s", data->if_name);
114 return 0; 127 return 0;
115 } 128 }
116 129
117 void vpn_died(struct connman_task *task, void *user_data) 130 void vpn_died(struct connman_task *task, void *user_data)
118 { 131 {
119 struct connman_provider *provider = user_data; 132 struct connman_provider *provider = user_data;
120 struct vpn_data *data = connman_provider_get_data(provider); 133 struct vpn_data *data = connman_provider_get_data(provider);
121 int state = data->state; 134 int state = data->state;
122 135
123 _DBG_VPN("provider %p data %p", provider, data); 136 _DBG_VPN("provider %p data %p", provider, data);
124 137
125 if (!data) 138 if (!data)
126 goto vpn_exit; 139 goto vpn_exit;
127 140
128 » kill_tun(data->if_name); 141 » kill_tun(provider);
129 connman_provider_set_data(provider, NULL); 142 connman_provider_set_data(provider, NULL);
130 connman_rtnl_remove_watch(data->watch); 143 connman_rtnl_remove_watch(data->watch);
131 144
132 vpn_exit: 145 vpn_exit:
133 if (state != VPN_STATE_READY && state != VPN_STATE_DISCONNECT) 146 if (state != VPN_STATE_READY && state != VPN_STATE_DISCONNECT)
134 connman_provider_set_state(provider, 147 connman_provider_set_state(provider,
135 CONNMAN_PROVIDER_STATE_FAILURE); 148 CONNMAN_PROVIDER_STATE_FAILURE);
136 else 149 else
137 connman_provider_set_state(provider, 150 connman_provider_set_state(provider,
138 CONNMAN_PROVIDER_STATE_IDLE); 151 CONNMAN_PROVIDER_STATE_IDLE);
139 152
140 connman_provider_set_index(provider, -1); 153 connman_provider_set_index(provider, -1);
141 connman_provider_unref(data->provider); 154 connman_provider_unref(data->provider);
142 g_free(data); 155 g_free(data);
143 156
144 connman_task_destroy(task); 157 connman_task_destroy(task);
145 } 158 }
146 159
160 int vpn_set_ifname(struct connman_provider *provider, const char *ifname)
161 {
162 struct vpn_data *data = connman_provider_get_data(provider);
163 int index;
164
165 if (ifname == NULL || data == NULL)
Sam Leffler 2011/03/04 17:47:45 need debug/error msgs
kmixter1 2011/03/05 09:30:51 Done.
166 return -EIO;
167
168 index = connman_inet_ifindex(ifname);
169 if (index < 0)
Sam Leffler 2011/03/04 17:47:45 need msg unless connman_inet_ifindex already compl
kmixter1 2011/03/05 09:30:51 It doesn't, so added.
170 return -EIO;
171
172 data->if_name = (char *)g_strdup(ifname);
173 connman_provider_set_index(provider, index);
174
175 return 0;
176 }
177
147 static void vpn_newlink(const char *ifname, unsigned flags, unsigned change, void *user_data) 178 static void vpn_newlink(const char *ifname, unsigned flags, unsigned change, void *user_data)
148 { 179 {
149 struct connman_provider *provider = user_data; 180 struct connman_provider *provider = user_data;
150 struct vpn_data *data = connman_provider_get_data(provider); 181 struct vpn_data *data = connman_provider_get_data(provider);
151 182
152 if ((data->flags & IFF_UP) != (flags & IFF_UP)) { 183 if ((data->flags & IFF_UP) != (flags & IFF_UP)) {
153 if (flags & IFF_UP) { 184 if (flags & IFF_UP) {
154 data->state = VPN_STATE_READY; 185 data->state = VPN_STATE_READY;
155 connman_provider_set_state(provider, 186 connman_provider_set_state(provider,
156 CONNMAN_PROVIDER_STATE_READY); 187 CONNMAN_PROVIDER_STATE_READY);
157 } 188 }
158 } 189 }
159 data->flags = flags; 190 data->flags = flags;
160 } 191 }
161 192
162 static void vpn_notify(struct connman_task *task, 193 static DBusMessage *vpn_notify(struct connman_task *task,
163 DBusMessage *msg, void *user_data) 194 DBusMessage *msg, void *user_data)
164 { 195 {
165 struct connman_provider *provider = user_data; 196 struct connman_provider *provider = user_data;
166 struct vpn_data *data; 197 struct vpn_data *data;
167 struct vpn_driver_data *vpn_driver_data; 198 struct vpn_driver_data *vpn_driver_data;
168 const char *name; 199 const char *name;
169 int state, index; 200 int state, index;
170 201
171 data = connman_provider_get_data(provider); 202 data = connman_provider_get_data(provider);
172 203
173 name = connman_provider_get_driver_name(provider); 204 name = connman_provider_get_driver_name(provider);
174 vpn_driver_data = g_hash_table_lookup(driver_hash, name); 205 vpn_driver_data = g_hash_table_lookup(driver_hash, name);
175 if (vpn_driver_data == NULL) 206 if (vpn_driver_data == NULL)
176 » » return; 207 » » return NULL;
177 208
178 state = vpn_driver_data->vpn_driver->notify(msg, provider); 209 state = vpn_driver_data->vpn_driver->notify(msg, provider);
179 switch (state) { 210 switch (state) {
180 case VPN_STATE_CONNECT: 211 case VPN_STATE_CONNECT:
181 case VPN_STATE_READY: 212 case VPN_STATE_READY:
182 index = connman_provider_get_index(provider); 213 index = connman_provider_get_index(provider);
183 data->watch = connman_rtnl_add_newlink_watch(index, 214 data->watch = connman_rtnl_add_newlink_watch(index,
184 vpn_newlink, provider); 215 vpn_newlink, provider);
185 connman_inet_ifup(index); 216 connman_inet_ifup(index);
186 break; 217 break;
187 218
188 case VPN_STATE_UNKNOWN: 219 case VPN_STATE_UNKNOWN:
189 case VPN_STATE_IDLE: 220 case VPN_STATE_IDLE:
190 case VPN_STATE_DISCONNECT: 221 case VPN_STATE_DISCONNECT:
191 case VPN_STATE_FAILURE: 222 case VPN_STATE_FAILURE:
192 connman_provider_set_state(provider, 223 connman_provider_set_state(provider,
193 CONNMAN_PROVIDER_STATE_DISCONNECT); 224 CONNMAN_PROVIDER_STATE_DISCONNECT);
194 break; 225 break;
195 } 226 }
227
228 return NULL;
196 } 229 }
197 230
198 static int vpn_connect(struct connman_provider *provider) 231 static int vpn_create_tun(struct connman_provider *provider)
199 { 232 {
200 struct vpn_data *data = connman_provider_get_data(provider); 233 struct vpn_data *data = connman_provider_get_data(provider);
201 struct vpn_driver_data *vpn_driver_data;
202 struct ifreq ifr; 234 struct ifreq ifr;
203 const char *name;
204 int i, fd, index; 235 int i, fd, index;
205 int ret = 0; 236 int ret = 0;
206 237
207 » if (data != NULL) 238 » if (data == NULL)
208 return -EISCONN; 239 return -EISCONN;
209 240
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); 241 fd = open("/dev/net/tun", O_RDWR);
226 if (fd < 0) { 242 if (fd < 0) {
227 i = -errno; 243 i = -errno;
228 connman_error("%s: failed to open /dev/net/tun: %s", 244 connman_error("%s: failed to open /dev/net/tun: %s",
229 __func__, strerror(errno)); 245 __func__, strerror(errno));
230 ret = i; 246 ret = i;
231 goto exist_err; 247 goto exist_err;
232 } 248 }
233 249
234 memset(&ifr, 0, sizeof(ifr)); 250 memset(&ifr, 0, sizeof(ifr));
(...skipping 27 matching lines...) Expand all
262 close(fd); 278 close(fd);
263 ret = i; 279 ret = i;
264 goto exist_err; 280 goto exist_err;
265 } 281 }
266 282
267 close(fd); 283 close(fd);
268 284
269 index = connman_inet_ifindex(data->if_name); 285 index = connman_inet_ifindex(data->if_name);
270 if (index < 0) { 286 if (index < 0) {
271 connman_error("%s: failed to get tun ifindex", __func__); 287 connman_error("%s: failed to get tun ifindex", __func__);
272 » » kill_tun(data->if_name); 288 » » kill_tun(provider);
273 ret = -EIO; 289 ret = -EIO;
274 goto exist_err; 290 goto exist_err;
275 } 291 }
276 connman_provider_set_index(provider, index); 292 connman_provider_set_index(provider, index);
277 293
294 return 0;
295
296 exist_err:
297 return ret;
298 }
299
300 static int vpn_connect(struct connman_provider *provider)
301 {
302 struct vpn_data *data = connman_provider_get_data(provider);
303 struct vpn_driver_data *vpn_driver_data;
304 const char *name;
305 int ret = 0;
306
307 if (data != NULL)
Sam Leffler 2011/03/04 17:47:45 please add debug msg
kmixter1 2011/03/05 09:30:51 Done.
308 return -EISCONN;
309
310 data = g_try_new0(struct vpn_data, 1);
311 if (data == NULL)
312 return -ENOMEM;
313
314 data->provider = connman_provider_ref(provider);
315 data->watch = 0;
316 data->flags = 0;
317 data->task = NULL;
318 data->state = VPN_STATE_IDLE;
319
320 connman_provider_set_data(provider, data);
321
322 name = connman_provider_get_driver_name(provider);
323 vpn_driver_data = g_hash_table_lookup(driver_hash, name);
324
325 if (vpn_driver_data && vpn_driver_data->vpn_driver &&
Sam Leffler 2011/03/04 17:47:45 ptr cmp to NULL
kmixter1 2011/03/05 09:30:51 Done.
326 vpn_driver_data->vpn_driver->flags != VPN_FLAG_NO_TUN) {
327
328 ret = vpn_create_tun(provider);
329 if (ret < 0)
330 goto exist_err;
331 }
332
278 data->task = connman_task_create(vpn_driver_data->program); 333 data->task = connman_task_create(vpn_driver_data->program);
279 334
280 if (data->task == NULL) { 335 if (data->task == NULL) {
281 ret = -ENOMEM; 336 ret = -ENOMEM;
282 » » kill_tun(data->if_name); 337 » » kill_tun(provider);
283 goto exist_err; 338 goto exist_err;
284 } 339 }
285 340
286 if (connman_task_set_notify(data->task, "notify", 341 if (connman_task_set_notify(data->task, "notify",
287 vpn_notify, provider)) { 342 vpn_notify, provider)) {
288 ret = -ENOMEM; 343 ret = -ENOMEM;
289 » » kill_tun(data->if_name); 344 » » kill_tun(provider);
290 connman_task_destroy(data->task); 345 connman_task_destroy(data->task);
291 data->task = NULL; 346 data->task = NULL;
292 goto exist_err; 347 goto exist_err;
293 } 348 }
294 349
295 ret = vpn_driver_data->vpn_driver->connect(provider, data->task, 350 ret = vpn_driver_data->vpn_driver->connect(provider, data->task,
296 data->if_name); 351 data->if_name);
297 if (ret < 0) { 352 if (ret < 0) {
298 » » kill_tun(data->if_name); 353 » » kill_tun(provider);
299 connman_task_destroy(data->task); 354 connman_task_destroy(data->task);
300 data->task = NULL; 355 data->task = NULL;
301 goto exist_err; 356 goto exist_err;
302 } 357 }
303 358
304 _DBG_VPN("%s started with dev %s", 359 _DBG_VPN("%s started with dev %s",
305 vpn_driver_data->provider_driver.name, data->if_name); 360 vpn_driver_data->provider_driver.name, data->if_name);
306 361
307 data->state = VPN_STATE_CONNECT; 362 data->state = VPN_STATE_CONNECT;
308 363
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 data->state = VPN_STATE_DISCONNECT; 402 data->state = VPN_STATE_DISCONNECT;
348 connman_task_stop(data->task); 403 connman_task_stop(data->task);
349 404
350 return 0; 405 return 0;
351 } 406 }
352 407
353 static int vpn_remove(struct connman_provider *provider) 408 static int vpn_remove(struct connman_provider *provider)
354 { 409 {
355 struct vpn_data *data; 410 struct vpn_data *data;
356 411
357 data = connman_provider_get_data(provider); 412 data = connman_provider_get_data(provider);
Sam Leffler 2011/03/04 17:47:45 not sure i follow why it's ok to drop set_data cal
kmixter1 2011/03/05 09:30:51 This is from upstream, but I agree. I see why it
358 connman_provider_set_data(provider, NULL);
359 if (data == NULL) 413 if (data == NULL)
360 return 0; 414 return 0;
361 415
362 if (data->watch != 0) 416 if (data->watch != 0)
363 connman_rtnl_remove_watch(data->watch); 417 connman_rtnl_remove_watch(data->watch);
364 data->watch = 0; 418 data->watch = 0;
365 connman_task_stop(data->task); 419 connman_task_stop(data->task);
366 420
367 g_usleep(G_USEC_PER_SEC); 421 g_usleep(G_USEC_PER_SEC);
368 » kill_tun(data->if_name); 422 » kill_tun(provider);
369 return 0; 423 return 0;
370 } 424 }
371 425
372 int vpn_register(const char *name, struct vpn_driver *vpn_driver, 426 int vpn_register(const char *name, struct vpn_driver *vpn_driver,
373 const char *program) 427 const char *program)
374 { 428 {
375 struct vpn_driver_data *data; 429 struct vpn_driver_data *data;
376 430
377 _DBG_VPN("name %s program %s", name, program); 431 _DBG_VPN("name %s program %s", name, program);
378 432
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 if (data == NULL) 466 if (data == NULL)
413 return; 467 return;
414 468
415 connman_provider_driver_unregister(&data->provider_driver); 469 connman_provider_driver_unregister(&data->provider_driver);
416 470
417 g_hash_table_remove(driver_hash, name); 471 g_hash_table_remove(driver_hash, name);
418 472
419 if (g_hash_table_size(driver_hash) == 0) 473 if (g_hash_table_size(driver_hash) == 0)
420 g_hash_table_destroy(driver_hash); 474 g_hash_table_destroy(driver_hash);
421 } 475 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698