| /* |
| * |
| * Connection Manager |
| * |
| * Copyright (C) 2007-2013 Intel Corporation. All rights reserved. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License version 2 as |
| * published by the Free Software Foundation. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| * |
| */ |
| |
| #ifdef HAVE_CONFIG_H |
| #include <config.h> |
| #endif |
| |
| #include <errno.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include <stdlib.h> |
| #include <glib.h> |
| |
| #include <connman/ipaddress.h> |
| |
| #include "connman.h" |
| |
| unsigned char connman_ipaddress_calc_netmask_len(const char *netmask) |
| { |
| unsigned char bits; |
| in_addr_t mask; |
| in_addr_t host; |
| |
| if (!netmask) |
| return 32; |
| |
| mask = inet_network(netmask); |
| host = ~mask; |
| |
| /* a valid netmask must be 2^n - 1 */ |
| if ((host & (host + 1)) != 0) |
| return -1; |
| |
| bits = 0; |
| for (; mask; mask <<= 1) |
| ++bits; |
| |
| return bits; |
| } |
| |
| struct connman_ipaddress *connman_ipaddress_alloc(int family) |
| { |
| struct connman_ipaddress *ipaddress; |
| |
| ipaddress = g_try_new0(struct connman_ipaddress, 1); |
| if (!ipaddress) |
| return NULL; |
| |
| ipaddress->family = family; |
| ipaddress->prefixlen = 0; |
| ipaddress->local = NULL; |
| ipaddress->peer = NULL; |
| ipaddress->broadcast = NULL; |
| ipaddress->gateway = NULL; |
| |
| return ipaddress; |
| } |
| |
| void connman_ipaddress_free(struct connman_ipaddress *ipaddress) |
| { |
| if (!ipaddress) |
| return; |
| |
| g_free(ipaddress->broadcast); |
| g_free(ipaddress->peer); |
| g_free(ipaddress->local); |
| g_free(ipaddress->gateway); |
| g_free(ipaddress); |
| } |
| |
| static bool check_ipv6_address(const char *address) |
| { |
| unsigned char buf[sizeof(struct in6_addr)]; |
| int err; |
| |
| if (!address) |
| return false; |
| |
| err = inet_pton(AF_INET6, address, buf); |
| if (err > 0) |
| return true; |
| |
| return false; |
| } |
| |
| int connman_ipaddress_set_ipv6(struct connman_ipaddress *ipaddress, |
| const char *address, |
| unsigned char prefix_length, |
| const char *gateway) |
| { |
| if (!ipaddress) |
| return -EINVAL; |
| |
| if (!check_ipv6_address(address)) |
| return -EINVAL; |
| |
| DBG("prefix_len %d address %s gateway %s", |
| prefix_length, address, gateway); |
| |
| ipaddress->family = AF_INET6; |
| |
| ipaddress->prefixlen = prefix_length; |
| |
| g_free(ipaddress->local); |
| ipaddress->local = g_strdup(address); |
| |
| g_free(ipaddress->gateway); |
| ipaddress->gateway = g_strdup(gateway); |
| |
| return 0; |
| } |
| |
| int connman_ipaddress_get_ip(struct connman_ipaddress *ipaddress, |
| const char **address, |
| unsigned char *netmask_prefix_length) |
| { |
| if (!ipaddress) |
| return -EINVAL; |
| |
| *netmask_prefix_length = ipaddress->prefixlen; |
| *address = ipaddress->local; |
| |
| return 0; |
| } |
| |
| int connman_ipaddress_set_ipv4(struct connman_ipaddress *ipaddress, |
| const char *address, const char *netmask, const char *gateway) |
| { |
| if (!ipaddress) |
| return -EINVAL; |
| |
| ipaddress->family = AF_INET; |
| |
| ipaddress->prefixlen = connman_ipaddress_calc_netmask_len(netmask); |
| |
| g_free(ipaddress->local); |
| ipaddress->local = g_strdup(address); |
| |
| g_free(ipaddress->gateway); |
| ipaddress->gateway = g_strdup(gateway); |
| |
| return 0; |
| } |
| |
| void connman_ipaddress_set_peer(struct connman_ipaddress *ipaddress, |
| const char *peer) |
| { |
| if (!ipaddress) |
| return; |
| |
| g_free(ipaddress->peer); |
| ipaddress->peer = g_strdup(peer); |
| } |
| |
| void connman_ipaddress_clear(struct connman_ipaddress *ipaddress) |
| { |
| if (!ipaddress) |
| return; |
| |
| ipaddress->prefixlen = 0; |
| |
| g_free(ipaddress->local); |
| ipaddress->local = NULL; |
| |
| g_free(ipaddress->peer); |
| ipaddress->peer = NULL; |
| |
| g_free(ipaddress->broadcast); |
| ipaddress->broadcast = NULL; |
| |
| g_free(ipaddress->gateway); |
| ipaddress->gateway = NULL; |
| } |
| |
| /* |
| * Note that this copy function only copies the actual address and |
| * prefixlen. Use the other copy function to copy the whole struct. |
| */ |
| void connman_ipaddress_copy_address(struct connman_ipaddress *ipaddress, |
| struct connman_ipaddress *source) |
| { |
| if (!ipaddress || !source) |
| return; |
| |
| ipaddress->family = source->family; |
| ipaddress->prefixlen = source->prefixlen; |
| |
| g_free(ipaddress->local); |
| ipaddress->local = g_strdup(source->local); |
| } |
| |
| struct connman_ipaddress * |
| connman_ipaddress_copy(struct connman_ipaddress *ipaddress) |
| { |
| struct connman_ipaddress *copy; |
| |
| if (!ipaddress) |
| return NULL; |
| |
| copy = g_new0(struct connman_ipaddress, 1); |
| |
| copy->family = ipaddress->family; |
| copy->prefixlen = ipaddress->prefixlen; |
| copy->local = g_strdup(ipaddress->local); |
| copy->peer = g_strdup(ipaddress->peer); |
| copy->broadcast = g_strdup(ipaddress->broadcast); |
| copy->gateway = g_strdup(ipaddress->gateway); |
| |
| return copy; |
| } |