OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * L2TP/IPsec VPN plugin. | |
3 * | |
4 * Copyright (c) 2011 The Chromium OS Authors. All rights reserved. | |
5 * Use of this source code is governed by a BSD-style license that can be | |
6 * found in the LICENSE file. | |
7 * | |
8 */ | |
9 | |
10 #ifdef HAVE_CONFIG_H | |
11 #include <config.h> | |
12 #endif | |
13 | |
14 #include <string.h> | |
15 #include <errno.h> | |
16 #include <unistd.h> | |
17 #include <sys/types.h> | |
18 #include <sys/stat.h> | |
19 #include <fcntl.h> | |
20 | |
21 #include <stdio.h> | |
22 #include <net/if.h> | |
23 | |
24 #include <glib.h> | |
25 | |
26 #define CONNMAN_API_SUBJECT_TO_CHANGE | |
27 #include <connman/plugin.h> | |
28 #include <connman/provider.h> | |
29 #include <connman/log.h> | |
30 #include <connman/task.h> | |
31 #include <connman/dbus.h> | |
32 #include <connman/inet.h> | |
33 | |
34 #include "vpn.h" | |
35 | |
36 #define _DBG_VPN(fmt, arg...) DBG(DBG_VPN, fmt, ## arg) | |
37 | |
38 static DBusConnection *connection; | |
39 | |
40 static DBusMessage *li_get_sec(struct connman_task *task, | |
41 DBusMessage *msg, void *user_data) | |
42 { | |
43 const char *user, *passwd; | |
44 struct connman_provider *provider = user_data; | |
45 | |
46 if (dbus_message_get_no_reply(msg) == FALSE) { | |
47 DBusMessage *reply; | |
48 | |
49 user = connman_provider_get_string(provider, "L2TPIPsec.User"); | |
50 passwd = connman_provider_get_string(provider, | |
51 "L2TPIPsec.Password"); | |
52 | |
53 if (user == NULL || strlen(user) == 0 || | |
54 passwd == NULL || strlen(passwd) == 0) { | |
55 _DBG_VPN("User or password not set"); | |
Sam Leffler
2011/03/11 17:49:55
if you print both user+passwd then you can see whi
| |
56 return NULL; | |
57 } | |
58 | |
59 reply = dbus_message_new_method_return(msg); | |
60 if (reply == NULL) | |
61 return NULL; | |
62 | |
63 dbus_message_append_args(reply, DBUS_TYPE_STRING, &user, | |
64 DBUS_TYPE_STRING, &passwd, | |
65 DBUS_TYPE_INVALID); | |
66 | |
67 return reply; | |
68 } | |
69 | |
70 return NULL; | |
71 } | |
72 | |
73 static int li_notify(DBusMessage *msg, struct connman_provider *provider) | |
74 { | |
75 DBusMessageIter iter, dict; | |
76 const char *reason, *key, *value; | |
77 char *ifname = NULL; | |
78 char *dns1 = NULL; | |
79 char *dns2 = NULL; | |
80 struct connman_ipaddress ipaddr; | |
81 | |
82 dbus_message_iter_init(msg, &iter); | |
83 | |
84 dbus_message_iter_get_basic(&iter, &reason); | |
85 dbus_message_iter_next(&iter); | |
Sam Leffler
2011/03/11 17:49:55
might want _DBG_VPN("reason %s", reason) here; not
kmixter1
2011/03/12 00:52:31
Done.
| |
86 | |
87 if (provider == NULL) { | |
88 connman_error("%s: No provider found", __func__); | |
89 return VPN_STATE_FAILURE; | |
90 } | |
91 | |
92 if (strcmp(reason, "connect")) | |
93 return VPN_STATE_DISCONNECT; | |
94 | |
95 memset(&ipaddr, 0, sizeof(ipaddr)); | |
96 ipaddr.af = AF_INET; | |
97 ipaddr.mask |= CONNMAN_IPCONFIG_AF; | |
98 | |
99 dbus_message_iter_recurse(&iter, &dict); | |
100 | |
101 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) { | |
102 DBusMessageIter entry; | |
103 | |
104 dbus_message_iter_recurse(&dict, &entry); | |
105 dbus_message_iter_get_basic(&entry, &key); | |
106 dbus_message_iter_next(&entry); | |
107 dbus_message_iter_get_basic(&entry, &value); | |
108 | |
109 _DBG_VPN("%s = %s", key, value); | |
110 | |
111 if (!strcmp(key, "INTERNAL_IP4_ADDRESS")) { | |
112 ipaddr.local = g_strdup(value); | |
113 ipaddr.mask |= CONNMAN_IPCONFIG_LOCAL; | |
114 } else if (!strcmp(key, "EXTERNAL_IP4_ADDRESS")) { | |
115 ipaddr.peer = g_strdup(value); | |
116 ipaddr.mask |= CONNMAN_IPCONFIG_PEER; | |
117 } else if (!strcmp(key, "DNS1")) { | |
118 dns1 = g_strdup(value); | |
119 } else if (!strcmp(key, "DNS2")) { | |
120 dns2 = g_strdup(value); | |
121 } else if (!strcmp(key, "INTERNAL_IFNAME")) { | |
122 ifname = g_strdup(value); | |
123 } | |
124 | |
125 dbus_message_iter_next(&dict); | |
126 } | |
127 | |
128 ipaddr.dns_servers = g_try_new0(gchar *, 3); | |
129 if (dns1 != NULL) { | |
130 ipaddr.dns_servers[0] = dns1; | |
131 if (dns2 != NULL) | |
132 ipaddr.dns_servers[1] = dns2; | |
133 ipaddr.mask |= CONNMAN_IPCONFIG_DNS; | |
134 } | |
135 | |
136 if (vpn_set_ifname(provider, ifname) <0) { | |
137 g_free(ifname); | |
138 return VPN_STATE_FAILURE; | |
139 } | |
140 | |
141 connman_provider_ipconfig_set(provider, &ipaddr); | |
142 | |
143 g_free(ifname); | |
144 g_free(dns1); | |
145 g_free(dns2); | |
146 g_strfreev(ipaddr.dns_servers); /* TODO(kmixter): OK to free? */ | |
Sam Leffler
2011/03/11 17:49:55
you own the storage so you need to free (note cons
| |
147 | |
148 return VPN_STATE_CONNECT; | |
149 } | |
150 | |
151 static int li_connect(struct connman_provider *provider, | |
152 struct connman_task *task, const char *if_name) | |
153 { | |
154 #define OPT_STR(property, option) do { \ | |
155 const char *s = connman_provider_get_string(provider, property); \ | |
156 if (s != NULL) \ | |
157 connman_task_add_argument(task, option, (char *)s); \ | |
158 } while (0) | |
159 #define OPT_BOOL(property, true_option, false_option) do { \ | |
160 const char *s = connman_provider_get_string(provider, property); \ | |
161 if (s != NULL) { \ | |
162 connman_task_add_argument(task, strcmp("true", s) == 0 ? \ | |
163 true_option : false_option, \ | |
164 NULL); \ | |
165 } \ | |
166 } while (0) | |
167 const char *vpnhost; | |
168 int err, fd; | |
169 | |
170 if (connman_task_set_notify(task, "getsec", | |
171 li_get_sec, provider)) | |
172 return -ENOMEM; | |
173 | |
174 vpnhost = connman_provider_get_string(provider, "Host"); | |
175 if (!vpnhost) { | |
176 connman_error("%s: host not set; cannot enable VPN", __func__); | |
177 return -EINVAL; | |
178 } | |
179 | |
180 connman_task_add_argument(task, "--remote_address", | |
181 (char *)vpnhost); | |
182 connman_task_add_argument(task, "--pppd_plugin", | |
183 SCRIPTDIR "/libppp-plugin.so"); | |
184 | |
185 OPT_STR("L2TPIPsec.CACert", "--server_ca_file"); | |
186 OPT_STR("L2TPIPsec.Key", "--client_key_file"); | |
187 OPT_STR("L2TPIPsec.Cert", "--client_cert_file"); | |
188 OPT_STR("L2TPIPsec.PSK", "--psk_file"); | |
189 OPT_STR("L2TPIPsec.User", "--user"); | |
190 OPT_STR("L2TPIPsec.IPsecTimeout", "--ipsec_timeout"); | |
191 OPT_STR("L2TPIPsec.LeftProtoPort", "--leftprotoport"); | |
192 OPT_BOOL("L2TPIPsec.PFS", "--pfs", "--nopfs"); | |
193 OPT_BOOL("L2TPIPsec.Rekey", "--rekey", "--norekey"); | |
194 OPT_STR("L2TPIPsec.RightProtoPort", "--leftprotoport"); | |
195 | |
196 OPT_BOOL("L2TPIPsec.RequireChap", "--require_chap", "--norequire_cha p"); | |
197 OPT_BOOL("L2TPIPsec.RefusePap", "--refuse_pap", "--norefuse_pap"); | |
198 OPT_BOOL("L2TPIPsec.RequireAuth", "--require_authentication", | |
199 "--norequire_authentication"); | |
200 OPT_BOOL("L2TPIPsec.LengthBit", "--length_bit", "--nolength_bit"); | |
201 | |
202 fd = fileno(stderr); | |
203 err = connman_task_run(task, vpn_died, provider, | |
204 NULL, &fd, &fd); | |
205 if (err < 0) { | |
206 connman_error("l2tpipsec failed to start"); | |
207 return -EIO; | |
208 } | |
209 | |
210 return 0; | |
211 } | |
212 | |
213 static struct vpn_driver vpn_driver = { | |
214 .flags = VPN_FLAG_NO_TUN, | |
215 .notify = li_notify, | |
216 .connect = li_connect, | |
217 }; | |
218 | |
219 static int li_init(void) | |
220 { | |
221 connection = connman_dbus_get_connection(); | |
222 | |
223 return vpn_register("l2tpipsec", &vpn_driver, L2TPIPSEC); | |
224 } | |
225 | |
226 static void li_exit(void) | |
227 { | |
228 vpn_unregister("l2tpipsec"); | |
229 | |
230 dbus_connection_unref(connection); | |
231 } | |
232 | |
233 CONNMAN_PLUGIN_DEFINE(l2tpipsec, "l2tpipsec plugin", VERSION, | |
234 CONNMAN_PLUGIN_PRIORITY_DEFAULT, li_init, li_exit) | |
OLD | NEW |