provider: Remove IPv4 element registration
[framework/connectivity/connman.git] / plugins / openconnect.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2010  Intel Corporation. All rights reserved.
6  *
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
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
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
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <string.h>
27 #include <errno.h>
28 #include <unistd.h>
29 #include <net/if.h>
30
31 #include <glib.h>
32
33 #define CONNMAN_API_SUBJECT_TO_CHANGE
34 #include <connman/plugin.h>
35 #include <connman/provider.h>
36 #include <connman/log.h>
37 #include <connman/task.h>
38 #include <connman/ipconfig.h>
39
40 #include "vpn.h"
41
42 static int oc_notify(DBusMessage *msg, struct connman_provider *provider)
43 {
44         DBusMessageIter iter, dict;
45         const char *reason, *key, *value;
46         const char *domain = NULL;
47         char *address = NULL, *netmask = NULL, *gateway = NULL;
48         struct connman_ipaddress *ipaddress;
49
50         dbus_message_iter_init(msg, &iter);
51
52         dbus_message_iter_get_basic(&iter, &reason);
53         dbus_message_iter_next(&iter);
54
55         if (!provider) {
56                 connman_error("No provider found");
57                 return VPN_STATE_FAILURE;
58         }
59
60         if (strcmp(reason, "connect"))
61                 return VPN_STATE_DISCONNECT;
62
63         domain = connman_provider_get_string(provider, "VPN.Domain");
64
65         dbus_message_iter_recurse(&iter, &dict);
66
67         while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
68                 DBusMessageIter entry;
69
70                 dbus_message_iter_recurse(&dict, &entry);
71                 dbus_message_iter_get_basic(&entry, &key);
72                 dbus_message_iter_next(&entry);
73                 dbus_message_iter_get_basic(&entry, &value);
74
75                 if (strcmp(key, "CISCO_CSTP_OPTIONS"))
76                         DBG("%s = %s", key, value);
77
78                 if (!strcmp(key, "VPNGATEWAY"))
79                         gateway = g_strdup(value);
80
81                 if (!strcmp(key, "INTERNAL_IP4_ADDRESS"))
82                         address = g_strdup(value);
83
84                 if (!strcmp(key, "INTERNAL_IP4_NETMASK"))
85                         netmask = g_strdup(value);
86
87                 if (!strcmp(key, "INTERNAL_IP4_DNS"))
88                         connman_provider_set_nameservers(provider, value);
89
90                 if (!strcmp(key, "CISCO_PROXY_PAC"))
91                         connman_provider_set_pac(provider, value);
92
93                 if (domain == NULL && !strcmp(key, "CISCO_DEF_DOMAIN"))
94                         domain = value;
95
96                 if (g_str_has_prefix(key, "CISCO_SPLIT_INC") == TRUE ||
97                         g_str_has_prefix(key, "CISCO_IPV6_SPLIT_INC") == TRUE)
98                         connman_provider_append_route(provider, key, value);
99
100                 dbus_message_iter_next(&dict);
101         }
102
103         ipaddress = connman_ipaddress_alloc(AF_INET);
104         if (ipaddress == NULL) {
105                 g_free(address);
106                 g_free(netmask);
107                 g_free(gateway);
108
109                 return VPN_STATE_FAILURE;
110         }
111
112         connman_ipaddress_set_ipv4(ipaddress, address, netmask, gateway);
113         connman_provider_set_ipaddress(provider, ipaddress);
114         connman_provider_set_domain(provider, domain);
115
116         g_free(address);
117         g_free(netmask);
118         g_free(gateway);
119         connman_ipaddress_free(ipaddress);
120
121         return VPN_STATE_CONNECT;
122 }
123
124 static int oc_connect(struct connman_provider *provider,
125                         struct connman_task *task, const char *if_name)
126 {
127         const char *vpnhost, *vpncookie, *cafile, *certsha1, *mtu;
128         int fd, err;
129
130         vpnhost = connman_provider_get_string(provider, "Host");
131         if (!vpnhost) {
132                 connman_error("Host not set; cannot enable VPN");
133                 return -EINVAL;
134         }
135
136         vpncookie = connman_provider_get_string(provider, "OpenConnect.Cookie");
137         if (!vpncookie) {
138                 connman_error("OpenConnect.Cookie not set; cannot enable VPN");
139                 return -EINVAL;
140         }
141
142         certsha1 = connman_provider_get_string(provider,
143                                                 "OpenConnect.ServerCert");
144         if (certsha1)
145                 connman_task_add_argument(task, "--servercert",
146                                                         (char *)certsha1);
147
148         cafile = connman_provider_get_string(provider, "OpenConnect.CACert");
149         mtu = connman_provider_get_string(provider, "VPN.MTU");
150
151         if (cafile)
152                 connman_task_add_argument(task, "--cafile",
153                                                         (char *)cafile);
154         if (mtu)
155                 connman_task_add_argument(task, "--mtu", (char *)mtu);
156
157         connman_task_add_argument(task, "--syslog", NULL);
158         connman_task_add_argument(task, "--cookie-on-stdin", NULL);
159
160         connman_task_add_argument(task, "--script",
161                                   SCRIPTDIR "/openconnect-script");
162
163         connman_task_add_argument(task, "--interface", if_name);
164
165         connman_task_add_argument(task, (char *)vpnhost, NULL);
166
167         err = connman_task_run(task, vpn_died, provider,
168                                &fd, NULL, NULL);
169         if (err < 0) {
170                 connman_error("openconnect failed to start");
171                 return -EIO;
172         }
173
174         if (write(fd, vpncookie, strlen(vpncookie)) !=
175                         (ssize_t)strlen(vpncookie) ||
176                         write(fd, "\n", 1) != 1) {
177                 connman_error("openconnect failed to take cookie on stdin");
178                 return -EIO;
179         }
180
181         return 0;
182 }
183
184 static int oc_error_code(int exit_code)
185 {
186
187         switch (exit_code) {
188         case 1:
189                 return CONNMAN_PROVIDER_ERROR_CONNECT_FAILED;
190         case 2:
191                 return CONNMAN_PROVIDER_ERROR_LOGIN_FAILED;
192         default:
193                 return CONNMAN_PROVIDER_ERROR_UNKNOWN;
194         }
195 }
196
197 static struct vpn_driver vpn_driver = {
198         .notify         = oc_notify,
199         .connect        = oc_connect,
200         .error_code     = oc_error_code,
201 };
202
203 static int openconnect_init(void)
204 {
205         return vpn_register("openconnect", &vpn_driver, OPENCONNECT);
206 }
207
208 static void openconnect_exit(void)
209 {
210         vpn_unregister("openconnect");
211 }
212
213 CONNMAN_PLUGIN_DEFINE(openconnect, "OpenConnect VPN plugin", VERSION,
214         CONNMAN_PLUGIN_PRIORITY_DEFAULT, openconnect_init, openconnect_exit)