OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |