#include <vconf.h>
#include <vconf-keys.h>
+#include <stdlib.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
#include "wifi.h"
#include "log.h"
gboolean netconfig_iface_network_state_add_route(
NetconfigNetworkState *master,
gchar *ip_addr, gchar *netmask,
- gchar *interface, gboolean *result, GError **error);
+ gchar *interface, gchar *gateway, gint32 address_family, gboolean *result, GError **error);
gboolean netconfig_iface_network_state_remove_route(
NetconfigNetworkState *master,
gchar *ip_addr, gchar *netmask,
- gchar *interface, gboolean *result, GError **error);
+ gchar *interface, gchar *gateway, gint32 address_family, gboolean *result, GError **error);
gboolean netconfig_iface_network_state_ethernet_cable_state(
NetconfigNetworkState *master, gint32 *state, GError **error);
gboolean netconfig_iface_network_state_add_route(
NetconfigNetworkState *master,
gchar *ip_addr, gchar *netmask,
- gchar *interface, gboolean *result, GError **error)
+ gchar *interface, gchar *gateway, gint32 address_family, gboolean *result, GError **error)
{
- gboolean ret = FALSE;
- gboolean rv = FALSE;
const char *path = ROUTE_EXEC_PATH;
- char *const args[] = {"route", "add",
- "-net", ip_addr,
- "netmask", netmask,
- "dev", interface,
- 0};
+ char *const args[] = { "/sbin/route", "add", "-net", ip_addr,
+ "netmask", netmask, "dev", interface, NULL };
char *const envs[] = { NULL };
+ const char* buf = NULL;
+ char* ch = NULL;
+ int prefix_len = 0;
+ int pos = 0;
+
+ DBG("ip_addr(%s), netmask(%s), interface(%s), gateway(%s)", ip_addr, netmask, interface, gateway);
+
+ switch(address_family) {
+ case AF_INET:
+ if (ip_addr == NULL || netmask == NULL || interface == NULL) {
+ ERR("Invalid parameter");
+ netconfig_error_invalid_parameter(error);
+ *result = FALSE;
+ return FALSE;
+ }
+ if (netconfig_execute_file(path, args, envs) < 0) {
+ DBG("Failed to add a new route");
+ netconfig_error_permission_denied(error);
+ *result = FALSE;
+ return FALSE;
+ }
+ break;
+ case AF_INET6:
+ if (ip_addr == NULL || interface == NULL || gateway == NULL) {
+ ERR("Invalid parameter");
+ netconfig_error_invalid_parameter(error);
+ *result = FALSE;
+ return FALSE;
+ }
- DBG("ip_addr(%s), netmask(%s), interface(%s)", ip_addr, netmask, interface);
-
- if (ip_addr == NULL || netmask == NULL || interface == NULL) {
- DBG("Invalid parameter!");
- goto done;
- }
+ buf = ip_addr;
+ ch = strchr(buf, '/');
+ pos = ch - buf + 1;
+ if (ch) {
+ prefix_len = atoi(ch + 1);
+ ip_addr[pos-1] = '\0';
+ } else {
+ prefix_len = 128;
+ }
- rv = netconfig_execute_file(path, args, envs);
- if (rv != TRUE) {
- DBG("Failed to add a new route");
- goto done;
+ if (netconfig_add_route_ipv6(ip_addr, interface, gateway, prefix_len) < 0) {
+ DBG("Failed to add a new route");
+ netconfig_error_permission_denied(error);
+ *result = FALSE;
+ return FALSE;
+ }
+ break;
+ default:
+ DBG("Unknown Address Family");
+ netconfig_error_invalid_parameter(error);
+ *result = FALSE;
+ return FALSE;
}
DBG("Successfully added a new route");
- ret = TRUE;
-
-done:
- *result = ret;
- return ret;
+ *result = TRUE;
+ return TRUE;
}
gboolean netconfig_iface_network_state_remove_route(
NetconfigNetworkState *master,
gchar *ip_addr, gchar *netmask,
- gchar *interface, gboolean *result, GError **error)
+ gchar *interface, gchar *gateway, gint32 address_family, gboolean *result, GError **error)
{
- gboolean ret = FALSE;
- gboolean rv = FALSE;
const char *path = ROUTE_EXEC_PATH;
- char *const args[] = {"route", "del",
- "-net", ip_addr,
- "netmask", netmask,
- "dev", interface,
- 0};
+ char *const args[] = { "/sbin/route", "del", "-net", ip_addr,
+ "netmask", netmask, "dev", interface, NULL };
char *const envs[] = { NULL };
+ const char* buf = NULL;
+ char* ch = NULL;
+ int prefix_len = 0;
+ int pos = 0;
+
+ DBG("ip_addr(%s), netmask(%s), interface(%s), gateway(%s)", ip_addr, netmask, interface, gateway);
+
+ switch(address_family) {
+ case AF_INET:
+ if (ip_addr == NULL || netmask == NULL || interface == NULL) {
+ DBG("Invalid parameter!");
+ netconfig_error_invalid_parameter(error);
+ *result = FALSE;
+ return FALSE;
+ }
+ if (netconfig_execute_file(path, args, envs) < 0) {
+ DBG("Failed to remove the route");
+ netconfig_error_permission_denied(error);
+ *result = FALSE;
+ return FALSE;
+ }
+ break;
+ case AF_INET6:
+ if (ip_addr == NULL || interface == NULL || gateway == NULL) {
+ DBG("Invalid parameter!");
+ netconfig_error_invalid_parameter(error);
+ *result = FALSE;
+ return FALSE;
+ }
- DBG("ip_addr(%s), netmask(%s), interface(%s)", ip_addr, netmask, interface);
-
- if (ip_addr == NULL || netmask == NULL || interface == NULL) {
- DBG("Invalid parameter!");
- goto done;
- }
+ buf = ip_addr;
+ ch = strchr(buf, '/');
+ pos = ch - buf + 1;
+ if (ch) {
+ prefix_len = atoi(ch + 1);
+ ip_addr[pos-1] = '\0';
+ } else {
+ prefix_len = 128;
+ }
- rv = netconfig_execute_file(path, args, envs);
- if (rv != TRUE) {
- DBG("Failed to remove a new route");
- goto done;
+ if (netconfig_del_route_ipv6(ip_addr, interface, gateway, prefix_len) < 0) {
+ DBG("Failed to remove the route");
+ netconfig_error_permission_denied(error);
+ *result = FALSE;
+ return FALSE;
+ }
+ break;
+ default:
+ DBG("Unknown Address Family");
+ netconfig_error_invalid_parameter(error);
+ *result = FALSE;
+ return FALSE;
}
- DBG("Successfully remove a new route");
- ret = TRUE;
+ DBG("Successfully removed the route");
+ *result = TRUE;
-done:
- *result = ret;
- return ret;
+ return TRUE;
}
gboolean netconfig_iface_network_state_ethernet_cable_state(
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
+#include <net/route.h>
+#include <arpa/inet.h>
#include <vconf.h>
#include <vconf-keys.h>
#include <wifi-direct.h>
return FALSE;
}
+int netconfig_add_route_ipv6(gchar *ip_addr, gchar *interface, gchar *gateway, unsigned char prefix_len)
+{
+ struct in6_rtmsg rt;
+ int fd = 0;
+ int err = 0;
+
+ memset(&rt, 0, sizeof(rt));
+
+ rt.rtmsg_dst_len = prefix_len;
+
+ rt.rtmsg_flags = RTF_UP | RTF_HOST;
+
+ if (inet_pton(AF_INET6, ip_addr, &rt.rtmsg_dst) < 0) {
+ err = -errno;
+ return err;
+ }
+
+ if (gateway != NULL) {
+ rt.rtmsg_flags |= RTF_GATEWAY;
+ if (inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway) < 0) {
+ err = -errno;
+ return err;
+ }
+ }
+
+ rt.rtmsg_metric = 1;
+
+ fd = socket(AF_INET6, SOCK_DGRAM, 0);
+ if (fd < 0)
+ return -1;
+
+ rt.rtmsg_ifindex = 0;
+
+ if (interface) {
+ struct ifreq ifr;
+ memset(&ifr, 0, sizeof(ifr));
+ strcpy(ifr.ifr_name, interface);
+ ioctl(fd, SIOCGIFINDEX, &ifr);
+ rt.rtmsg_ifindex = ifr.ifr_ifindex;
+ }
+
+ if ((err = ioctl(fd, SIOCADDRT, &rt)) < 0) {
+ DBG("Failed to add route: %d\n", err);
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+
+ return 1;
+}
+
+int netconfig_del_route_ipv6(gchar *ip_addr, gchar *interface, gchar *gateway, unsigned char prefix_len)
+{
+ struct in6_rtmsg rt;
+ int fd = 0;
+ int err = 0;
+
+ memset(&rt, 0, sizeof(rt));
+
+ rt.rtmsg_dst_len = prefix_len;
+
+ rt.rtmsg_flags = RTF_UP | RTF_HOST;
+
+ if (inet_pton(AF_INET6, ip_addr, &rt.rtmsg_dst) < 0) {
+ err = -errno;
+ return err;
+ }
+
+ if (gateway != NULL) {
+ rt.rtmsg_flags |= RTF_GATEWAY;
+ if (inet_pton(AF_INET6, gateway, &rt.rtmsg_gateway) < 0) {
+ err = -errno;
+ return err;
+ }
+ }
+
+ rt.rtmsg_metric = 1;
+
+ fd = socket(AF_INET6, SOCK_DGRAM, 0);
+ if (fd < 0)
+ return -1;
+
+ rt.rtmsg_ifindex = 0;
+
+ if (interface) {
+ struct ifreq ifr;
+ memset(&ifr, 0, sizeof(ifr));
+ strcpy(ifr.ifr_name, interface);
+ ioctl(fd, SIOCGIFINDEX, &ifr);
+ rt.rtmsg_ifindex = ifr.ifr_ifindex;
+ }
+
+ if ((err = ioctl(fd, SIOCDELRT, &rt)) < 0) {
+ DBG("Failed to add route: %d\n", err);
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+
+ return 1;
+}
+
gboolean netconfig_iface_wifi_launch_direct(NetconfigWifi *wifi, GError **error)
{
gboolean ret = TRUE;