5 * Copyright (C) 2011 Intel Corporation. All rights reserved.
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.
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.
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
29 #include <sys/types.h>
32 #include <pppd/pppd.h>
34 #include <pppd/ipcp.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
38 #include <dbus/dbus.h>
40 #define INET_ADDRES_LEN (INET_ADDRSTRLEN + 5)
41 #define INET_DNS_LEN (2*INET_ADDRSTRLEN + 9)
44 static char *interface;
47 static DBusConnection *connection;
49 char pppd_version[] = VERSION;
51 int plugin_init(void);
53 static void append(DBusMessageIter *dict, const char *key, const char *value)
55 DBusMessageIter entry;
57 /* We clean the environment before invoking pppd, but
58 * might as well still filter out the few things that get
59 * added that we're not interested in
61 if (!strcmp(key, "PWD") || !strcmp(key, "_") ||
62 !strcmp(key, "SHLVL") ||
63 !strcmp(key, "connman_busname") ||
64 !strcmp(key, "connman_network"))
67 dbus_message_iter_open_container(dict, DBUS_TYPE_DICT_ENTRY,
70 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &key);
72 dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &value);
74 dbus_message_iter_close_container(dict, &entry);
78 static int ppp_have_secret()
83 static int ppp_get_secret(char *username, char *password)
85 DBusMessage *msg, *reply;
86 const char *user, *pass;
89 if (username == NULL && password == NULL)
95 if (connection == NULL)
98 dbus_error_init(&err);
100 msg = dbus_message_new_method_call(busname, path, interface, "getsec");
104 dbus_message_append_args(msg, DBUS_TYPE_INVALID, DBUS_TYPE_INVALID);
106 reply = dbus_connection_send_with_reply_and_block(connection,
109 if (dbus_error_is_set(&err) == TRUE)
110 dbus_error_free(&err);
112 dbus_message_unref(msg);
116 dbus_message_unref(msg);
118 dbus_error_init(&err);
120 if (dbus_message_get_args(reply, &err, DBUS_TYPE_STRING, &user,
121 DBUS_TYPE_STRING, &pass,
122 DBUS_TYPE_INVALID) == FALSE) {
123 if (dbus_error_is_set(&err) == TRUE)
124 dbus_error_free(&err);
126 dbus_message_unref(reply);
130 if (username != NULL)
131 strcpy(username, user);
133 strcpy(password, pass);
135 dbus_message_unref(reply);
140 static void ppp_up(void *data, int arg)
142 char buf[INET_ADDRES_LEN];
143 char dns[INET_DNS_LEN];
144 const char *reason = "connect";
145 bool add_blank = FALSE;
146 DBusMessageIter iter, dict;
149 if (connection == NULL)
152 if (ipcp_gotoptions[0].ouraddr == 0)
155 msg = dbus_message_new_method_call(busname, path,
156 interface, "notify");
160 dbus_message_set_no_reply(msg, TRUE);
162 dbus_message_append_args(msg,
163 DBUS_TYPE_STRING, &reason, DBUS_TYPE_INVALID);
165 dbus_message_iter_init_append(msg, &iter);
167 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY,
168 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
169 DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_STRING_AS_STRING
170 DBUS_DICT_ENTRY_END_CHAR_AS_STRING, &dict);
172 append(&dict, "INTERNAL_IFNAME", ifname);
174 inet_ntop(AF_INET, &ipcp_gotoptions[0].ouraddr, buf, INET_ADDRSTRLEN);
175 append(&dict, "INTERNAL_IP4_ADDRESS", buf);
177 strcpy(buf, "255.255.255.255");
178 append(&dict, "INTERNAL_IP4_NETMASK", buf);
180 if (ipcp_gotoptions[0].dnsaddr[0] || ipcp_gotoptions[0].dnsaddr[1]) {
181 memset(dns, 0, sizeof(dns));
184 if (ipcp_gotoptions[0].dnsaddr[0]) {
185 inet_ntop(AF_INET, &ipcp_gotoptions[0].dnsaddr[0],
186 buf, INET_ADDRSTRLEN);
192 if (ipcp_gotoptions[0].dnsaddr[1]) {
193 inet_ntop(AF_INET, &ipcp_gotoptions[0].dnsaddr[1],
194 buf, INET_ADDRSTRLEN);
195 if (add_blank == TRUE)
200 append(&dict, "INTERNAL_IP4_DNS", dns);
203 append(&dict, "MTU", "1400");
205 dbus_message_iter_close_container(&iter, &dict);
207 dbus_connection_send(connection, msg, NULL);
209 dbus_connection_flush(connection);
211 dbus_message_unref(msg);
214 static void ppp_exit(void *data, int arg)
216 if (connection != NULL) {
217 dbus_connection_unref(connection);
221 if (busname != NULL) {
226 if (interface != NULL) {
237 static void ppp_phase_change(void *data, int arg)
239 const char *reason = "disconnect";
242 if (connection == NULL)
245 if (arg == PHASE_DEAD || arg == PHASE_DISCONNECT) {
246 msg = dbus_message_new_method_call(busname, path,
247 interface, "notify");
251 dbus_message_set_no_reply(msg, TRUE);
253 dbus_message_append_args(msg,
254 DBUS_TYPE_STRING, &reason, DBUS_TYPE_INVALID);
256 dbus_connection_send(connection, msg, NULL);
258 dbus_connection_flush(connection);
260 dbus_message_unref(msg);
264 int plugin_init(void)
267 static const char *bus, *inter, *p;
269 dbus_error_init(&error);
271 bus = getenv("CONNMAN_BUSNAME");
272 inter = getenv("CONNMAN_INTERFACE");
273 p = getenv("CONNMAN_PATH");
275 if (bus == NULL || inter == NULL || p == NULL)
278 busname = strdup(bus);
279 interface = strdup(inter);
282 if (busname == NULL || interface == NULL || path == NULL) {
287 connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
288 if (connection == NULL) {
289 if (dbus_error_is_set(&error) == TRUE)
290 dbus_error_free(&error);
296 pap_passwd_hook = ppp_get_secret;
297 chap_passwd_hook = ppp_get_secret;
299 chap_check_hook = ppp_have_secret;
300 pap_check_hook = ppp_have_secret;
302 add_notifier(&ip_up_notifier, ppp_up, NULL);
303 add_notifier(&phasechange, ppp_phase_change, NULL);
304 add_notifier(&exitnotify, ppp_exit, connection);