Chromium Code Reviews| Index: plugins/vpn.c |
| diff --git a/plugins/vpn.c b/plugins/vpn.c |
| index af0e082c7276f9424023b3ad2274df21e5867fe2..fd96dddcfae840d585ee26cbaa41e261998f4bcc 100644 |
| --- a/plugins/vpn.c |
| +++ b/plugins/vpn.c |
| @@ -25,7 +25,6 @@ |
| * vpn plugin is responsible for launching the external process and |
| * handling notification callbacks to clock the provider state machine. |
| * |
| - * TODO(sleffler) currently assumes extern vpn service uses tun but not all do |
| * TODO(sleffler) seems to make more sense in src than plugins |
| */ |
| @@ -77,27 +76,40 @@ struct vpn_driver_data { |
| static GHashTable *driver_hash = NULL; |
| -static int kill_tun(char *tun_name) |
| +static int kill_tun(struct connman_provider *provider) |
| { |
| + struct vpn_data *data = connman_provider_get_data(provider); |
| + struct vpn_driver_data *vpn_driver_data; |
| + const char *name; |
| struct ifreq ifr; |
| int fd, err; |
| + if (data == NULL) |
| + return -1; |
| + |
| + name = connman_provider_get_driver_name(provider); |
| + vpn_driver_data = g_hash_table_lookup(driver_hash, name); |
| + |
| + if (vpn_driver_data != NULL && vpn_driver_data->vpn_driver !=NULL && |
| + vpn_driver_data->vpn_driver->flags == VPN_FLAG_NO_TUN) |
| + return 0; |
| + |
| memset(&ifr, 0, sizeof(ifr)); |
| ifr.ifr_flags = IFF_TUN | IFF_NO_PI; |
| - strncpy(ifr.ifr_name, tun_name, sizeof(ifr.ifr_name)); |
| + 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
|
| fd = open("/dev/net/tun", O_RDWR); |
| if (fd < 0) { |
| err = -errno; |
| connman_error("Failed to open /dev/net/tun to device %s: %s", |
| - tun_name, strerror(errno)); |
| + data->if_name, strerror(errno)); |
| return err; |
| } |
| if (ioctl(fd, TUNSETIFF, (void *)&ifr)) { |
| err = -errno; |
| connman_error("Failed to TUNSETIFF for device %s to it: %s", |
| - tun_name, strerror(errno)); |
| + data->if_name, strerror(errno)); |
| close(fd); |
| return err; |
| } |
| @@ -105,12 +117,12 @@ static int kill_tun(char *tun_name) |
| if (ioctl(fd, TUNSETPERSIST, 0)) { |
| err = -errno; |
| connman_error("Failed to set tun device %s nonpersistent: %s", |
| - tun_name, strerror(errno)); |
| + data->if_name, strerror(errno)); |
| close(fd); |
| return err; |
| } |
| close(fd); |
| - _DBG_VPN("Killed tun device %s", tun_name); |
| + _DBG_VPN("Killed tun device %s", data->if_name); |
| return 0; |
| } |
| @@ -125,7 +137,7 @@ void vpn_died(struct connman_task *task, void *user_data) |
| if (!data) |
| goto vpn_exit; |
| - kill_tun(data->if_name); |
| + kill_tun(provider); |
| connman_provider_set_data(provider, NULL); |
| connman_rtnl_remove_watch(data->watch); |
| @@ -144,6 +156,36 @@ vpn_exit: |
| connman_task_destroy(task); |
| } |
| +int vpn_set_ifname(struct connman_provider *provider, const char *ifname) |
| +{ |
| + struct vpn_data *data = connman_provider_get_data(provider); |
| + int index; |
| + |
| + if (data == NULL) { |
| + _DBG_VPN("%s: provider data not accessible", __func__); |
| + return -EIO; |
| + } |
| + |
| + if (ifname == NULL) { |
| + _DBG_VPN("%s: ifname not provided", __func__); |
| + return -EIO; |
| + } |
| + |
| + index = connman_inet_ifindex(ifname); |
| + if (index < 0) { |
| + _DBG_VPN("%s: could not get ifindex from %s", __func__, ifname); |
| + return -EIO; |
| + } |
| + |
| + data->if_name = (char *)g_strdup(ifname); |
| + connman_provider_set_index(provider, index); |
| + |
| + /* Set connect state to retry creating ipconfig with index above. */ |
| + connman_provider_set_state(provider, CONNMAN_PROVIDER_STATE_CONNECT); |
| + |
| + return 0; |
| +} |
| + |
| static void vpn_newlink(const char *ifname, unsigned flags, unsigned change, void *user_data) |
| { |
| struct connman_provider *provider = user_data; |
| @@ -159,7 +201,7 @@ static void vpn_newlink(const char *ifname, unsigned flags, unsigned change, |
| data->flags = flags; |
| } |
| -static void vpn_notify(struct connman_task *task, |
| +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
|
| DBusMessage *msg, void *user_data) |
| { |
| struct connman_provider *provider = user_data; |
| @@ -173,7 +215,7 @@ static void vpn_notify(struct connman_task *task, |
| name = connman_provider_get_driver_name(provider); |
| vpn_driver_data = g_hash_table_lookup(driver_hash, name); |
| if (vpn_driver_data == NULL) |
| - return; |
| + return NULL; |
| state = vpn_driver_data->vpn_driver->notify(msg, provider); |
| switch (state) { |
| @@ -193,34 +235,19 @@ static void vpn_notify(struct connman_task *task, |
| CONNMAN_PROVIDER_STATE_DISCONNECT); |
| break; |
| } |
| + |
| + return NULL; |
| } |
| -static int vpn_connect(struct connman_provider *provider) |
| +static int vpn_create_tun(struct connman_provider *provider) |
| { |
| struct vpn_data *data = connman_provider_get_data(provider); |
| - struct vpn_driver_data *vpn_driver_data; |
| struct ifreq ifr; |
| - const char *name; |
| int i, fd, index; |
| int ret = 0; |
| - if (data != NULL) |
| - return -EISCONN; |
| - |
| - data = g_try_new0(struct vpn_data, 1); |
| 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.
|
| - return -ENOMEM; |
| - |
| - data->provider = connman_provider_ref(provider); |
| - data->watch = 0; |
| - data->flags = 0; |
| - data->task = NULL; |
| - data->state = VPN_STATE_IDLE; |
| - |
| - connman_provider_set_data(provider, data); |
| - |
| - name = connman_provider_get_driver_name(provider); |
| - vpn_driver_data = g_hash_table_lookup(driver_hash, name); |
| + return -EISCONN; |
| fd = open("/dev/net/tun", O_RDWR); |
| if (fd < 0) { |
| @@ -269,24 +296,65 @@ static int vpn_connect(struct connman_provider *provider) |
| index = connman_inet_ifindex(data->if_name); |
| if (index < 0) { |
| connman_error("%s: failed to get tun ifindex", __func__); |
| - kill_tun(data->if_name); |
| + kill_tun(provider); |
| ret = -EIO; |
| goto exist_err; |
| } |
| connman_provider_set_index(provider, index); |
| + return 0; |
| + |
| +exist_err: |
| + return ret; |
| +} |
| + |
| +static int vpn_connect(struct connman_provider *provider) |
| +{ |
| + struct vpn_data *data = connman_provider_get_data(provider); |
| + struct vpn_driver_data *vpn_driver_data; |
| + const char *name; |
| + int ret = 0; |
| + |
| + 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
|
| + _DBG_VPN("%s: unable to access provider data", __func__); |
| + return -EISCONN; |
| + } |
| + |
| + data = g_try_new0(struct vpn_data, 1); |
| + if (data == NULL) |
| + return -ENOMEM; |
| + |
| + data->provider = connman_provider_ref(provider); |
| + data->watch = 0; |
| + data->flags = 0; |
| + data->task = NULL; |
| + data->state = VPN_STATE_IDLE; |
| + |
| + connman_provider_set_data(provider, data); |
| + |
| + name = connman_provider_get_driver_name(provider); |
| + vpn_driver_data = g_hash_table_lookup(driver_hash, name); |
| + |
| + if (vpn_driver_data != NULL && vpn_driver_data->vpn_driver != NULL && |
| + vpn_driver_data->vpn_driver->flags != VPN_FLAG_NO_TUN) { |
| + |
| + ret = vpn_create_tun(provider); |
| + if (ret < 0) |
| + goto exist_err; |
| + } |
| + |
| data->task = connman_task_create(vpn_driver_data->program); |
| if (data->task == NULL) { |
| ret = -ENOMEM; |
| - kill_tun(data->if_name); |
| + kill_tun(provider); |
| goto exist_err; |
| } |
| if (connman_task_set_notify(data->task, "notify", |
| vpn_notify, provider)) { |
| ret = -ENOMEM; |
| - kill_tun(data->if_name); |
| + kill_tun(provider); |
| connman_task_destroy(data->task); |
| data->task = NULL; |
| goto exist_err; |
| @@ -295,7 +363,7 @@ static int vpn_connect(struct connman_provider *provider) |
| ret = vpn_driver_data->vpn_driver->connect(provider, data->task, |
| data->if_name); |
| if (ret < 0) { |
| - kill_tun(data->if_name); |
| + kill_tun(provider); |
| connman_task_destroy(data->task); |
| data->task = NULL; |
| goto exist_err; |
| @@ -355,7 +423,6 @@ static int vpn_remove(struct connman_provider *provider) |
| struct vpn_data *data; |
| data = connman_provider_get_data(provider); |
| - connman_provider_set_data(provider, NULL); |
| if (data == NULL) |
| return 0; |
| @@ -365,7 +432,8 @@ static int vpn_remove(struct connman_provider *provider) |
| connman_task_stop(data->task); |
| g_usleep(G_USEC_PER_SEC); |
| - kill_tun(data->if_name); |
| + kill_tun(provider); |
| + connman_provider_set_data(provider, NULL); |
| return 0; |
| } |