1 #include "dvpnlib-internal.h"
2 #include "dvpnlib-vpn-connection.h"
4 static GList *vpn_connection_list;
5 static GHashTable *vpn_connection_hash;
7 struct connection_property_changed_cb {
8 vpn_connection_property_changed_cb property_changed_cb;
12 struct vpn_connection {
13 GDBusProxy *dbus_proxy;
21 enum vpn_connection_state state;
22 struct vpn_connection_ipv4 *ipv4;
23 struct vpn_connection_ipv6 *ipv6;
25 GSList *user_routes; /*struct vpn_connection_route */
26 GSList *server_routes; /* struct vpn_connection_route */
27 GHashTable *property_changed_cb_hash;
30 static void free_vpn_connection_ipv4(struct vpn_connection_ipv4 *ipv4_info);
31 static void free_vpn_connection_ipv6(struct vpn_connection_ipv6 *ipv6_info);
32 static void free_vpn_connection_route(gpointer data);
36 vpn_connection_set_user_routes(struct vpn_connection *connection,
37 struct vpn_connection_route **user_routes)
39 if (!connection || !user_routes)
40 return DVPNLIB_ERR_INVALID_PARAMETER;
42 GVariantBuilder user_routes_b;
43 GVariant *user_routes_v;
45 g_variant_builder_init(&user_routes_b, G_VARIANT_TYPE("a(a{sv})"));
47 while (*user_routes != NULL) {
49 g_variant_builder_open(&user_routes_b,
50 G_VARIANT_TYPE("(a{sv})"));
51 g_variant_builder_open(&user_routes_b,
52 G_VARIANT_TYPE("a{sv}"));
54 if ((*user_routes)->protocol_family) {
55 g_variant_builder_add(&user_routes_b, "{sv}",
58 (*user_routes)->protocol_family));
61 if ((*user_routes)->network) {
62 g_variant_builder_add(&user_routes_b, "{sv}",
64 g_variant_new_string((*user_routes)->network));
67 if ((*user_routes)->netmask) {
68 g_variant_builder_add(&user_routes_b, "{sv}",
70 g_variant_new_string((*user_routes)->netmask));
73 if ((*user_routes)->gateway) {
74 g_variant_builder_add(&user_routes_b, "{sv}",
76 g_variant_new_string((*user_routes)->gateway));
79 g_variant_builder_close(&user_routes_b);
84 user_routes_v = g_variant_builder_end(&user_routes_b);
86 return common_set_property(connection->dbus_proxy, "UserRoutes",
91 static struct connection_property_changed_cb
92 *get_connection_property_changed_cb(
93 struct vpn_connection *connection,
94 enum vpn_connection_property_type type)
96 return g_hash_table_lookup(connection->property_changed_cb_hash,
97 GINT_TO_POINTER(type));
100 static void parse_connection_property_ipv4(
101 struct vpn_connection *connection,
110 g_variant_get(ipv4, "a{sv}", &iter);
111 if (g_variant_iter_n_children(iter) == 0) {
112 g_variant_iter_free(iter);
116 if (connection->ipv4)
117 free_vpn_connection_ipv4(connection->ipv4);
119 connection->ipv4 = g_try_new0(struct vpn_connection_ipv4, 1);
120 if (connection->ipv4 == NULL) {
122 g_variant_iter_free(iter);
126 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
127 if (!g_strcmp0(key, "Address")) {
128 const char *property_value =
129 g_variant_get_string(value, NULL);
130 DBG("Address is %s", property_value);
131 connection->ipv4->address = g_strdup(property_value);
132 } else if (!g_strcmp0(key, "Netmask")) {
133 const char *property_value =
134 g_variant_get_string(value, NULL);
135 DBG("Netmask is %s", property_value);
136 connection->ipv4->netmask = g_strdup(property_value);
137 } else if (!g_strcmp0(key, "Gateway")) {
138 const char *property_value =
139 g_variant_get_string(value, NULL);
140 DBG("Gateway is %s", property_value);
141 connection->ipv4->gateway = g_strdup(property_value);
142 } else if (!g_strcmp0(key, "Peer")) {
143 const char *property_value =
144 g_variant_get_string(value, NULL);
145 DBG("Peer is %s", property_value);
146 connection->ipv4->peer = g_strdup(property_value);
150 g_variant_iter_free(iter);
153 static void parse_connection_property_ipv6(
154 struct vpn_connection *connection,
163 g_variant_get(ipv6, "a{sv}", &iter);
164 if (g_variant_iter_n_children(iter) == 0) {
165 g_variant_iter_free(iter);
169 if (connection->ipv6)
170 free_vpn_connection_ipv6(connection->ipv6);
172 connection->ipv6 = g_try_new0(struct vpn_connection_ipv6, 1);
173 if (connection->ipv6 == NULL) {
175 g_variant_iter_free(iter);
179 while (g_variant_iter_loop(iter, "{sv}", &key, &value)) {
180 if (!g_strcmp0(key, "Address")) {
181 const char *property_value =
182 g_variant_get_string(value, NULL);
183 DBG("Address is %s", property_value);
184 connection->ipv6->address = g_strdup(property_value);
185 } else if (!g_strcmp0(key, "PrefixLength")) {
186 const char *property_value =
187 g_variant_get_string(value, NULL);
188 DBG("PrefixLength is %s", property_value);
189 connection->ipv6->prefix_length =
190 g_strdup(property_value);
191 } else if (!g_strcmp0(key, "Gateway")) {
192 const char *property_value =
193 g_variant_get_string(value, NULL);
194 DBG("Gateway is %s", property_value);
195 connection->ipv6->gateway = g_strdup(property_value);
196 } else if (!g_strcmp0(key, "Peer")) {
197 const char *property_value =
198 g_variant_get_string(value, NULL);
199 DBG("Peer is %s", property_value);
200 connection->ipv6->peer = g_strdup(property_value);
204 g_variant_iter_free(iter);
207 static void parse_connection_property_nameservers(
208 struct vpn_connection *connection,
209 GVariant *nameservers)
217 g_variant_get(nameservers, "as", &iter);
218 if (g_variant_iter_n_children(iter) == 0) {
219 g_variant_iter_free(iter);
223 g_strfreev(connection->nameservers);
224 n = g_variant_iter_n_children(iter);
225 connection->nameservers = g_try_new0(char *, n+1);
226 if (connection->nameservers == NULL) {
228 g_variant_iter_free(iter);
232 while (g_variant_iter_loop(iter, "s", &value) && i < n) {
233 DBG("Nameserver Entry is %s", value);
234 connection->nameservers[i] = g_strdup(value);
237 connection->nameservers[n] = NULL;
239 g_variant_iter_free(iter);
242 static void print_variant(const gchar *s, GVariant *v)
244 gchar *temp = g_variant_print(v, true);
245 DBG("%s => %s", s, temp);
249 static void parse_connection_property_user_routes(
250 struct vpn_connection *connection,
251 GVariant *user_routes)
256 GVariantIter *route_entry;
258 print_variant("Incoming : ", user_routes);
260 g_variant_iter_init(&outer, user_routes);
261 if (g_variant_iter_n_children(&outer) == 0)
264 if (connection->user_routes == NULL) {
265 ERROR("connection->server_routes is NULL");
268 g_slist_free_full(connection->user_routes,
269 free_vpn_connection_route);
270 connection->user_routes = NULL;
273 while (g_variant_iter_loop(&outer, "(a{sv})", &route_entry)) {
277 if (g_variant_iter_n_children(route_entry) == 0)
280 struct vpn_connection_route *route =
281 g_try_new0(struct vpn_connection_route, 1);
287 while (g_variant_iter_loop(route_entry, "{sv}", &key, &value)) {
288 if (!g_strcmp0(key, "ProtocolFamily")) {
289 int property_value = g_variant_get_int32(value);
290 DBG("ProtocolFamily is %d", property_value);
291 route->protocol_family = property_value;
292 } else if (!g_strcmp0(key, "Network")) {
293 const char *property_value =
294 g_variant_get_string(value, NULL);
295 DBG("Network is %s", property_value);
297 g_free(route->network);
298 route->network = g_strdup(property_value);
299 } else if (!g_strcmp0(key, "Netmask")) {
300 const char *property_value =
301 g_variant_get_string(value, NULL);
302 DBG("Netmask is %s", property_value);
304 g_free(route->netmask);
305 route->netmask = g_strdup(property_value);
306 } else if (!g_strcmp0(key, "Gateway")) {
307 const char *property_value =
308 g_variant_get_string(value, NULL);
309 DBG("Gateway is %s", property_value);
311 g_free(route->gateway);
312 route->gateway = g_strdup(property_value);
316 /*TODO: See if g_slist_prepend works better*/
317 connection->user_routes =
318 g_slist_append(connection->user_routes, route);
323 static void parse_connection_property_server_routes(
324 struct vpn_connection *connection,
325 GVariant *server_routes)
330 GVariantIter *route_entry;
332 g_variant_iter_init(&outer, server_routes);
333 if (g_variant_iter_n_children(&outer) == 0)
336 if (connection->server_routes == NULL) {
337 ERROR("connection->server_routes is NULL");
340 g_slist_free_full(connection->server_routes,
341 free_vpn_connection_route);
342 connection->server_routes = NULL;
345 while (g_variant_iter_loop(&outer, "(a{sv})", &route_entry)) {
349 if (g_variant_iter_n_children(route_entry) == 0)
352 struct vpn_connection_route *route =
353 g_try_new0(struct vpn_connection_route, 1);
359 while (g_variant_iter_loop(route_entry, "{sv}", &key, &value)) {
360 if (!g_strcmp0(key, "ProtocolFamily")) {
361 int property_value = g_variant_get_int32(value);
362 DBG("ProtocolFamily is %d", property_value);
363 route->protocol_family = property_value;
364 } else if (!g_strcmp0(key, "Network")) {
365 const char *property_value =
366 g_variant_get_string(value, NULL);
367 DBG("Network is %s", property_value);
369 g_free(route->network);
370 route->network = g_strdup(property_value);
371 } else if (!g_strcmp0(key, "Netmask")) {
372 const char *property_value =
373 g_variant_get_string(value, NULL);
374 DBG("Netmask is %s", property_value);
376 g_free(route->netmask);
377 route->netmask = g_strdup(property_value);
378 } else if (!g_strcmp0(key, "Gateway")) {
379 const char *property_value =
380 g_variant_get_string(value, NULL);
381 DBG("Gateway is %s", property_value);
383 g_free(route->gateway);
384 route->gateway = g_strdup(property_value);
388 /*TODO: See if g_slist_prepend works better*/
389 connection->server_routes =
390 g_slist_append(connection->server_routes, route);
394 static enum vpn_connection_property_type parse_connection_property(
395 struct vpn_connection *connection,
396 gchar *key, GVariant *value)
398 assert(connection != NULL);
399 enum vpn_connection_property_type property_type = VPN_CONN_PROP_NONE;
401 if (!g_strcmp0(key, "State")) {
402 const gchar *property_value;
403 property_value = g_variant_get_string(value, NULL);
404 DBG("connection state is %s", property_value);
405 if (!g_strcmp0(property_value, "idle"))
406 connection->state = VPN_CONN_STATE_IDLE;
407 else if (!g_strcmp0(property_value, "failure"))
408 connection->state = VPN_CONN_STATE_FAILURE;
409 else if (!g_strcmp0(property_value, "configuration"))
410 connection->state = VPN_CONN_STATE_CONFIGURATION;
411 else if (!g_strcmp0(property_value, "ready"))
412 connection->state = VPN_CONN_STATE_READY;
413 else if (!g_strcmp0(property_value, "disconnect"))
414 connection->state = VPN_CONN_STATE_DISCONNECT;
415 property_type = VPN_CONN_PROP_STATE;
416 } else if (!g_strcmp0(key, "Type")) {
417 const gchar *property_value;
418 property_value = g_variant_get_string(value, NULL);
419 DBG("connection type is %s", property_value);
420 g_free(connection->type);
421 connection->type = g_strdup(property_value);
422 property_type = VPN_CONN_PROP_TYPE;
423 } else if (!g_strcmp0(key, "Name")) {
424 const gchar *property_value;
425 property_value = g_variant_get_string(value, NULL);
426 g_free(connection->name);
427 connection->name = g_strdup(property_value);
428 property_type = VPN_CONN_PROP_NAME;
429 } else if (!g_strcmp0(key, "Domain")) {
430 const gchar *property_value;
431 property_value = g_variant_get_string(value, NULL);
432 g_free(connection->domain);
433 connection->domain = g_strdup(property_value);
434 property_type = VPN_CONN_PROP_DOMAIN;
435 } else if (!g_strcmp0(key, "Host")) {
436 const gchar *property_value;
437 property_value = g_variant_get_string(value, NULL);
438 g_free(connection->host);
439 connection->host = g_strdup(property_value);
440 property_type = VPN_CONN_PROP_HOST;
441 } else if (!g_strcmp0(key, "Immutable")) {
442 connection->immutable = g_variant_get_boolean(value);
443 property_type = VPN_CONN_PROP_IMMUTABLE;
444 } else if (!g_strcmp0(key, "Index")) {
445 connection->index = g_variant_get_int32(value);
446 property_type = VPN_CONN_PROP_INDEX;
449 * Add IPv4/IPV6/Nameservers
450 * UserRoutes/ServerRoutes
453 else if (!g_strcmp0(key, "IPv4")) {
454 parse_connection_property_ipv4(connection, value);
455 property_type = VPN_CONN_PROP_IPV4;
456 } else if (!g_strcmp0(key, "IPv6")) {
457 parse_connection_property_ipv6(connection, value);
458 property_type = VPN_CONN_PROP_IPV6;
459 } else if (!g_strcmp0(key, "Nameservers")) {
460 parse_connection_property_nameservers(connection, value);
461 property_type = VPN_CONN_PROP_USERROUTES;
462 } else if (!g_strcmp0(key, "UserRoutes")) {
463 parse_connection_property_user_routes(connection, value);
464 property_type = VPN_CONN_PROP_USERROUTES;
465 } else if (!g_strcmp0(key, "ServerRoutes")) {
466 parse_connection_property_server_routes(connection, value);
467 property_type = VPN_CONN_PROP_SERVERROUTES;
470 return property_type;
473 static void parse_connection_properties(
474 struct vpn_connection *connection,
475 GVariantIter *properties)
480 while (g_variant_iter_next(properties, "{sv}", &key, &value)) {
481 parse_connection_property(connection, key, value);
484 g_variant_unref(value);
488 static void connection_property_changed(
489 struct vpn_connection *connection,
490 GVariant *parameters)
494 enum vpn_connection_property_type property_type;
498 g_variant_get(parameters, "(sv)", &key, &value);
499 property_type = parse_connection_property(connection, key, value);
501 if (property_type != VPN_CONN_PROP_NONE) {
502 DBG("Now check property changed callback");
504 struct connection_property_changed_cb *property_changed_cb_t;
506 property_changed_cb_t = get_connection_property_changed_cb(
509 if (property_changed_cb_t != NULL) {
510 DBG("property changed callback has been set");
511 property_changed_cb_t->property_changed_cb(connection,
512 property_changed_cb_t->user_data);
517 g_variant_unref(value);
520 static void connection_signal_handler(GDBusProxy *proxy,
523 GVariant *parameters,
526 DBG("signal_name: %s", signal_name);
528 struct vpn_connection *connection = user_data;
530 if (!g_strcmp0(signal_name, "PropertyChanged"))
531 connection_property_changed(connection, parameters);
534 static void free_connection_property_changed_cb(gpointer data)
537 struct connection_property_changed_cb *property_changed_cb = data;
539 g_free(property_changed_cb);
543 void destroy_vpn_connections(void)
545 if (vpn_connection_list != NULL) {
546 g_list_free(vpn_connection_list); //LCOV_EXCL_LINE
547 vpn_connection_list = NULL; //LCOV_EXCL_LINE
549 if (vpn_connection_hash != NULL) {
550 g_hash_table_destroy(vpn_connection_hash);
551 vpn_connection_hash = NULL;
556 static struct vpn_connection *create_vpn_connection(
558 GVariantIter *properties)
560 GDBusProxy *connection_proxy;
561 struct vpn_connection *connection;
562 GError *error = NULL;
566 connection_proxy = g_dbus_proxy_new_for_bus_sync(G_BUS_TYPE_SYSTEM,
567 G_DBUS_PROXY_FLAGS_NONE, NULL,
568 VPN_NAME, object_path,
569 VPN_CONNECTION_INTERFACE, NULL, &error);
570 if (connection_proxy == NULL) {
571 ERROR("error info: %s", error->message);
576 connection = g_try_new0(struct vpn_connection, 1);
577 if (connection == NULL) {
579 g_object_unref(connection_proxy);
583 connection->dbus_proxy = connection_proxy;
584 connection->path = g_strdup(object_path);
586 parse_connection_properties(connection, properties);
588 g_hash_table_insert(vpn_connection_hash,
589 (gpointer)connection->path,
590 (gpointer)connection);
592 vpn_connection_list = g_list_append(vpn_connection_list,
595 connection->property_changed_cb_hash = g_hash_table_new_full(
596 g_direct_hash, g_direct_equal, NULL,
597 free_connection_property_changed_cb);
599 g_signal_connect(connection->dbus_proxy, "g-signal",
600 G_CALLBACK(connection_signal_handler), connection);
605 static void free_vpn_connection_ipv4(struct vpn_connection_ipv4 *ipv4_info)
609 g_free(ipv4_info->address);
610 g_free(ipv4_info->netmask);
611 g_free(ipv4_info->gateway);
612 g_free(ipv4_info->peer);
616 static void free_vpn_connection_ipv6(struct vpn_connection_ipv6 *ipv6_info)
620 g_free(ipv6_info->address);
621 g_free(ipv6_info->prefix_length);
622 g_free(ipv6_info->gateway);
623 g_free(ipv6_info->peer);
627 static void free_vpn_connection_route(gpointer data)
631 struct vpn_connection_route *route = data;
634 DBG("Nothing to Delete!");
638 g_free(route->network);
639 g_free(route->netmask);
640 g_free(route->gateway);
645 static void free_vpn_connection(gpointer data)
649 struct vpn_connection *connection = data;
651 if (connection == NULL)
654 if (connection->dbus_proxy != NULL)
655 g_object_unref(connection->dbus_proxy);
657 if (connection->property_changed_cb_hash != NULL)
658 g_hash_table_destroy(connection->property_changed_cb_hash);
660 g_free(connection->path);
661 g_free(connection->name);
662 g_free(connection->domain);
663 g_free(connection->host);
665 if (connection->ipv4)
666 free_vpn_connection_ipv4(connection->ipv4);
668 if (connection->ipv6)
669 free_vpn_connection_ipv6(connection->ipv6);
671 g_strfreev(connection->nameservers);
673 if (connection->user_routes)
674 g_slist_free_full(connection->user_routes,
675 free_vpn_connection_route);
677 if (connection->server_routes)
678 g_slist_free_full(connection->server_routes,
679 free_vpn_connection_route);
685 static void create_vpn_connections(GVariant *connections)
689 GVariantIter *properties;
691 g_variant_get(connections, "(a(oa{sv}))", &iter);
692 if (g_variant_iter_n_children(iter) == 0) {
693 g_variant_iter_free(iter);
697 while (g_variant_iter_loop(iter, "(oa{sv})", &path, &properties)) //LCOV_EXCL_LINE
698 create_vpn_connection(path, properties); //LCOV_EXCL_LINE
700 g_variant_iter_free(iter); //LCOV_EXCL_LINE
704 struct vpn_connection *get_connection_by_path(const gchar *path)
706 DBG("path: %s", path);
708 return g_hash_table_lookup(vpn_connection_hash, (gpointer)path);
711 gboolean add_vpn_connection(GVariant **parameters,
712 struct vpn_connection **connection)
715 gchar *connection_path;
716 GVariantIter *properties;
719 g_variant_get(*parameters, "(oa{sv})", &connection_path, &properties);
721 print_str = g_variant_print(*parameters, TRUE);
722 DBG("connection path: %s, parameters: %s", connection_path, print_str);
726 * Lookup if it has existed in the hash table
728 *connection = g_hash_table_lookup(vpn_connection_hash,
729 (gpointer) connection_path);
730 if (*connection != NULL) {
731 DBG("Repetitive connection %s", (*connection)->name);
735 *connection = create_vpn_connection(connection_path,
737 if (*connection != NULL)
743 g_variant_iter_free(properties);
747 void remove_vpn_connection(struct vpn_connection *connection)
751 assert(connection != NULL);
753 vpn_connection_list = g_list_remove(vpn_connection_list,
754 (gpointer)connection);
756 g_hash_table_remove(vpn_connection_hash,
757 (gconstpointer)connection->path);
761 void sync_vpn_connections(void)
766 GVariant *connections;
767 GError *error = NULL;
769 connections = g_dbus_proxy_call_sync(get_vpn_manager_dbus_proxy(),
770 "GetConnections", NULL,
771 G_DBUS_CALL_FLAGS_NONE,
773 if (connections == NULL) {
774 ERROR("error info: %s", error->message); //LCOV_EXCL_LINE
775 g_error_free(error); //LCOV_EXCL_LINE
776 return; //LCOV_EXCL_LINE
779 print_str = g_variant_print(connections, TRUE);
780 DBG("connections: %s", print_str);
783 if (!vpn_connection_hash)
784 vpn_connection_hash = g_hash_table_new_full(
785 g_str_hash, g_str_equal,
786 NULL, free_vpn_connection);
787 DBG("hash: %p", vpn_connection_hash);
789 create_vpn_connections(connections);
791 g_variant_unref(connections);
795 * VPN Connection Methods
797 GList *vpn_get_connections(void)
801 return vpn_connection_list;
805 struct vpn_connection *vpn_get_connection(
806 const char *name, const char *host, const char *domain)
813 for (iter = vpn_connection_list; iter != NULL;
815 struct vpn_connection *connection =
816 (struct vpn_connection *)(iter->data);
818 if (g_str_equal(connection->name, name) &&
819 g_str_equal(connection->host, host) &&
820 (!domain || g_str_equal(connection->domain, domain)))
827 enum dvpnlib_err vpn_connection_clear_property(
828 struct vpn_connection *connection)
832 assert(connection != NULL);
835 * Only supported the "UserRoutes" item now;
837 value = g_variant_new("(s)", "UserRoutes");
839 return common_set_interface_call_method_sync(connection->dbus_proxy,
840 "ClearProperty", &value);
844 * Asynchronous connect callback
846 static void connect_callback(GObject *source_object,
847 GAsyncResult *res, gpointer user_data)
849 GError *error = NULL;
850 enum dvpnlib_err error_type = DVPNLIB_ERR_NONE;
852 struct common_reply_data *reply_data;
853 struct vpn_connection *connection;
855 reply_data = user_data;
859 connection = reply_data->user;
863 if (!connection->dbus_proxy)
866 ret = g_dbus_proxy_call_finish(connection->dbus_proxy, res, &error);
868 DBG("%s", error->message);
869 error_type = get_error_type(error);
873 g_variant_unref(ret);
875 if (reply_data->cb) {
876 dvpnlib_reply_cb callback = reply_data->cb;
877 callback(error_type, reply_data->data);
884 enum dvpnlib_err vpn_connection_connect(struct vpn_connection *connection,
885 dvpnlib_reply_cb callback,
890 struct common_reply_data *reply_data;
892 assert(connection != NULL);
895 common_reply_data_new(callback, user_data, connection, TRUE);
897 return common_set_interface_call_method(connection->dbus_proxy,
899 (GAsyncReadyCallback)
900 connect_callback, reply_data);
904 vpn_connection_disconnect(struct vpn_connection *connection)
908 assert(connection != NULL);
910 return common_set_interface_call_method_sync(connection->dbus_proxy,
915 const char *vpn_connection_get_type(
916 struct vpn_connection *connection)
918 assert(connection != NULL);
920 return connection->type;
923 const char *vpn_connection_get_name(
924 struct vpn_connection *connection)
926 assert(connection != NULL);
928 return connection->name;
931 const char *vpn_connection_get_path(
932 struct vpn_connection *connection)
934 assert(connection != NULL);
936 return connection->path;
939 const char *vpn_connection_get_domain(
940 struct vpn_connection *connection)
942 assert(connection != NULL);
944 return connection->domain;
947 const char *vpn_connection_get_host(
948 struct vpn_connection *connection)
950 assert(connection != NULL);
952 return connection->host;
955 bool vpn_connection_get_immutable(
956 struct vpn_connection *connection)
958 assert(connection != NULL);
960 return connection->immutable;
963 int vpn_connection_get_index(
964 struct vpn_connection *connection)
966 assert(connection != NULL);
968 return connection->index;
971 enum vpn_connection_state vpn_connection_get_state(
972 struct vpn_connection *connection)
974 assert(connection != NULL);
976 return connection->state;
979 const struct vpn_connection_ipv4 *vpn_connection_get_ipv4(
980 struct vpn_connection *connection)
982 assert(connection != NULL);
984 return connection->ipv4;
987 const struct vpn_connection_ipv6 *vpn_connection_get_ipv6(
988 struct vpn_connection *connection)
990 assert(connection != NULL);
992 return connection->ipv6;
995 char **vpn_connection_get_nameservers(
996 struct vpn_connection *connection)
998 assert(connection != NULL);
1000 return connection->nameservers;
1003 GSList *vpn_connection_get_user_routes(
1004 struct vpn_connection *connection)
1006 assert(connection != NULL);
1008 return connection->user_routes;
1011 GSList *vpn_connection_get_server_routes(
1012 struct vpn_connection *connection)
1014 assert(connection != NULL);
1016 return connection->server_routes;
1019 enum dvpnlib_err vpn_connection_set_property_changed_cb(
1020 struct vpn_connection *connection,
1021 enum vpn_connection_property_type type,
1022 vpn_connection_property_changed_cb cb,
1027 if (connection == NULL)
1028 return DVPNLIB_ERR_INVALID_PARAMETER;
1030 struct connection_property_changed_cb *property_changed_cb_t =
1031 g_try_new0(struct connection_property_changed_cb, 1);
1032 if (property_changed_cb_t == NULL) {
1034 return DVPNLIB_ERR_FAILED;
1036 property_changed_cb_t->property_changed_cb = cb;
1037 property_changed_cb_t->user_data = user_data;
1039 g_hash_table_insert(connection->property_changed_cb_hash,
1040 GINT_TO_POINTER(type),
1041 (gpointer)property_changed_cb_t);
1043 return DVPNLIB_ERR_NONE;
1046 enum dvpnlib_err vpn_connection_unset_property_changed_cb(
1047 struct vpn_connection *connection,
1048 enum vpn_connection_property_type type)
1052 if (connection == NULL)
1053 return DVPNLIB_ERR_INVALID_PARAMETER;
1055 struct connection_property_changed_cb *property_changed_cb_t =
1056 get_connection_property_changed_cb(connection, type);
1058 if (property_changed_cb_t == NULL) {
1059 DBG("Can't find connection property changed callback");
1060 return DVPNLIB_ERR_FAILED;
1063 g_hash_table_remove(connection->property_changed_cb_hash,
1064 GINT_TO_POINTER(type));
1066 return DVPNLIB_ERR_NONE;