iptables: Refactoring how jumps are handled
[framework/connectivity/connman.git] / src / inet.c
index 12c87e7..d898650 100644 (file)
@@ -88,13 +88,15 @@ int __connman_inet_modify_address(int cmd, int flags,
        struct in_addr ipv4_addr, ipv4_dest, ipv4_bcast;
        int sk, err;
 
-       DBG("");
+       DBG("cmd %#x flags %#x index %d family %d address %s peer %s "
+               "prefixlen %hhu broadcast %s", cmd, flags, index, family,
+               address, peer, prefixlen, broadcast);
 
        if (address == NULL)
-               return -1;
+               return -EINVAL;
 
        if (family != AF_INET && family != AF_INET6)
-               return -1;
+               return -EINVAL;
 
        memset(&request, 0, sizeof(request));
 
@@ -150,7 +152,7 @@ int __connman_inet_modify_address(int cmd, int flags,
 
        sk = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
        if (sk < 0)
-               return -1;
+               return -errno;
 
        memset(&nl_addr, 0, sizeof(nl_addr));
        nl_addr.nl_family = AF_NETLINK;
@@ -541,6 +543,7 @@ struct in6_ifreq {
 int connman_inet_set_ipv6_address(int index,
                struct connman_ipaddress *ipaddress)
 {
+       int err;
        unsigned char prefix_len;
        const char *address;
 
@@ -552,11 +555,12 @@ int connman_inet_set_ipv6_address(int index,
 
        DBG("index %d address %s prefix_len %d", index, address, prefix_len);
 
-       if ((__connman_inet_modify_address(RTM_NEWADDR,
-                       NLM_F_REPLACE | NLM_F_ACK, index, AF_INET6,
-                               address, NULL, prefix_len, NULL)) < 0) {
-               connman_error("Set IPv6 address error");
-               return -1;
+       err = __connman_inet_modify_address(RTM_NEWADDR,
+                               NLM_F_REPLACE | NLM_F_ACK, index, AF_INET6,
+                               address, NULL, prefix_len, NULL);
+       if (err < 0) {
+               connman_error("%s: %s", __func__, strerror(-err));
+               return err;
        }
 
        return 0;
@@ -564,6 +568,7 @@ int connman_inet_set_ipv6_address(int index,
 
 int connman_inet_set_address(int index, struct connman_ipaddress *ipaddress)
 {
+       int err;
        unsigned char prefix_len;
        const char *address, *broadcast, *peer;
 
@@ -577,11 +582,12 @@ int connman_inet_set_address(int index, struct connman_ipaddress *ipaddress)
 
        DBG("index %d address %s prefix_len %d", index, address, prefix_len);
 
-       if ((__connman_inet_modify_address(RTM_NEWADDR,
-                       NLM_F_REPLACE | NLM_F_ACK, index, AF_INET,
-                               address, peer, prefix_len, broadcast)) < 0) {
-               DBG("address setting failed");
-               return -1;
+       err = __connman_inet_modify_address(RTM_NEWADDR,
+                               NLM_F_REPLACE | NLM_F_ACK, index, AF_INET,
+                               address, peer, prefix_len, broadcast);
+       if (err < 0) {
+               connman_error("%s: %s", __func__, strerror(-err));
+               return err;
        }
 
        return 0;
@@ -590,12 +596,15 @@ int connman_inet_set_address(int index, struct connman_ipaddress *ipaddress)
 int connman_inet_clear_ipv6_address(int index, const char *address,
                                                        int prefix_len)
 {
+       int err;
+
        DBG("index %d address %s prefix_len %d", index, address, prefix_len);
 
-       if ((__connman_inet_modify_address(RTM_DELADDR, 0, index, AF_INET6,
-                                       address, NULL, prefix_len, NULL)) < 0) {
-               connman_error("Clear IPv6 address error");
-               return -1;
+       err = __connman_inet_modify_address(RTM_DELADDR, 0, index, AF_INET6,
+                               address, NULL, prefix_len, NULL);
+       if (err < 0) {
+               connman_error("%s: %s", __func__, strerror(-err));
+               return err;
        }
 
        return 0;
@@ -603,6 +612,7 @@ int connman_inet_clear_ipv6_address(int index, const char *address,
 
 int connman_inet_clear_address(int index, struct connman_ipaddress *ipaddress)
 {
+       int err;
        unsigned char prefix_len;
        const char *address, *broadcast, *peer;
 
@@ -613,10 +623,11 @@ int connman_inet_clear_address(int index, struct connman_ipaddress *ipaddress)
 
        DBG("index %d address %s prefix_len %d", index, address, prefix_len);
 
-       if ((__connman_inet_modify_address(RTM_DELADDR, 0, index, AF_INET,
-                               address, peer, prefix_len, broadcast)) < 0) {
-               DBG("address removal failed");
-               return -1;
+       err = __connman_inet_modify_address(RTM_DELADDR, 0, index, AF_INET,
+                               address, peer, prefix_len, broadcast);
+       if (err < 0) {
+               connman_error("%s: %s", __func__, strerror(-err));
+               return err;
        }
 
        return 0;
@@ -772,7 +783,8 @@ int connman_inet_del_ipv6_network_route(int index, const char *host,
        close(sk);
 out:
        if (err < 0)
-               connman_error("Del IPv6 host route error");
+               connman_error("Del IPv6 host route error (%s)",
+                                               strerror(errno));
 
        return err;
 }
@@ -784,7 +796,7 @@ int connman_inet_del_ipv6_host_route(int index, const char *host)
 
 int connman_inet_add_ipv6_network_route(int index, const char *host,
                                        const char *gateway,
-                                               unsigned char prefix_len)
+                                       unsigned char prefix_len)
 {
        struct in6_rtmsg rt;
        int sk, err;
@@ -822,7 +834,8 @@ int connman_inet_add_ipv6_network_route(int index, const char *host,
        close(sk);
 out:
        if (err < 0)
-               connman_error("Set IPv6 host route error");
+               connman_error("Set IPv6 host route error (%s)",
+                                               strerror(errno));
 
        return err;
 }
@@ -864,7 +877,8 @@ int connman_inet_set_ipv6_gateway_address(int index, const char *gateway)
        close(sk);
 out:
        if (err < 0)
-               connman_error("Set default IPv6 gateway error");
+               connman_error("Set default IPv6 gateway error (%s)",
+                                               strerror(errno));
 
        return err;
 }
@@ -900,7 +914,8 @@ int connman_inet_clear_ipv6_gateway_address(int index, const char *gateway)
        close(sk);
 out:
        if (err < 0)
-               connman_error("Clear default IPv6 gateway error");
+               connman_error("Clear default IPv6 gateway error (%s)",
+                                               strerror(errno));
 
        return err;
 }
@@ -999,6 +1014,52 @@ int connman_inet_set_gateway_interface(int index)
        return err;
 }
 
+int connman_inet_set_ipv6_gateway_interface(int index)
+{
+       struct ifreq ifr;
+       struct rtentry rt;
+       struct sockaddr_in6 addr;
+       const struct in6_addr any = IN6ADDR_ANY_INIT;
+       int sk, err;
+
+       DBG("");
+
+       sk = socket(PF_INET6, SOCK_DGRAM, 0);
+       if (sk < 0)
+               return -1;
+
+       memset(&ifr, 0, sizeof(ifr));
+       ifr.ifr_ifindex = index;
+
+       if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
+               close(sk);
+               return -1;
+       }
+
+       DBG("ifname %s", ifr.ifr_name);
+
+       memset(&rt, 0, sizeof(rt));
+       rt.rt_flags = RTF_UP;
+
+       memset(&addr, 0, sizeof(addr));
+       addr.sin6_family = AF_INET6;
+       addr.sin6_addr = any;
+
+       memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
+       memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
+       memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
+
+       rt.rt_dev = ifr.ifr_name;
+
+       err = ioctl(sk, SIOCADDRT, &rt);
+       if (err < 0)
+               connman_error("Setting default interface route failed (%s)",
+                                                       strerror(errno));
+       close(sk);
+
+       return err;
+}
+
 int connman_inet_clear_gateway_address(int index, const char *gateway)
 {
        struct ifreq ifr;
@@ -1095,6 +1156,52 @@ int connman_inet_clear_gateway_interface(int index)
        return err;
 }
 
+int connman_inet_clear_ipv6_gateway_interface(int index)
+{
+       struct ifreq ifr;
+       struct rtentry rt;
+       struct sockaddr_in6 addr;
+       const struct in6_addr any = IN6ADDR_ANY_INIT;
+       int sk, err;
+
+       DBG("");
+
+       sk = socket(PF_INET6, SOCK_DGRAM, 0);
+       if (sk < 0)
+               return -1;
+
+       memset(&ifr, 0, sizeof(ifr));
+       ifr.ifr_ifindex = index;
+
+       if (ioctl(sk, SIOCGIFNAME, &ifr) < 0) {
+               close(sk);
+               return -1;
+       }
+
+       DBG("ifname %s", ifr.ifr_name);
+
+       memset(&rt, 0, sizeof(rt));
+       rt.rt_flags = RTF_UP;
+
+       memset(&addr, 0, sizeof(addr));
+       addr.sin6_family = AF_INET6;
+       addr.sin6_addr = any;
+
+       memcpy(&rt.rt_genmask, &addr, sizeof(rt.rt_genmask));
+       memcpy(&rt.rt_dst, &addr, sizeof(rt.rt_dst));
+       memcpy(&rt.rt_gateway, &addr, sizeof(rt.rt_gateway));
+
+       rt.rt_dev = ifr.ifr_name;
+
+       err = ioctl(sk, SIOCDELRT, &rt);
+       if (err < 0)
+               connman_error("Removing default interface route failed (%s)",
+                                                       strerror(errno));
+       close(sk);
+
+       return err;
+}
+
 connman_bool_t connman_inet_compare_subnet(int index, const char *host)
 {
        struct ifreq ifr;