diff options
Diffstat (limited to 'hicn-light/src/socket')
-rw-r--r-- | hicn-light/src/socket/CMakeLists.txt | 31 | ||||
-rw-r--r-- | hicn-light/src/socket/api.c | 604 | ||||
-rw-r--r-- | hicn-light/src/socket/api.h | 217 | ||||
-rw-r--r-- | hicn-light/src/socket/error.c | 7 | ||||
-rw-r--r-- | hicn-light/src/socket/error.h | 46 | ||||
-rw-r--r-- | hicn-light/src/socket/ops.h | 54 | ||||
-rw-r--r-- | hicn-light/src/socket/ops_linux.c | 1723 |
7 files changed, 0 insertions, 2682 deletions
diff --git a/hicn-light/src/socket/CMakeLists.txt b/hicn-light/src/socket/CMakeLists.txt deleted file mode 100644 index 6ea94dcfa..000000000 --- a/hicn-light/src/socket/CMakeLists.txt +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at: -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -cmake_minimum_required(VERSION 3.5 FATAL_ERROR) - -if (UNIX AND NOT APPLE AND NOT ANDROID_API) - list(APPEND HEADER_FILES - socket/api.h - socket/error.h - socket/ops.h - ) - - list(APPEND SOURCE_FILES - socket/api.c - socket/error.c - socket/ops_linux.c - ) -endif() - -set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE) -set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE)
\ No newline at end of file diff --git a/hicn-light/src/socket/api.c b/hicn-light/src/socket/api.c deleted file mode 100644 index aede01efe..000000000 --- a/hicn-light/src/socket/api.c +++ /dev/null @@ -1,604 +0,0 @@ -#include <arpa/inet.h> // inet_ntop -#include <netdb.h> // '' -#include <search.h> // tfind(), tdestroy(), twalk(), preorder... -#include <stdbool.h> -#include <stdio.h> // perror -#include <stdlib.h> // calloc -#include <string.h> // memcpy -#include <sys/socket.h> // '' -#include <sys/types.h> // getaddrinfo -#include <unistd.h> // close - -#include "api.h" -#include "error.h" -#include "ops.h" - -#define INET_MAX_ADDRSTRLEN INET6_ADDRSTRLEN - -#define IF_NAMESIZE 16 -#define MAX_TABLES 256 - -#define DEFAULT_INTERVAL 1000 -#define DEFAULT_IDENTIFIER "hicn" -#define DEFAULT_SOCKET_IDENTIFIER "main" -#define LOCAL_IPV6_PREFIX "fe80" - -#define LOCAL_PRIORITY 32000 - -extern hicn_socket_ops_t ops; - -/* Configuration stored as a global variable to allow access from signal - * handlers for instance */ - -static hicn_conf_t hicn_default_conf = { - .identifier = DEFAULT_IDENTIFIER, - //.format = HF_INET6_TCP -}; - -/* Global state */ -// FIXME move into helper state ? - -struct ip_rule_state_ { - char tun_name[IF_NAMESIZE]; - ip_address_t ip_address; - uint32_t table_id; - uint8_t priority; - uint8_t address_family; -}; - -struct ip_route_state_ { - char remote_ip_address[128]; // this is to big, but it is fine for now - uint8_t address_family; - uint32_t table_id; -}; - -typedef struct ip_rule_state_ ip_rule_state; -typedef struct ip_route_state_ ip_route_state; - -int punting_table_id; -uint16_t rules_counter; -uint16_t routes_counter; -static ip_rule_state rules_to_remove[MAX_TABLES]; -static ip_route_state routes_to_remove[MAX_TABLES]; - -// END FIXME - -hicn_socket_helper_t *hicn_create() { - int rc; - - punting_table_id = -1; - rules_counter = 0; - - hicn_socket_helper_t *hicn = malloc(sizeof(hicn_socket_helper_t)); - if (!hicn) { - goto ERR_MALLOC; - } - - hicn->conf = malloc(sizeof(hicn_conf_t)); - if (hicn->conf < 0) goto ERR_CONF; - memcpy(hicn->conf, &hicn_default_conf, sizeof(hicn_conf_t)); - - /* Initialize socket tree to empty */ - hicn->socket_root = NULL; - - // enable forwarding globally. Per-interface forwarding will be enabled when - // interfaces are created (TODO) - rc = ops.enable_v6_forwarding(NULL); - if (rc < 0) { - goto ERR_FW; - } - - rc = ops.enable_v4_forwarding(); - if (rc < 0) { - goto ERR_FW; - } - - // modify priority of table local - /* ip -6 rule del from all prio 0 table local */ - /* ip -6 rule add from all prio 32000 table local */ - - rc = ops.del_lo_prio_rule(NULL, AF_INET6, 0); - if (rc < 0) { - goto ERR_FW; - } - - rc = ops.del_lo_prio_rule(NULL, AF_INET, 0); - if (rc < 0) { - goto ERR_FW; - } - - rc = ops.add_lo_prio_rule(NULL, AF_INET6, LOCAL_PRIORITY); - if (rc < 0) { - goto ERR_FW; - } - - rc = ops.add_lo_prio_rule(NULL, AF_INET, LOCAL_PRIORITY); - if (rc < 0) { - goto ERR_FW; - } - - return hicn; - -ERR_FW: - free(hicn->conf); -ERR_CONF: - free(hicn); -ERR_MALLOC: - return NULL; -} - -void hicn_destroy() { - int rc; - uint16_t i; - - /* Restore default rules */ - printf("Restoring default configuration.\n"); - rc = ops.del_lo_prio_rule(NULL, AF_INET6, LOCAL_PRIORITY); - if (rc < 0) { - goto ERR; - } - - rc = ops.del_lo_prio_rule(NULL, AF_INET, LOCAL_PRIORITY); - if (rc < 0) { - goto ERR; - } - - rc = ops.add_lo_prio_rule(NULL, AF_INET6, 0); - if (rc < 0) { - goto ERR; - } - - rc = ops.add_lo_prio_rule(NULL, AF_INET, 0); - if (rc < 0) { - goto ERR; - } - - for (i = 0; i < rules_counter; i++) { - if (strcmp(rules_to_remove[i].tun_name, "NONE") != 0) { - rc = ops.del_rule(rules_to_remove[i].tun_name, - rules_to_remove[i].address_family, - rules_to_remove[i].table_id); - if (rc < 0) { - goto ERR; - } - } else { - rc = ops.del_prio_rule( - &rules_to_remove[i].ip_address, rules_to_remove[i].address_family, - rules_to_remove[i].priority, rules_to_remove[i].table_id); - if (rc < 0) { - goto ERR; - } - } - } - - for (i = 0; i < routes_counter; i++) { - rc = ops.del_out_route(routes_to_remove[i].remote_ip_address, - routes_to_remove[i].address_family, - routes_to_remove[i].table_id); - if (rc < 0) { - goto ERR; - } - } - -ERR: - if (rc < 0) printf("Unexpected exit. Some state may not be deleted.\n"); - return; -} - -void hicn_free(hicn_socket_helper_t *hicn) { - // close tun ? - free(hicn); -} - -hicn_socket_t *hicn_socket_create() { - hicn_socket_t *socket = calloc(1, sizeof(hicn_socket_t)); - if (!socket) { - goto ERR_SOCKET; - } - socket->type = HS_UNSPEC; - - return socket; - -ERR_SOCKET: - return NULL; -} - -int hicn_socket_cmp(hicn_socket_t *a, hicn_socket_t *b) { - return b->fd - a->fd; -} - -ip_address_t *hicn_socket_get_src_ip(hicn_socket_t *socket) { - if (socket->type != HS_CONNECTION) { - return NULL; - } - return &socket->connection.tun_ip_address; -} - -typedef int (*cmp_t)(const void *, const void *); - -int hicn_socket_add(hicn_socket_helper_t *hicn, hicn_socket_t *socket) { - if (!(tsearch(socket, &hicn->socket_root, (cmp_t)hicn_socket_cmp))) { - // ERROR("Could not insert field id into index"); - return -1; - } - return 0; -} - -hicn_socket_t *hicn_socket_find(hicn_socket_helper_t *hicn, int fd) { - hicn_socket_t search = { - .fd = fd, - }; - hicn_socket_t **socket = - tfind(&search, &hicn->socket_root, (cmp_t)hicn_socket_cmp); - return socket ? *socket : NULL; -} - -/******************************************************************************* - * New API - *******************************************************************************/ - -int hicn_set_local_endpoint(hicn_socket_t *socket, const char *local_ip_address, - bool allow_null) { - int rc = HICN_SOCKET_ERROR_NONE; - - if (!local_ip_address) { - if (!allow_null) { - rc = HICN_SOCKET_ERROR_SOCKET_LOCAL_NULL_ADDRESS; - } - goto end; - } - - /* local_ip_address should be a prefix with global scope in which to pick - * the locator address to use as the source. - * If we expect to pick another IP for the tun, then it needs to be of size - * less than 128. - */ - - /* Copy the local IP address inside the connection */ - rc = hicn_ip_pton(local_ip_address, &socket->connection.tun_ip_address); - if (rc < 0) { - rc = HICN_SOCKET_ERROR_SOCKET_LOCAL_REPR; - goto end; - } - -end: - return rc; -} - -// XXX This could be used by hicn_set_remote_endpoint -// XXX This has been introduced for mapme -int hicn_get_local_address(const ip_address_t *remote_address, - ip_address_t *local_address) { - int rc = 0; - uint32_t interface_id; - char remote_address_str[INET_MAX_ADDRSTRLEN]; - - rc = hicn_ip_ntop(remote_address, remote_address_str, - sizeof(remote_address_str)); - if (rc < 0) { - rc = HICN_SOCKET_ERROR_BIND_REMOTE_REPR; - goto ERR; - } - - rc = ops.get_output_ifid(remote_address_str, remote_address->family, - &interface_id); - if (rc < 0 || interface_id == 0) { - rc = HICN_SOCKET_ERROR_BIND_REMOTE_INTERFACE; - goto ERR; - } - - /* Local ip */ - rc = ops.get_ip_addr(interface_id, remote_address->family, local_address); - if (rc < 0) { - rc = HICN_SOCKET_ERROR_BIND_REMOTE_NETMASK; - goto ERR; - } - -ERR: - return rc; -} - -/** - * - * sets socket->interface_id - */ -int hicn_set_remote_endpoint(hicn_socket_t *socket, - const char *remote_ip_address) { - int af, rc = HICN_SOCKET_ERROR_NONE; - ip_address_t addr; - - af = get_addr_family(remote_ip_address); - if ((af != AF_INET6) && (af != AF_INET)) { - return HICN_SOCKET_ERROR_INVALID_IP_ADDRESS; - } - - /* Bind local endpoint if not done yet */ - if (ip_address_empty(&socket->connection.tun_ip_address)) { - char local_ip_address[INET_MAX_ADDRSTRLEN]; - - /* Local interface id */ - // INFO("Getting interface_id from gateway IP address %s", - // remote_ip_address); - ///// - int addr_family = get_addr_family(remote_ip_address); - if (addr_family < 0) { - rc = addr_family; - goto ERR; - } - - rc = ops.get_output_ifid(remote_ip_address, (uint8_t)addr_family, - &socket->connection.interface_id); - if (rc < 0 || socket->connection.interface_id == 0) { - rc = HICN_SOCKET_ERROR_BIND_REMOTE_INTERFACE; - goto ERR; - } - - /* Local ip */ - rc = ops.get_ip_addr(socket->connection.interface_id, (uint8_t)addr_family, - &addr); - if (rc < 0) { - rc = HICN_SOCKET_ERROR_BIND_REMOTE_NETMASK; - goto ERR; - } - ///// - - /* Convert to representation format */ - rc = hicn_ip_ntop(&addr, local_ip_address, sizeof(local_ip_address)); - if (rc < 0) { - rc = HICN_SOCKET_ERROR_BIND_REMOTE_REPR; - goto ERR; - } - - rc = hicn_set_local_endpoint(socket, local_ip_address, true); - if (rc < 0) { - switch (rc) { - case HICN_SOCKET_ERROR_SOCKET_LOCAL_NULL_ADDRESS: - rc = HICN_SOCKET_ERROR_BIND_REMOTE_LOCAL_NULL_ADDR; - break; - case HICN_SOCKET_ERROR_SOCKET_LOCAL_REPR: - rc = HICN_SOCKET_ERROR_BIND_REMOTE_LOCAL_REPR; - break; - case HICN_SOCKET_ERROR_SOCKET_LOCAL_HEURISTIC: - rc = HICN_SOCKET_ERROR_BIND_REMOTE_LOCAL_HEURISTIC; - break; - case HICN_SOCKET_ERROR_SOCKET_LOCAL_SET_TUN_IP: - rc = HICN_SOCKET_ERROR_BIND_REMOTE_LOCAL_SET_TUN_IP; - break; - } - goto ERR; - } - } - return HICN_SOCKET_ERROR_NONE; - -ERR: - return rc; -} - -/** - * - * We need at least an identifier. - */ -int hicn_socket(hicn_socket_helper_t *hicn, const char *identifier, - const char *local_ip_address) { - int rc; - - hicn_socket_t *socket = hicn_socket_create(); - if (!socket) { - rc = -5; - goto ERR_SOCKET; - } - - ops.get_tun_name(hicn->conf->identifier, identifier, socket->tun_name); - - // register the hicn face on which to bind prefixes, create the in/out TUN - // device - socket->fd = ops.tun_create(socket->tun_name); - if (socket->fd <= 0) { - rc = -2; - goto ERR_TUN; - } - - // INFO("Successfully created listener on TUN device %s", socket->tun_name); - - /* Retrieve interface id */ - socket->tun_id = ops.get_ifid(socket->tun_name); - if (socket->tun_id < 0) { - rc = -3; - goto ERR_TUNIFID; - } - // INFO("Interface id=%d", socket->tun_id); - - // WARN("Need to set offload"); - - // INFO("Setting interface up"); - rc = ops.up_if(socket->tun_id); - if (rc < 0) { - rc = -4; - goto ERR_UP; - } - - /* Update state */ - rc = hicn_socket_add(hicn, socket); - if (rc < 0) { - rc = -5; - goto ERR_ADD; - } - - rc = hicn_set_local_endpoint(socket, local_ip_address, true); - if (rc < 0) { - rc = -6; - goto ERR_ADJACENCY; - } - - return socket->fd; - -ERR_ADJACENCY: -ERR_ADD: -ERR_UP: -ERR_TUNIFID: -ERR_TUN: - free(socket); -ERR_SOCKET: - // ERR_PARAMS: - return rc; -} - -int hicn_listen(hicn_socket_helper_t *hicn, int fd, const char *prefix) { - int rc; - hicn_socket_t *socket = hicn_socket_find(hicn, fd); - if (!socket) { - return -1; - } - - /* Check socket is not a connection */ - if (socket->type == HS_CONNECTION) { - return -1; - } - - rc = ops.add_in_route_s(prefix, socket->tun_id); - if (rc < 0) { - return rc; - } - - ip_address_t ip_address; - rc = hicn_ip_pton(prefix, &ip_address); - if (rc < 0) { - return rc; - } - - // ip -6 rule add from b001::/16 prio 0 table 100 - socket->connection.table_id = - socket->tun_id % MAX_TABLES; // this table should be unused - - if (punting_table_id == -1) punting_table_id = socket->connection.table_id; - - rc = ops.add_prio_rule(&ip_address, ip_address.family, 0, - socket->connection.table_id); - if (rc < 0) { - return rc; - } - - strcpy(rules_to_remove[rules_counter].tun_name, "NONE"); - - rules_to_remove[rules_counter].ip_address = ip_address; - rules_to_remove[rules_counter].address_family = ip_address.family; - rules_to_remove[rules_counter].table_id = socket->connection.table_id; - rules_to_remove[rules_counter].priority = 0; - ++rules_counter; - - /* Update socket upon success */ - socket->type = HS_LISTENER; - - return 0; -} - -/** - * - * We can pass all adjacency parameters but identifier - */ -int hicn_bind(hicn_socket_helper_t *hicn, int fd, - const char *remote_ip_address) { - // uint32_t interface_id; - int rc = HICN_SOCKET_ERROR_NONE; - - hicn_socket_t *socket = hicn_socket_find(hicn, fd); - if (!socket) { - rc = HICN_SOCKET_ERROR_BIND_SOCKET_NOT_FOUND; - goto ERR; - } - - /* We allow reuse */ - if (socket->type == HS_CONNECTION) return rc; - - /* Check socket is not a connection */ - if (socket->type != HS_UNSPEC) { - rc = HICN_SOCKET_ERROR_BIND_SOCKET_ALREADY_BOUND; - goto ERR; - } - socket->type = HS_CONNECTION; - - // each connection is associated a table id, let's take it equal to the - // tun ID by default (% MAX_TABLES, assuming TUN IDs do not overlap modulo - // 256...). - // XXX we need to make sure the corresponding table is flushed. - socket->connection.table_id = - socket->tun_id % MAX_TABLES; // interface_id; // ops.get_free_table_id(); - - // XXX use IP address - rc = hicn_set_remote_endpoint(socket, remote_ip_address); - if (rc < 0) { - goto ERR; - } - - // rule - // ip -6 rule from all iif eth0 lookup 200 - // INFO("Adding output rule for %s in table %d", socket->tun_name, - // socket->connection.table_id); - int addr_family = get_addr_family(remote_ip_address); - if (addr_family < 0) { - rc = addr_family; - goto ERR; - } - - rc = ops.add_rule(socket->tun_name, (uint8_t)addr_family, - socket->connection.table_id); - if (rc < 0) { - rc = HICN_SOCKET_ERROR_BIND_RULE; - goto ERR; - } - - strcpy(rules_to_remove[rules_counter].tun_name, socket->tun_name); - rules_to_remove[rules_counter].address_family = addr_family; - rules_to_remove[rules_counter].table_id = socket->connection.table_id; - ++rules_counter; - - // route - // ip -6 route add default via 2002::2 table 28 - // INFO("Adding output route in table %d via gateway %s", - // socket->connection.table_id, - // remote_ip_address); - - // if the address is an IPv6 and start with fe80 we need to specify the device - // in the route - u32 default_interface = ~0; - if (addr_family == AF_INET6 && strncmp(LOCAL_IPV6_PREFIX, remote_ip_address, - strlen(LOCAL_IPV6_PREFIX)) == 0) { - rc = ops.get_output_ifid(remote_ip_address, (uint8_t)addr_family, - &default_interface); - if (rc < 0) { - goto ERR; - } - } - - rc = ops.add_out_route(remote_ip_address, (uint8_t)addr_family, - socket->connection.table_id, default_interface); - if (rc < 0) { - rc = HICN_SOCKET_ERROR_BIND_ROUTE; - goto ERR; - } - - strcpy(routes_to_remove[routes_counter].remote_ip_address, remote_ip_address); - routes_to_remove[routes_counter].table_id = socket->connection.table_id; - routes_to_remove[routes_counter].address_family = (uint8_t)addr_family; - ++routes_counter; - - // add route for data - // ip -6 route add 0:1::/64 dev hicn-if0 table 100 - // this routes are deleted by removing the tun interfaces - - if (punting_table_id == -1) { - // the punting_table_id was not initialized beacause no main-tun was created - // we use as an id (socket->tun_id - 1) % MAX_TABLES, so that we will hava a - // collision only after 255 new interfaces - punting_table_id = (socket->tun_id - 1) % MAX_TABLES; - } - rc = ops.add_in_route_table(&socket->connection.tun_ip_address, - socket->tun_id, punting_table_id); - if (rc < 0) { - rc = HICN_SOCKET_ERROR_BIND_ROUTE; - goto ERR; - } - -ERR: - return rc; -} diff --git a/hicn-light/src/socket/api.h b/hicn-light/src/socket/api.h deleted file mode 100644 index 3a1ae92b4..000000000 --- a/hicn-light/src/socket/api.h +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * @file hicn_face.h - * @brief hICN socket library - * - * This module provides an interface to managing so-called hICN sockets, - * realizing punting of interest and data packets using a TUN device. - */ - -#ifndef HICN_SOCKET_API_H -#define HICN_SOCKET_API_H - -#include <stdint.h> // uint*_t -#include <stdlib.h> - -#include <hicn/hicn.h> -#include "error.h" - -#define BUFSIZE 4096 -#define MAX_CONNECTIONS \ - 255 // We currently limit the number of connections we can establish -#ifndef IF_NAMESIZE -#define IF_NAMESIZE 16 -#endif -/* hICN socket helper */ - -/** hICN configuration options */ -typedef struct { - // uint32_t interval; - - /* Identifier used to name hICN TUN interfaces (should be unique) */ - char *identifier; - // hicn_format_t format; - -} hicn_conf_t; - -/** - * hICN adjacency - */ -typedef struct { - char *local_ip_address; - char *gateway_ip_address; -} hicn_adjacency_t; - -#define EMPTY_HICN_ADJACENCY \ - (hicn_adjacency_t) { 0, 0 } - -/* hICN socket operations */ - -typedef struct { - uint8_t pkbuf[BUFSIZE]; - uint32_t rb_pkbuf_r; - uint32_t rb_pkbuf_w; -} hicn_buffer_t; - -typedef enum { HS_UNSPEC, HS_LISTENER, HS_CONNECTION } hicn_socket_type_t; - -typedef struct hicn_socket_s { - hicn_socket_type_t type; - int fd; - - /* Implementation specific state follows */ - char tun_name[IF_NAMESIZE]; - uint32_t tun_id; - - hicn_buffer_t buffer; - void (*cb)(struct hicn_socket_s *, void *, uint8_t *, size_t); - void *cb_data; - - union { - struct { - ip_address_t tun_ip_address; - uint32_t interface_id; - - /* ID of the corresponding table : avoid default values of 0, 32766 and - * 32767 */ - uint8_t table_id; - } connection; - }; -} hicn_socket_t; - -/** - * hICN global state - */ -typedef struct { - /* Configuration data */ - hicn_conf_t *conf; - - // We need state associate to each FD, to know what type of socket it is and - // its state. - void *socket_root; /**< A tree of socket indexed by their fd */ - -} hicn_socket_helper_t; - -/** - * Create an hICN instance. - * - * This is used to configure the state of an hICN router consistently between - * a listener and the different connections. It also regroups all the state - * related to hICN functionalities. - * - * @return A pointer to an hICN instance. - */ -hicn_socket_helper_t *hicn_create(); - -void hicn_destroy(); - -/** - * Retrieve hICN configuration. - * - * Gets the current configuration of an hICN instance for information purposes, - * or later update it. - * - * TODO - * - We might want to prevent configuration updates while the hICN instance is - * running. Define running... - * - * @param [in] hicn Pointer to hICN instance. - * @return Pointer to an hICN configuration data structure. - * - * @see hicn_set_conf - */ -hicn_conf_t *hicn_get_conf(hicn_socket_helper_t *hicn); - -/** - * Update hICN configuration. - * - * @param [in] hicn Pointer to an hICN instance. - * @param [in] hicn_conf Pointer to an hICN configuration data structure. - * @return 0 in case of success, -1 otherwise. - * - * @see hicn_get_conf - */ -int hicn_set_conf(hicn_socket_helper_t *hicn, hicn_conf_t *hicn_conf); - -/** - * Release hICN state. - * - * @param [in] hicn Pointer to an hICN instance. - */ -void hicn_free(hicn_socket_helper_t *hicn); - -// FIXME doc -int hicn_get_local_address(const ip_address_t *remote_address, - ip_address_t *local_address); - -/* hICN socket */ - -/** - * Create an hICN socket. - * - * An hICN socket abstracts the underlying implementation and allows hICN - * packets to be sent and received independently of the underlying - * implementation. - * - * It is possible to further specialize the socket in a listener socket, and a - * connection socket. - * - * @param [in] hicn Pointer to an hICN instance. - * @param [in] identifier Unique identifier for this socket, used to named the - * TUN device - * @param [in] local_ip_address IP address used locally by the socket (or NULL - * for letting the library decide automatically). - * @return File descriptor (>0) in case of success, -1 otherwise. - * - * @see hicn_listen - * @see hicn_bind - */ -int hicn_socket(hicn_socket_helper_t *hicn, const char *identifier, - const char *local_ip_address); - -/** - * Packet punting. - * - * Note that we cannot listen on a socket that is already bound. - * - * @param [in] hicn Pointer to an hICN instance. - * @param [in] fd File descriptor identifying the hICN socket. - * @param [in] prefix Prefix (IPv4 or IPv6) to be bound to hICN in - * RFC-compliant presentation format. - * @return 0 in case of success, -1 otherwise. - * - * @see hicn_socket - */ -int hicn_listen(hicn_socket_helper_t *hicn, int fd, const char *prefix); - -/** - * Packet forwarding - * @param [in] hicn Pointer to an hICN instance. - * @param [in] fd File descriptor identifying the hICN socket. - * @param [in] prefix Prefix (IPv4 or IPv6) to be bound to hICN in - * RFC-compliant presentation format. - * @return 0 in case of success, -1 otherwise. - * - * XXX adjacency does not perform any copy heresofar - * - * @see hicn_socket - */ -int hicn_bind(hicn_socket_helper_t *hicn, int fd, - const char *remote_ip_address); - -#endif /* HICN_SOCKET_API_H */ diff --git a/hicn-light/src/socket/error.c b/hicn-light/src/socket/error.c deleted file mode 100644 index 3dafec8cf..000000000 --- a/hicn-light/src/socket/error.c +++ /dev/null @@ -1,7 +0,0 @@ -#include "error.h" - -const char* HICN_SOCKET_ERROR_STRING[] = { -#define _(a, b, c) [b] = c, - foreach_hicn_socket_error -#undef _ -}; diff --git a/hicn-light/src/socket/error.h b/hicn-light/src/socket/error.h deleted file mode 100644 index 8195efd84..000000000 --- a/hicn-light/src/socket/error.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef HICN_SOCKET_ERROR_H -#define HICN_SOCKET_ERROR_H - -// FIXME remove unused errors -#define foreach_hicn_socket_error \ - _(NONE, 0, "OK") \ - _(UNSPEC, 1, "unspecified error") \ - _(NOT_HICN, 2, "not a hICN paclet") \ - _(UNKNOWN_ADDRESS, 10, "unknown address") \ - _(INVALID_PARAMETER, 20, "invalid parameter") \ - _(INVALID_IP_ADDRESS, 21, "invalid IP address") \ - _(CORRUPTED_PACKET, 22, "corrupted packet") \ - _(UNEXPECTED, 98, "unexpected error") \ - _(NOT_IMPLEMENTED, 99, "not implemented") \ - _(SOCKET_LOCAL_NULL_ADDRESS, 101, "empty local address") \ - _(SOCKET_LOCAL_REPR, 102, "cannot represent local address") \ - _(SOCKET_LOCAL_HEURISTIC, 103, "error finding local address") \ - _(SOCKET_LOCAL_SET_TUN_IP, 104, "cannot set local IP to TUN") \ - _(BIND_SOCKET_NOT_FOUND, 301, "bind: socket not found") \ - _(BIND_SOCKET_ALREADY_BOUND, 302, "bind: socket already bound") \ - _(BIND_REMOTE_INTERFACE, 303, "bind: no interface towards gateway") \ - _(BIND_REMOTE_NETMASK, 304, "bind: no local IP with netmask < 128") \ - _(BIND_REMOTE_REPR, 305, "bind: error representing local IP") \ - _(BIND_REMOTE_LOCAL_NULL_ADDR, 306, "bind: could not set local endpoint") \ - _(BIND_REMOTE_LOCAL_REPR, 307, "bind: error representing remote IP") \ - _(BIND_REMOTE_LOCAL_HEURISTIC, 308, "bind: could not apply heuristic") \ - _(BIND_REMOTE_LOCAL_SET_TUN_IP, 309, "bind: error setting local IP to TUN") \ - _(BIND_NDP, 310, "bind: could not enable NDP proxy") \ - _(BIND_NEIGH_PROXY, 311, "bind: could not neighbour") \ - _(BIND_REPR, 312, "bind: error represeting IP") \ - _(BIND_LO, 313, "bind: could not remove local route") \ - _(BIND_RULE, 314, "bind: could not add rule") \ - _(BIND_ROUTE, 315, "bind: could not add output route") - -typedef enum { -#define _(a, b, c) HICN_SOCKET_ERROR_##a = (-b), - foreach_hicn_socket_error -#undef _ - HICN_SOCKET_N_ERROR, -} hicn_socket_error_t; - -extern const char *HICN_SOCKET_ERROR_STRING[]; - -#define hicn_socket_strerror(errno) (char *)(HICN_SOCKET_ERROR_STRING[-errno]) - -#endif /* HICN_SOCKET_ERROR_H */ diff --git a/hicn-light/src/socket/ops.h b/hicn-light/src/socket/ops.h deleted file mode 100644 index 249caf87a..000000000 --- a/hicn-light/src/socket/ops.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef HICN_SOCKET_OPS_H -#define HICN_SOCKET_OPS_H - -#include <hicn/hicn.h> -#include <stdint.h> - -typedef struct { - char *arch; - int (*tun_create)(char *name); - int (*get_tun_name)(const char *prefix, const char *identifier, - char *tun_name); - int (*enable_v6_forwarding)(char *interface_name); - int (*enable_v4_forwarding)(); - int (*enable_ndp_proxy)(); - - uint32_t (*get_ifid)(const char *ifname); - int (*get_output_ifid)(const char *ip_address, uint8_t address_family, - uint32_t *interface_id); - int (*get_ip_addr)(uint32_t interface_id, uint8_t address_family, - ip_address_t *ip_address); - int (*set_ip_addr)(uint32_t interface_id, ip_address_t *ip_address); - int (*up_if)(uint32_t interface_id); - int (*add_in_route_table)(const ip_address_t *prefix, - const uint32_t interface_id, - const uint8_t table_id); - int (*add_in_route_table_s)(const char *prefix, const uint32_t interface_id, - const uint8_t table_id); - int (*add_in_route_s)(const char *prefix, const uint32_t interface_id); - int (*add_out_route)(const char *gateway, const uint8_t address_family, - const uint8_t table_id, int default_route); - int (*del_out_route)(const char *gateway, const uint8_t address_family, - const uint8_t table_id); - int (*del_lo_route)(const ip_address_t *ip_address); - int (*add_rule)(const char *interface_name, const uint8_t address_family, - const uint8_t table_id); - int (*del_rule)(const char *interface_name, const uint8_t address_family, - const uint8_t table_id); - int (*add_neigh_proxy)(const ip_address_t *ip_address, - const uint32_t interface_id); - int (*add_prio_rule)(const ip_address_t *ip_address, - const uint8_t address_family, const uint32_t priority, - const uint8_t table_id); - int (*add_lo_prio_rule)(const ip_address_t *ip_address, - const uint8_t address_family, - const uint32_t priority); - int (*del_prio_rule)(const ip_address_t *ip_address, - const uint8_t address_family, const uint32_t priority, - const uint8_t table_id); - int (*del_lo_prio_rule)(const ip_address_t *ip_address, - const uint8_t address_family, - const uint32_t priority); -} hicn_socket_ops_t; - -#endif /* HICN_SOCKET_OPS_H */ diff --git a/hicn-light/src/socket/ops_linux.c b/hicn-light/src/socket/ops_linux.c deleted file mode 100644 index d085f0d3d..000000000 --- a/hicn-light/src/socket/ops_linux.c +++ /dev/null @@ -1,1723 +0,0 @@ -#include <sys/ioctl.h> // ioctl -#include <sys/socket.h> // needed by linux/if.h -//#include <linux/if.h> -#include <errno.h> -#include <fcntl.h> // '' -#include <linux/if_tun.h> -#include <linux/limits.h> // PATH_MAX -#include <stdio.h> // fprintf -#include <string.h> // memset -#include <sys/stat.h> // open -#include <sys/uio.h> // writev -#include <unistd.h> // close - -#include "error.h" -#include "ops.h" - -#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a))) - -/****************************************************************************** - * netlink.h - ******************************************************************************/ - -#ifndef HICN_NETLINK_H -#define HICN_NETLINK_H - -#include <stdint.h> -#include <stdlib.h> - -// DEPRECATED|/* Socket */ -// DEPRECATED|int _nl_get_socket(); -// DEPRECATED|int _nl_send(int s, uint8_t * buffer, size_t len); -// DEPRECATED|size_t _nl_receive(uint8_t * buffer, size_t len); -// DEPRECATED| -// DEPRECATED|/* Netlink packet format */ -// DEPRECATED|int _nl_header(int request, uint8_t * buffer, size_t len, uint32_t -// flags); DEPRECATED|int _nl_payload_rule(uint8_t table_id, uint8_t * buffer, -// size_t len); DEPRECATED|int _nl_payload_link(uint32_t ifindex, uint8_t * -// buffer, size_t len); DEPRECATED|int _nl_payload_route(uint8_t table_id, -// uint8_t dst_len, uint8_t * buffer, size_t len); DEPRECATED| DEPRECATED|int -// _nl_parse(uint8_t * buffer, size_t len); DEPRECATED|int _nl_parse_ret(uint8_t -// * buffer, size_t len); DEPRECATED|int _nl_parse_link_ifid(uint8_t * buffer, -// size_t len, uint32_t * interface_id); DEPRECATED|int -// _nl_parse_link_ip_addr(uint8_t * buffer, size_t len, struct in6_addr * addr); - -/* Public interface */ - -/** - * Get the interface ID of an interface by its name - * - * @return 32-bit interface identifier in case of success, or 0. - * - * @see if_nametoindex - * - */ -uint32_t _nl_get_ifid(const char *ifname); - -/** - * Retrieve the output interface corresponding to the specified IP address. - * - * @param [in] addr IP(v6) address in presentation form. - * @param [out] Identifier of the corresponding output interface. - * @return int 0 in case of success, -1 otherwise - */ -int _nl_get_output_ifid(const char *ip_address, uint8_t address_family, - uint32_t *interface_id); - -/** - * Retrieve the first IP address of an interface (identified by its id) which - * has a netmask < 128. - * - * @param [in] s File descriptor of the netlink socket (deprecated). - * @param [in] interface_id Identifier of the interface for which to retrieve - * the IP address. - * @param [out] addr IP(v6) address in binary form. - * @return int 0 in case of success, -1 otherwise - * - * @see getifaddrs - */ -int _nl_get_ip_addr(uint32_t interface_id, uint8_t address_family, - ip_address_t *ip_address); - -int _nl_set_ip_addr(uint32_t interface_id, ip_address_t *ip_address); - -int _nl_up_if(uint32_t interface_id); - -int _nl_add_in_route_table(const ip_address_t *prefix, - const uint32_t interface_id, const uint8_t table_id); -int _nl_add_in_route_table_s(const char *prefix, const uint32_t interface_id, - const uint8_t table_id); -int _nl_add_in_route_s(const char *prefix, const uint32_t interface_id); - -int _nl_add_out_route(const char *gateway, const uint8_t address_family, - const uint8_t table_idi, int default_route); -int _nl_del_out_route(const char *gateway, const uint8_t address_family, - const uint8_t table_id); - -int _nl_del_lo_route(const ip_address_t *ip_address); - -int _nl_add_rule(const char *interface_name, const uint8_t address_family, - const uint8_t table_id); -int _nl_del_rule(const char *interface_name, const uint8_t address_family, - const uint8_t table_id); - -int _nl_add_neigh_proxy(const ip_address_t *ip_address, - const uint32_t interface_id); - -int _nl_add_prio_rule(const ip_address_t *ip_address, - const uint8_t address_family, const uint32_t priority, - const uint8_t table_id); -int _nl_add_lo_prio_rule(const ip_address_t *ip_address, - const uint8_t address_family, const uint32_t priority); -int _nl_del_prio_rule(const ip_address_t *ip_address, - const uint8_t address_family, const uint32_t priority, - const uint8_t table_id); -int _nl_del_lo_prio_rule(const ip_address_t *ip_address, - const uint8_t address_family, const uint32_t priority); - -#endif /* HICN_NETLINK_H */ - -/****************************************************************************** - * netlink.c - ******************************************************************************/ - -/* - * This module offers an interface to the Netlink API appropriate for - * implementing punting as required by hICN (1). - * - * More specifically, it consists of the following functionalities: - * - LINK - . map interface name to ID - . set and interface up - * - ADDR - . get and set ip addresses on a given interface ID - * - ROUTE - . get output interface id towards IP (ip route get IP > interface_id) - . add input route (ip route add PREFIX dev INTERFACE) for punting - interests . add output route (ip route add default GATEWAY table TABLE) for - routing interests (2, 3) . delete local route towards IP (ip route del IP table - local) for ??? - /!\ could this be avoided by removing the local attribute in the - netlink call ? - * - RULE - * . add output rule (ip rule add iif interface table TABLE) for routing - interests (2, 3) - * - ND PROXY - * . enable NDP proxy functionality for IP on interface ID (ip -6 neigh add - proxy IP dev INTERFACE) - * for allowing the TUN to be reachable on the reverse data path - * - * Implementation notes: - * (1) We have not been using the libnl library because it requires - * manipulating too many function and data structures for a simple purpose. - * Currently, many parts of the code are somehow repetitive, but this might - * be improved by a proper API in a future release. - * (2) allows load balancing over different interfaces = multihoming. Please - * note that it is not possible to have load balancing over two faces using - * the same output interface as we are using the underlying IP network ! - * This might be mitigated with the use of SR however. - * (3) The implementation of punting heavily uses the policy routing - * functionalities, as we need to hook through a TUN into user space a - * whole prefix used as a destination (for interests) or source (for data - * packets). We thus combine the use of rules to assign routing table IDs, - * and routes inside those tables. As there is no easy way to allocate - * which routing tables we use, we made the choice to index them by the ID - * of the interface, assuming there is no external conflict. This might be - * improved in the future. - * - * This hICN implementation uses TUNs in two different ways: - * - a main TUN interface, which receives all punted interests, - * demultiplex them before assigning them an input face (eventually - * dynamically creating it); - * - a set of output TUN interfaces, aka faces, used for routing of - * interests, and for receiving the corresponding data packets on the way - * back. Punting of data packets if based of their destination IP, which - * is the IP of the physical output interface used for the interest, which - * is unique (cf (2)). - * - * The corresponding routing tables IDs are : - * MAIN_TUN_ID -> used for punting of data packets - * OUTPUT_TUN_ID_i -> used for routing of interests towards next hop - * (bypassing local IP routing table) - * - * Note that punting of interests is done just through a route, and routing - * of data packets is done just through the regular IP routing table on the - * note after the address translation done in the forwarder. - * - * - Forging netlink packets - * - * A previous implementation used function calls with pointers to populate - * the various header parts in a buffer in order to build a netlink packet. - * A newer implementation uses nested structs and iovecs to build the whole - * packet in a single write call. This should allow a simpler evolution - * towards a cleaner API. - */ - -#include <arpa/inet.h> // inet_pton -#include <errno.h> // errno -#include <linux/fib_rules.h> // fib_rule_hdr, FRA_* -#include <linux/netlink.h> -#include <linux/rtnetlink.h> -#include <net/if.h> // IFF_UP -#include <netinet/in.h> // in6addr -#include <stdio.h> // perror -#include <string.h> -#include <sys/socket.h> // '' -#include <sys/types.h> // socket -#include <unistd.h> // read - -#include <sys/socket.h> // '' -#include <sys/types.h> // send, recv - -//#include "../../hicn.h" -//#include "../../hicn_util.h" // ARRAY_SIZE, hicn_packet_dump_iov - -#define BUFSIZE 4096 -#define FLAGS_CREATE NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK -// ?? -#define FLAGS_CREATE_MATCH \ - NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK | NLM_F_MATCH - -// XXX putting ACK poses a prolem for the value received by get_if_id. -#define FLAGS_GET NLM_F_REQUEST -#define FLAGS_GET_ROOT (NLM_F_REQUEST | NLM_F_ROOT) - -#define FLAGS_LIST NLM_F_REQUEST | NLM_F_DUMP - -#define IF_NAMESIZE 16 -#define FR_ACT_TO_TBL 1 -#define NLMSG_BOTTOM(nlmsg) \ - ((struct rtattr *)(((void *)(nlmsg)) + NLMSG_ALIGN((nlmsg)->nlmsg_len))) - -int seq = 1; - -static inline size_t iov_length(const struct iovec *iov, - unsigned long nr_segs) { - unsigned long seg; - size_t ret = 0; - - for (seg = 0; seg < nr_segs; seg++) ret += iov[seg].iov_len; - return ret; -} - -typedef struct { - struct nlmsghdr hdr; - struct nlmsgerr payload; -} nl_err_hdr_t; - -/* Low level : nl header */ - -int _nl_get_socket() { return socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); } - -int _nl_header(int request, uint8_t *buffer, size_t len, uint32_t flags) { - struct nlmsghdr *nl = (struct nlmsghdr *)buffer; - - nl->nlmsg_len = 0; // NLMSG_LENGTH(sizeof(struct ifinfomsg)); - nl->nlmsg_type = request; - nl->nlmsg_flags = flags; - nl->nlmsg_seq = seq++; // - nl->nlmsg_pid = 0; // getpid(); - - return 0; -} - -/* Low level : nl protocols */ - -/* Low level : attributes */ - -int addAttr(struct nlmsghdr *nl, int maxlen, int type, void *data, - int attr_len) { - struct rtattr *rta; - int len = RTA_LENGTH(attr_len); - - if (NLMSG_ALIGN(nl->nlmsg_len) + len > maxlen) { - exit(EXIT_FAILURE); - } - - rta = (struct rtattr *)((char *)nl + NLMSG_ALIGN(nl->nlmsg_len)); - rta->rta_type = type; - rta->rta_len = len; - memcpy(RTA_DATA(rta), data, attr_len); - nl->nlmsg_len = NLMSG_ALIGN(nl->nlmsg_len) + len; - return 0; -} - -int _nl_payload_rule(uint8_t table_id, uint8_t address_family, uint8_t *buffer, - size_t len) { - struct nlmsghdr *nl = (struct nlmsghdr *)buffer; - struct fib_rule_hdr *frh = (struct fib_rule_hdr *)(NLMSG_DATA(buffer)); - - memset(frh, 0, sizeof(struct fib_rule_hdr)); - frh->family = address_family; - frh->table = table_id; - frh->action = FR_ACT_TO_TBL, - frh->flags = NLM_F_REPLACE; // 0 - frh->tos = 0; - - nl->nlmsg_len += NLMSG_LENGTH(sizeof(struct fib_rule_hdr)); - - return 0; -} - -int _nl_payload_link(uint32_t ifindex, uint8_t *buffer, size_t len) { - struct nlmsghdr *nl = (struct nlmsghdr *)buffer; - struct ifinfomsg *ifi = (struct ifinfomsg *)(NLMSG_DATA(buffer)); - - memset(ifi, 0, sizeof(struct ifinfomsg)); - ifi->ifi_family = AF_UNSPEC; - // ifi->ifi_type = 0; - ifi->ifi_index = - ifindex; // new interface, could be specified since linux 3.7 - ifi->ifi_flags = 0; - // ifi->ifi_change = 0xffffffff; - - nl->nlmsg_len += NLMSG_LENGTH(sizeof(struct ifinfomsg)); - - return 0; -} - -int _nl_payload_addr(uint32_t ifindex, uint8_t *buffer, size_t len) { - struct nlmsghdr *nl = (struct nlmsghdr *)buffer; - struct ifaddrmsg *addr = (struct ifaddrmsg *)(NLMSG_DATA(buffer)); - - memset(addr, 0, sizeof(struct ifaddrmsg)); - addr->ifa_family = AF_UNSPEC; // INET6; - /* - addr->ifa_prefixlen = 128; - addr->ifa_flags = 0; - addr->ifa_scope = RT_SCOPE_LINK; //IFA_ADDRESS; - addr->ifa_index = ifindex; - */ - - nl->nlmsg_len += NLMSG_LENGTH(sizeof(struct ifaddrmsg)) - 4; - - return 0; -} - -int _nl_payload_route(uint8_t table_id, uint8_t addr_family, uint8_t dst_len, - uint8_t *buffer, size_t len) { - struct nlmsghdr *nl = (struct nlmsghdr *)buffer; - struct rtmsg *raddr = (struct rtmsg *)(NLMSG_DATA(buffer)); - - raddr->rtm_family = addr_family; - raddr->rtm_dst_len = dst_len; - raddr->rtm_src_len = 0; - raddr->rtm_tos = 0; - - raddr->rtm_table = table_id; - raddr->rtm_protocol = RTPROT_BOOT; - raddr->rtm_scope = RT_SCOPE_UNIVERSE; - raddr->rtm_type = RTN_UNICAST; - - raddr->rtm_flags = 0; - - nl->nlmsg_len += NLMSG_LENGTH(sizeof(struct rtmsg)); - - return 0; -} - -uint32_t _nl_get_ifid(const char *interface_name) { - char buffer[BUFSIZE]; - struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; - size_t n; - int fd; - size_t len = interface_name ? strlen(interface_name) + 1 : 0; - uint8_t padding[RTA_ALIGNTO] = {0, 0, 0, 0}; - - if (len == 0) { - goto ERR_IF; - } - - struct { - struct nlmsghdr hdr; - struct ifinfomsg payload; - } msg = {//.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)), - .hdr.nlmsg_type = RTM_GETLINK, - .hdr.nlmsg_flags = FLAGS_GET, - .payload.ifi_family = AF_UNSPEC, - .payload.ifi_index = 0}; - struct rtattr a_ifname = {RTA_LENGTH(strlen(interface_name) + 1), - IFLA_IFNAME}; - - struct iovec iov[] = {{&msg, sizeof(msg)}, - {&a_ifname, sizeof(a_ifname)}, - {(char *)interface_name, len}, - {padding, RTA_SPACE(len) - RTA_LENGTH(len)}}; - msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); - - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR_SOCKET; - } - n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); - if (n == -1) { - goto ERR_SEND; - } - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR_RECV; - } - - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0) { - errno = -err->error; - goto ERR_NL; - } - return 0; /* Unexpected */ - } - - for (; NLMSG_OK(hdr, n); hdr = NLMSG_NEXT(hdr, n)) { - struct ifinfomsg *payload = (struct ifinfomsg *)NLMSG_DATA(hdr); - return payload->ifi_index; - } - return 0; - -ERR_NL: -ERR_RECV: -ERR_SEND: -ERR_SOCKET: -ERR_IF: - return 0; -} - -int _nl_get_output_ifid(const char *ip_address, uint8_t family_address, - uint32_t *interface_id) { - int rc; - - char buffer[BUFSIZE]; - struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; - size_t n; - int fd; - - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR; - } - - if (family_address == AF_INET6) { - struct in6_addr addr; // V6SPECIFIC - - struct { - struct nlmsghdr hdr; - struct rtmsg payload; - } msg = { - .hdr.nlmsg_type = RTM_GETROUTE, - .hdr.nlmsg_flags = NLM_F_REQUEST, - .hdr.nlmsg_seq = seq++, - .payload.rtm_family = AF_INET6, - .payload.rtm_dst_len = IPV6_ADDR_LEN_BITS, - .payload.rtm_src_len = 0, - .payload.rtm_tos = 0, - .payload.rtm_table = RT_TABLE_UNSPEC, - .payload.rtm_protocol = RTPROT_UNSPEC, - .payload.rtm_scope = RT_SCOPE_UNIVERSE, - .payload.rtm_type = RTN_UNSPEC, - .payload.rtm_flags = 0 // RTM_F_NOTIFY in 'ip route get' - }; - - /* Convert the IP address to binary form */ - rc = inet_pton(AF_INET6, ip_address, &addr); - if (rc <= 0) { - goto ERR; - } - - /* Set attribute = length/type/value */ - struct rtattr a_dst = {RTA_LENGTH(16), RTA_DST}; - struct iovec iov[] = { - {&msg, sizeof(msg)}, - {&a_dst, sizeof(a_dst)}, // attribute - {&addr, sizeof(addr)} // value - }; - msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); - - n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); - if (n == -1) { - goto ERR; - } - } else if (family_address == AF_INET) { - struct in_addr addr; - - struct { - struct nlmsghdr hdr; - struct rtmsg payload; - } msg = { - .hdr.nlmsg_type = RTM_GETROUTE, - .hdr.nlmsg_flags = NLM_F_REQUEST, - .hdr.nlmsg_seq = seq++, - .payload.rtm_family = AF_INET, - .payload.rtm_dst_len = IPV4_ADDR_LEN_BITS, - .payload.rtm_src_len = 0, - .payload.rtm_tos = 0, - .payload.rtm_table = RT_TABLE_UNSPEC, - .payload.rtm_protocol = RTPROT_UNSPEC, - .payload.rtm_scope = RT_SCOPE_UNIVERSE, - .payload.rtm_type = RTN_UNSPEC, - .payload.rtm_flags = 0 // RTM_F_NOTIFY in 'ip route get' - }; - - /* Convert the IP address to binary form */ - rc = inet_pton(AF_INET, ip_address, &addr); - if (rc <= 0) { - goto ERR; - } - - /* Set attribute = length/type/value */ - struct rtattr a_dst = {RTA_LENGTH(4), RTA_DST}; - struct iovec iov[] = { - {&msg, sizeof(msg)}, - {&a_dst, sizeof(a_dst)}, // attribute - {&addr, sizeof(addr)} // value - }; - msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); - - n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); - if (n == -1) { - goto ERR; - } - } else { - goto ERR; - } - - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR; - } - - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0) { - errno = -err->error; - goto ERR; - } - return HICN_SOCKET_ERROR_UNEXPECTED; /* Unexpected */ - } - - for (; NLMSG_OK(hdr, n); hdr = NLMSG_NEXT(hdr, n)) { - struct rtmsg *rtm = (struct rtmsg *)NLMSG_DATA(hdr); - int attrlen = RTM_PAYLOAD(hdr); - struct rtattr *rta; - for (rta = RTM_RTA(rtm); RTA_OK(rta, attrlen); - rta = RTA_NEXT(rta, attrlen)) { - if (rta->rta_type == RTA_OIF) { - *interface_id = *(uint32_t *)RTA_DATA(rta); - return HICN_SOCKET_ERROR_NONE; - } - } - } - - return HICN_SOCKET_ERROR_NONE; - -ERR: - return HICN_SOCKET_ERROR_UNSPEC; -} - -int _nl_get_ip_addr(uint32_t interface_id, uint8_t address_family, - ip_address_t *ip_address) { - char buffer[BUFSIZE]; - struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; - size_t n; - int fd; - - struct { - struct nlmsghdr hdr; - struct ifaddrmsg payload; - } msg = {.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)), - .hdr.nlmsg_type = RTM_GETADDR, - .hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ROOT, // | NLM_F_MATCH, - .payload.ifa_family = address_family, - .payload.ifa_index = 0}; - - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR_SOCKET; - } - - n = send(fd, &msg, sizeof(msg), 0); - if (n == -1) { - goto ERR_SEND; - } - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR_RECV; - } - - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0) { - errno = -err->error; - goto ERR_NL; - } - return -99; /* Unexpected */ - } - - for (; NLMSG_OK(hdr, n); hdr = NLMSG_NEXT(hdr, n)) { - struct ifaddrmsg *payload = (struct ifaddrmsg *)NLMSG_DATA(hdr); - - if (address_family == AF_INET6) { - if ((payload->ifa_index == interface_id) && - (payload->ifa_prefixlen < IPV6_ADDR_LEN * 8)) { - printf("got ip address\n"); - memcpy(ip_address->buffer, RTA_DATA(payload + 1), IPV6_ADDR_LEN); - ip_address->family = AF_INET6; - ip_address->prefix_len = IPV6_ADDR_LEN_BITS; - printf("returning %d\n", HICN_SOCKET_ERROR_NONE); - return HICN_SOCKET_ERROR_NONE; - } - } else if (address_family == AF_INET) { - if ((payload->ifa_index == interface_id) && - (payload->ifa_prefixlen < IPV4_ADDR_LEN * 8)) { - printf("got ip address\n"); - memcpy(ip_address->buffer, RTA_DATA(payload + 1), IPV4_ADDR_LEN); - ip_address->family = AF_INET; - ip_address->prefix_len = IPV4_ADDR_LEN_BITS; - printf("returning %d\n", HICN_SOCKET_ERROR_NONE); - return HICN_SOCKET_ERROR_NONE; - } - } else { - return -99; - } - } - -ERR_NL: -ERR_RECV: -ERR_SEND: -ERR_SOCKET: - printf("error getting ip address\n"); - return HICN_SOCKET_ERROR_UNSPEC; -} - -int _nl_set_ip_addr(uint32_t interface_id, ip_address_t *ip_address) { - char buffer[BUFSIZE]; - struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; - size_t n; - int fd; - - struct { - struct nlmsghdr hdr; - struct ifaddrmsg payload; - } msg = { - .hdr.nlmsg_type = RTM_NEWADDR, - .hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | NLM_F_MATCH | NLM_F_ATOMIC, - .hdr.nlmsg_seq = seq++, - .payload.ifa_family = ip_address->family, - .payload.ifa_prefixlen = ip_address->prefix_len, - .payload.ifa_flags = 0, - .payload.ifa_scope = RT_SCOPE_UNIVERSE, - .payload.ifa_index = interface_id}; - - /* Set attributes = length/type/value */ - struct rtattr ifa_address = {RTA_LENGTH(ip_address_len(ip_address)), - IFA_ADDRESS}; - // XXX maybe the reason why we have a local route ? - // struct rtattr ifa_local = { RTA_LENGTH(ip_address_len(ip_address)), - // IFA_LOCAL }; - struct iovec iov[] = { - {&msg, sizeof(msg)}, - {&ifa_address, sizeof(ifa_address)}, - {(void *)&ip_address->buffer, sizeof(ip_address->buffer)}, - // { &ifa_local, sizeof(ifa_local) }, - // { (void*)&ip_address->buffer, sizeof(ip_address->buffer) }, - }; - msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); - - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR_SOCKET; - } - - // hicn_packet_dump_iov(iov, ARRAY_SIZE(iov)); - - n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); - if (n == -1) { - goto ERR_SEND; - } - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR_RECV; - } - - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0) { - errno = -err->error; - goto ERR_NL; - } - } - - return 0; - -ERR_NL: -ERR_RECV: -ERR_SEND: -ERR_SOCKET: - return -1; -} - -int _nl_up_if(uint32_t interface_id) { - char buffer[BUFSIZE]; - struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; - size_t n; - int fd; - - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR_SOCKET; - } - - struct { - struct nlmsghdr hdr; - struct ifinfomsg payload; - } msg = { - .hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg)), - .hdr.nlmsg_type = RTM_NEWLINK, - .hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK, - .payload.ifi_family = AF_UNSPEC, - .payload.ifi_index = interface_id, - .payload.ifi_flags = IFF_UP, - .payload.ifi_change = IFF_UP // 0xffffffff - }; - - n = send(fd, &msg, sizeof(msg), 0); - if (n == -1) { - goto ERR_SEND; - } - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR_RECV; - } - - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0) { - errno = -err->error; - goto ERR_NL; - } - return 0; - } - -ERR_NL: -ERR_RECV: -ERR_SEND: -ERR_SOCKET: - return -1; -} - -struct route_info { - char *dst_addr; - char *src_addr; - char *gateway; - char ifName[IF_NAMESIZE]; -}; - -/* - * ip -6 route add PREFIX dev INTERFACE_NAME - */ -#if 0 -int _nl_add_in_route(const char * prefix, const uint32_t interface_id) -{ - char buffer[BUFSIZE]; - struct nlmsghdr * hdr = (struct nlmsghdr *)buffer; - size_t n; - int fd; - - int pton_fd; - unsigned char dst[sizeof(struct in6_addr)]; - char * p; - char * eptr; - char addr[strlen(prefix)]; - uint32_t dst_len; - - strncpy(addr, prefix, strlen(prefix)); - - p = strchr(addr, '/'); - if (!p) { - dst_len = IPV6_ADDR_LEN; - } else { - dst_len = strtoul(p + 1, &eptr, 10); - if (dst_len > IPV6_ADDR_LEN * 8) { - printf("E: Netmask > IPV6_ADDR_LEN"); - return -1; - } - *p = 0; - } - - pton_fd = inet_pton(AF_INET6, addr, dst); - if (pton_fd <= 0) { - if (pton_fd == 0) - ;//ERROR("Not in presentation format"); - else - perror("inet_pton"); - return -2; - } - - _nl_header(RTM_NEWROUTE, (uint8_t *)buffer, BUFSIZE, FLAGS_CREATE_MATCH); - _nl_payload_route(RT_TABLE_MAIN, dst_len, (uint8_t *)buffer, BUFSIZE); - - addAttr(hdr, BUFSIZE, RTA_DST, dst, IPV6_ADDR_LEN); - addAttr(hdr, BUFSIZE, RTA_OIF, (void*)&interface_id, sizeof(uint32_t)); - - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR_SOCKET; - } - - n = send(fd, buffer, hdr->nlmsg_len, 0); - if (n == -1) { - goto ERR_SEND; - } - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR_RECV; - } - - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr * err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0) { - errno = -err->error; - goto ERR_NL; - } - return 0; - } - -ERR_NL: -ERR_RECV: -ERR_SEND: -ERR_SOCKET: - return -1; - -} -#endif - -/* - * ip -6 route add local default via GATEWAY_IP table TABLE_ID - */ -int _nl_add_out_route(const char *gateway, uint8_t address_family, - const uint8_t table_id, int default_route) { - char buffer[BUFSIZE]; - struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; - size_t n; - int fd; - - int pton_fd; - - if (address_family == AF_INET) { - struct in_addr gw; - - pton_fd = inet_pton(AF_INET, gateway, (struct in_addr *)&gw); - if (pton_fd < 0) { - return -1; - } - - _nl_header(RTM_NEWROUTE, (uint8_t *)buffer, BUFSIZE, - NLM_F_REQUEST | NLM_F_ACK | NLM_F_MATCH | NLM_F_ATOMIC); - _nl_payload_route(table_id, address_family, 0, (uint8_t *)buffer, BUFSIZE); - - /* gw */ - addAttr(hdr, BUFSIZE, RTA_GATEWAY, &gw, sizeof(gw)); - - } else if (address_family == AF_INET6) { - struct in6_addr gw; - - pton_fd = inet_pton(AF_INET6, gateway, (struct in6_addr *)&gw); - if (pton_fd < 0) { - return -1; - } - - _nl_header(RTM_NEWROUTE, (uint8_t *)buffer, BUFSIZE, - NLM_F_REQUEST | NLM_F_ACK | NLM_F_MATCH | NLM_F_ATOMIC); - _nl_payload_route(table_id, address_family, 0, (uint8_t *)buffer, BUFSIZE); - - /* gw */ - addAttr(hdr, BUFSIZE, RTA_GATEWAY, &gw, sizeof(gw)); - if (default_route != -1) { - addAttr(hdr, BUFSIZE, RTA_OIF, &default_route, sizeof(default_route)); - } - - } else { - return -1; - } - - // For more than 255 tables - // addAttr(msg, BUFSIZE, RTA_TABLE, &table_id, sizeof(uint32_t)); - - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR_SOCKET; - } - - n = send(fd, buffer, hdr->nlmsg_len, 0); - if (n == -1) { - goto ERR_SEND; - } - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR_RECV; - } - - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0) { - errno = -err->error; - goto ERR_NL; - } - return 0; - } - -ERR_NL: -ERR_RECV: -ERR_SEND: -ERR_SOCKET: - return -1; -} - -/* - * ip -6 route del local default via GATEWAY_IP table TABLE_ID - */ -int _nl_del_out_route(const char *gateway, const uint8_t address_family, - const uint8_t table_id) { - char buffer[BUFSIZE]; - struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; - size_t n; - int fd; - - int pton_fd; - - if (address_family == AF_INET) { - struct in_addr gw; - - pton_fd = inet_pton(AF_INET, gateway, (struct in_addr *)&gw); - if (pton_fd < 0) { - return -1; - } - - _nl_header(RTM_DELROUTE, (uint8_t *)buffer, BUFSIZE, - NLM_F_REQUEST | NLM_F_ACK | NLM_F_MATCH | NLM_F_ATOMIC); - _nl_payload_route(table_id, address_family, 0, (uint8_t *)buffer, BUFSIZE); - - /* gw */ - addAttr(hdr, BUFSIZE, RTA_GATEWAY, &gw, sizeof(gw)); - - } else if (address_family == AF_INET6) { - struct in6_addr gw; - - pton_fd = inet_pton(AF_INET6, gateway, (struct in6_addr *)&gw); - if (pton_fd < 0) { - return -1; - } - - _nl_header(RTM_DELROUTE, (uint8_t *)buffer, BUFSIZE, - NLM_F_REQUEST | NLM_F_ACK | NLM_F_MATCH | NLM_F_ATOMIC); - _nl_payload_route(table_id, address_family, 0, (uint8_t *)buffer, BUFSIZE); - - /* gw */ - addAttr(hdr, BUFSIZE, RTA_GATEWAY, &gw, sizeof(gw)); - - } else { - return -1; - } - - // For more than 255 tables - // addAttr(msg, BUFSIZE, RTA_TABLE, &table_id, sizeof(uint32_t)); - - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR_SOCKET; - } - - n = send(fd, buffer, hdr->nlmsg_len, 0); - if (n == -1) { - goto ERR_SEND; - } - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR_RECV; - } - - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0) { - errno = -err->error; - goto ERR_NL; - } - return 0; - } - -ERR_NL: -ERR_RECV: -ERR_SEND: -ERR_SOCKET: - return -1; -} - -/* - * ip route del 1:2::2 dev lo table local - * - */ -int _nl_del_lo_route(const ip_address_t *ip_address) { - char buffer[BUFSIZE]; - struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; - size_t n; - int fd; - - struct { - struct nlmsghdr hdr; - struct rtmsg payload; - } msg = { - .hdr.nlmsg_type = RTM_DELROUTE, - .hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK, - .hdr.nlmsg_seq = seq++, - .payload.rtm_family = ip_address->family, - .payload.rtm_dst_len = ip_address->prefix_len, - .payload.rtm_src_len = 0, - .payload.rtm_tos = 0, - .payload.rtm_table = RT_TABLE_LOCAL, - .payload.rtm_protocol = RTPROT_UNSPEC, - .payload.rtm_scope = RT_SCOPE_UNIVERSE, - .payload.rtm_type = RTN_UNSPEC, - .payload.rtm_flags = 0 // RTM_F_NOTIFY in 'ip route get' - }; - - /* Set attribute = length/type/value */ - uint32_t one = 1; - struct rtattr a_dst = {RTA_LENGTH(ip_address_len(ip_address)), RTA_DST}; - struct rtattr a_ifid_lo = {RTA_LENGTH(sizeof(uint32_t)), RTA_OIF}; - struct iovec iov[] = { - {&msg, sizeof(msg)}, - /* Ip address */ - {&a_dst, sizeof(a_dst)}, - {(void *)&ip_address->buffer, ip_address_len(ip_address)}, - /* Interface id */ - {&a_ifid_lo, sizeof(a_ifid_lo)}, - {&one, sizeof(one)}}; - msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); - - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR; - } - - n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); - if (n == -1) { - goto ERR; - } - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR; - } - - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0) { - errno = -err->error; - goto ERR; - } - return 0; - } - - return HICN_SOCKET_ERROR_NONE; -ERR: - return HICN_SOCKET_ERROR_UNSPEC; -} - -/* - * ip -6 rule add iif INTERFACE_NAME lookup TABLE_ID - */ -int _nl_add_rule(const char *interface_name, uint8_t address_family, - const uint8_t table_id) { - char buffer[BUFSIZE]; - struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; - size_t n; - int fd; - - _nl_header(RTM_NEWRULE, (uint8_t *)buffer, BUFSIZE, FLAGS_CREATE); - _nl_payload_rule(table_id, address_family, (uint8_t *)buffer, BUFSIZE); - - /* XXX iif */ - addAttr(hdr, BUFSIZE, FRA_IIFNAME, (void *)interface_name, - strlen(interface_name)); - // attr1 = addNestedAttr(hdr, IFLA_LINKINFO); - // endNestedAttr(hdr, attr1); - - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR_SOCKET; - } - - n = send(fd, buffer, hdr->nlmsg_len, 0); - if (n == -1) { - goto ERR_SEND; - } - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR_RECV; - } - - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0) { - errno = -err->error; - goto ERR_NL; - } - return 0; - } - -ERR_NL: -ERR_RECV: -ERR_SEND: -ERR_SOCKET: - return -1; -} - -/* - * ip -6 rule del iif INTERFACE_NAME //lookup TABLE_ID - */ -int _nl_del_rule(const char *interface_name, uint8_t address_family, - const uint8_t table_id) { - char buffer[BUFSIZE]; - struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; - size_t n; - int fd; - - _nl_header(RTM_DELRULE, (uint8_t *)buffer, BUFSIZE, FLAGS_CREATE); - _nl_payload_rule(table_id, address_family, (uint8_t *)buffer, BUFSIZE); - - /* XXX iif */ - addAttr(hdr, BUFSIZE, FRA_IIFNAME, (void *)interface_name, - strlen(interface_name)); - - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR_SOCKET; - } - - n = send(fd, buffer, hdr->nlmsg_len, 0); - if (n == -1) { - goto ERR_SEND; - } - - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR_RECV; - } - - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0) { - errno = -err->error; - goto ERR_NL; - } - return 0; - } - -ERR_NL: -ERR_RECV: -ERR_SEND: -ERR_SOCKET: - return -1; -} - -/* - * ip -6 neigh add proxy 1:2::2 dev hicnc-cons-eth0 2>&1 | grep nei - * - */ -int _nl_add_neigh_proxy(const ip_address_t *ip_address, - const uint32_t interface_id) { - /* Buffer for holding the response, with appropriate casting on the header */ - char buffer[BUFSIZE]; - struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; - - /* Used for send and receive operations on netlink socket */ - int fd; - size_t n; - - /* Packet header */ - struct { - struct nlmsghdr hdr; - struct ndmsg payload; - } msg = { - .hdr.nlmsg_type = RTM_NEWNEIGH, - .hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK | NLM_F_EXCL, - .hdr.nlmsg_seq = seq++, - .payload.ndm_family = ip_address->family, - .payload.ndm_ifindex = interface_id, - .payload.ndm_state = NUD_PERMANENT, - .payload.ndm_flags = NTF_PROXY, - }; - - /* Message attributes = length/type/value */ - struct rtattr a_dst = {RTA_LENGTH(ip_address_len(ip_address)), NDA_DST}; - - /* Iovec describing the packets */ - struct iovec iov[] = { - {&msg, sizeof(msg)}, - /* Ip address */ - {&a_dst, sizeof(a_dst)}, - {(void *)&ip_address->buffer, sizeof(ip_address->buffer)}, - }; - msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); - - /* Open netlink socket */ - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR; - } - - /* Send packet */ - n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); - if (n == -1) { - goto ERR; - } - - /* Receive answer */ - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR; - } - - /* Parse answer */ - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0) { - errno = -err->error; - goto ERR; - } - } - - return HICN_SOCKET_ERROR_NONE; -ERR: - return HICN_SOCKET_ERROR_UNSPEC; -} - -/* ip -6 route add 0:1::/64 dev hicn-if0 table 100 */ -/* ip -6 route add 0:2::/64 dev hicn-if1 table 100 */ -int _nl_add_in_route_table(const ip_address_t *prefix, - const uint32_t interface_id, - const uint8_t table_id) { - /* Buffer for holding the response, with appropriate casting on the header */ - char buffer[BUFSIZE]; - struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; - - /* Used for send and receive operations on netlink socket */ - int fd; - size_t n; - - /* Packet header */ - struct { - struct nlmsghdr hdr; - struct rtmsg payload; - } msg = { - .hdr.nlmsg_type = RTM_NEWROUTE, - .hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK | NLM_F_EXCL, - .hdr.nlmsg_seq = seq++, - .payload.rtm_family = prefix->family, - .payload.rtm_dst_len = prefix->prefix_len, // XXX ? XXX dst_len, - .payload.rtm_src_len = 0, - .payload.rtm_tos = 0, - .payload.rtm_table = table_id, /* RT_TABLE_MAIN, etc. */ - .payload.rtm_protocol = RTPROT_BOOT, - .payload.rtm_scope = - prefix->family == AF_INET6 ? RT_SCOPE_UNIVERSE : RT_SCOPE_LINK, - .payload.rtm_type = RTN_UNICAST, - .payload.rtm_flags = 0, - }; - - /* Message attributes = length/type/value */ - // XXX This could be put directly inside the iovec maybe ? XXX - struct rtattr a_dst = {RTA_LENGTH(ip_address_len(prefix)), RTA_DST}; - struct rtattr a_oif = {RTA_LENGTH(sizeof(uint32_t)), RTA_OIF}; - - /* Iovec describing the packets */ - struct iovec iov[] = { - {&msg, sizeof(msg)}, - /* Destination prefix / ip address */ - {&a_dst, sizeof(a_dst)}, - {(void *)&prefix->buffer, ip_address_len(prefix)}, - /* Output interface */ - {&a_oif, sizeof(a_oif)}, - {(void *)&interface_id, sizeof(uint32_t)}, - }; - msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); - - /* Open netlink socket */ - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR; - } - - /* Send packet */ - n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); - if (n == -1) { - goto ERR; - } - - /* Receive answer */ - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR; - } - - /* Parse answer */ - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0) { - errno = -err->error; - goto ERR; - } - } - - return HICN_SOCKET_ERROR_NONE; -ERR: - return HICN_SOCKET_ERROR_UNSPEC; -} - -/* Additional helper functions */ - -int _nl_add_in_route_table_s(const char *prefix, const uint32_t interface_id, - const uint8_t table_id) { - int rc; - ip_address_t ip_address; - - rc = hicn_ip_pton(prefix, &ip_address); - if (rc < 0) { - return rc; - } - - return _nl_add_in_route_table(&ip_address, interface_id, table_id); -} - -int _nl_add_in_route_s(const char *prefix, const uint32_t interface_id) { - return _nl_add_in_route_table_s(prefix, interface_id, RT_TABLE_MAIN); -} - -////////* ip -6 rule add from all prio 10 table local */ -/* ip -6 rule add from b001::/16 prio 0 table 100 */ -int _nl_add_prio_rule(const ip_address_t *ip_address, uint8_t address_family, - const uint32_t priority, const uint8_t table_id) { - /* Buffer for holding the response, with appropriate casting on the header */ - char buffer[BUFSIZE]; - struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; - - /* Used for send and receive operations on netlink socket */ - int fd; - size_t n; - - /* Packet header */ - struct { - struct nlmsghdr hdr; - struct fib_rule_hdr payload; - } msg = { - .hdr.nlmsg_type = RTM_NEWRULE, - .hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK | NLM_F_EXCL, - .hdr.nlmsg_seq = seq++, - .payload.family = address_family, - //.payload.dst_len = , - .payload.src_len = ip_address ? ip_address->prefix_len : 0, - .payload.tos = 0, - .payload.table = table_id, - .payload.action = FR_ACT_TO_TBL, - .payload.flags = NLM_F_REPLACE, // 0 - }; - - /* Open netlink socket */ - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR; - } - - if (ip_address) { - /* Message attributes = length/type/value */ - struct rtattr a_src = {RTA_LENGTH(ip_address_len(ip_address)), FRA_SRC}; - struct rtattr a_prio = {RTA_LENGTH(sizeof(uint32_t)), FRA_PRIORITY}; - - /* Iovec describing the packets */ - struct iovec iov[] = { - {&msg, sizeof(msg)}, - /* Source prefix / ip_address */ - {&a_src, sizeof(a_src)}, - {(void *)&ip_address->buffer, ip_address_len(ip_address)}, - /* Priority */ - {&a_prio, sizeof(a_prio)}, - {(void *)&priority, sizeof(uint32_t)}, - }; - msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); - - /* Send packet */ - n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); - if (n == -1) { - goto ERR; - } - } else { - struct rtattr a_prio = {RTA_LENGTH(sizeof(uint32_t)), FRA_PRIORITY}; - - /* Iovec describing the packets */ - struct iovec iov[] = { - {&msg, sizeof(msg)}, - /* Priority */ - {&a_prio, sizeof(a_prio)}, - {(void *)&priority, sizeof(uint32_t)}, - }; - msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); - - /* Send packet */ - n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); - if (n == -1) { - goto ERR; - } - } - - /* Receive answer */ - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR; - } - - /* Parse answer */ - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0) { - errno = -err->error; - goto ERR; - } - } - - return HICN_SOCKET_ERROR_NONE; -ERR: - return HICN_SOCKET_ERROR_UNSPEC; -} - -int _nl_add_lo_prio_rule(const ip_address_t *ip_address, uint8_t address_family, - const uint32_t priority) { - return _nl_add_prio_rule(ip_address, address_family, priority, - RT_TABLE_LOCAL); -} - -/* ip -6 rule del from all prio 0 table local */ -int _nl_del_prio_rule(const ip_address_t *ip_address, uint8_t address_family, - const uint32_t priority, const uint8_t table_id) { - /* Buffer for holding the response, with appropriate casting on the header */ - char buffer[BUFSIZE]; - struct nlmsghdr *hdr = (struct nlmsghdr *)buffer; - - /* Used for send and receive operations on netlink socket */ - int fd; - size_t n; - - /* Packet header */ - struct { - struct nlmsghdr hdr; - struct fib_rule_hdr payload; - } msg = { - .hdr.nlmsg_type = RTM_DELRULE, - .hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_ACK | NLM_F_EXCL, - .hdr.nlmsg_seq = seq++, - .payload.family = address_family, - //.payload.dst_len = , - .payload.src_len = ip_address ? ip_address->prefix_len : 0, - .payload.tos = 0, - .payload.table = table_id, - .payload.action = FR_ACT_TO_TBL, - .payload.flags = NLM_F_REPLACE, // 0 - }; - - /* Open netlink socket */ - fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE); - if (fd < 0) { - goto ERR; - } - - /* Message attributes = length/type/value */ - if (ip_address) { - struct rtattr a_src = {RTA_LENGTH(ip_address_len(ip_address)), FRA_SRC}; - struct rtattr a_prio = {RTA_LENGTH(sizeof(uint32_t)), FRA_PRIORITY}; - - /* Iovec describing the packets */ - struct iovec iov[] = { - {&msg, sizeof(msg)}, - /* Source prefix / ip_address */ - {&a_src, sizeof(a_src)}, - {(void *)&ip_address->buffer, ip_address_len(ip_address)}, - /* Priority */ - {&a_prio, sizeof(a_prio)}, - {(void *)&priority, sizeof(uint32_t)}, - }; - msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); - - /* Send packet */ - n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); - if (n == -1) { - goto ERR; - } - - } else { - struct rtattr a_prio = {RTA_LENGTH(sizeof(uint32_t)), FRA_PRIORITY}; - - /* Iovec describing the packets */ - struct iovec iov[] = { - {&msg, sizeof(msg)}, - /* Priority */ - {&a_prio, sizeof(a_prio)}, - {(void *)&priority, sizeof(uint32_t)}, - }; - msg.hdr.nlmsg_len = iov_length(iov, ARRAY_SIZE(iov)); - - /* Send packet */ - n = writev(fd, (struct iovec *)&iov, ARRAY_SIZE(iov)); - if (n == -1) { - goto ERR; - } - } - - /* Receive answer */ - n = recv(fd, buffer, BUFSIZE, 0); - if (n == -1) { - goto ERR; - } - - /* Parse answer */ - if (hdr->nlmsg_type == NLMSG_ERROR) { - struct nlmsgerr *err = (struct nlmsgerr *)NLMSG_DATA(hdr); - if (err->error < 0 && - err->error != -2) { //-2 is not such file or directory - errno = -err->error; - goto ERR; - } - } - - return HICN_SOCKET_ERROR_NONE; -ERR: - return HICN_SOCKET_ERROR_UNSPEC; -} - -int _nl_del_lo_prio_rule(const ip_address_t *ip_address, uint8_t address_family, - const uint32_t priority) { - return _nl_del_prio_rule(ip_address, address_family, priority, - RT_TABLE_LOCAL); -} - -/******************************************************************************/ - -// #include <net/if.h> -// duplicate declarations, in the meantime -#define IF_NAMESIZE 16 - -//#define WITH_TUN_PI 1 - -#ifdef WITH_TUN_PI -#define TUN_FLAGS IFF_TUN -#else -#define TUN_FLAGS IFF_TUN | IFF_NO_PI -#endif - -/* - * Taken from Kernel Documentation/networking/tuntap.txt - */ - -int tun_alloc(char *dev, int flags) { - struct ifreq ifr; - int fd, err; - char *clonedev = "/dev/net/tun"; - - /* Arguments taken by the function: - * - * char *dev: the name of an interface (or '\0'). MUST have enough - * space to hold the interface name if '\0' is passed - * int flags: interface flags (eg, IFF_TUN etc.) - */ - - /* open the clone device */ - if ((fd = open(clonedev, O_RDWR)) < 0) { - return fd; - } - - /* preparation of the struct ifr, of type "struct ifreq" */ - memset(&ifr, 0, sizeof(ifr)); - - ifr.ifr_flags = flags; - - if (*dev) { - /* if a device name was specified, put it in the structure; otherwise, - * the kernel will try to allocate the "next" device of the - * specified type */ - strncpy(ifr.ifr_name, dev, IF_NAMESIZE - 1); - } - - /* try to create the device */ - if ((err = ioctl(fd, TUNSETIFF, (void *)&ifr)) < 0) { - close(fd); - return err; - } - - /* if the operation was successful, write back the name of the - * interface to the variable "dev", so the caller can know - * it. Note that the caller MUST reserve space in *dev (see calling - * code below) */ - strcpy(dev, ifr.ifr_name); - - /* this is the special file descriptor that the caller will use to talk - * with the virtual interface */ - return fd; -} - -int linux_get_tun_name(const char *prefix, const char *identifier, - char *tun_name) { - snprintf(tun_name, IF_NAMESIZE, "%s-%s", prefix, - identifier ? identifier : "main"); - return 0; -} - -int linux_tun_enable_offload(int fd) { - unsigned int offload = 0, tso4 = 1, tso6 = 1, ecn = 1, ufo = 1, csum = 1; - - /* Check if our kernel supports TUNSETOFFLOAD */ - if (ioctl(fd, TUNSETOFFLOAD, 0) != 0 && errno == EINVAL) { - goto ERR_TUN; - } - - if (csum) { - offload |= TUN_F_CSUM; - if (tso4) offload |= TUN_F_TSO4; - if (tso6) offload |= TUN_F_TSO6; - if ((tso4 || tso6) && ecn) offload |= TUN_F_TSO_ECN; - if (ufo) offload |= TUN_F_UFO; - } - - if (ioctl(fd, TUNSETOFFLOAD, offload) != 0) { - offload &= ~TUN_F_UFO; - if (ioctl(fd, TUNSETOFFLOAD, offload) != 0) { - fprintf(stderr, "TUNSETOFFLOAD ioctl() failed: %s\n", strerror(errno)); - } - } - - return 0; - -ERR_TUN: - return -1; -} - -int linux_tun_create(char *name) { - int fd, rc; - - fd = tun_alloc(name, TUN_FLAGS); - if (fd < 0) { - // ERROR("Error connecting to tun/tap interface %s!", name); - errno = -2; - goto ERR_TUN; - } - - rc = linux_tun_enable_offload(fd); - if (rc < 0) { - // WARN("Could not enable hardware offload on TUN device"); - } else { - // INFO("Enabled hardware offload on TUN device"); - } - - return fd; - -ERR_TUN: - return -1; -} - -/* - * - * interface name can be NULL for all interfaces - */ -int linux_enable_proc(char *path) { - int ret = 0; - int fd; - - fd = open(path, O_WRONLY); - if (fd < 0) { - return -1; - } - - if (write(fd, "1", 1) != 1) { - ret = -2; - } - - close(fd); - return ret; -} - -int linux_enable_v4_forwarding() { - return linux_enable_proc("/proc/sys/net/ipv4/ip_forward"); -} - -int linux_enable_v6_forwarding(char *interface_name) { - char path[PATH_MAX]; - snprintf(path, PATH_MAX, "/proc/sys/net/ipv6/conf/%s/forwarding", - (interface_name) ? interface_name : "all"); - - return linux_enable_proc(path); -} - -int linux_enable_ndp_proxy() { - return linux_enable_proc("/proc/sys/net/ipv6/conf/all/proxy_ndp"); -} - -const hicn_socket_ops_t ops = { - .arch = "linux", - .get_tun_name = linux_get_tun_name, - .tun_create = linux_tun_create, - .enable_v4_forwarding = linux_enable_v4_forwarding, - .enable_v6_forwarding = linux_enable_v6_forwarding, - .enable_ndp_proxy = linux_enable_ndp_proxy, - .get_ifid = _nl_get_ifid, - .get_output_ifid = _nl_get_output_ifid, - .get_ip_addr = _nl_get_ip_addr, - .set_ip_addr = _nl_set_ip_addr, - .up_if = _nl_up_if, - .add_in_route_table = _nl_add_in_route_table, - .add_in_route_table_s = _nl_add_in_route_table_s, - .add_in_route_s = _nl_add_in_route_s, - .add_out_route = _nl_add_out_route, - .del_out_route = _nl_del_out_route, - .del_lo_route = _nl_del_lo_route, - .add_rule = _nl_add_rule, - .del_rule = _nl_del_rule, - .add_neigh_proxy = _nl_add_neigh_proxy, - .add_prio_rule = _nl_add_prio_rule, - .add_lo_prio_rule = _nl_add_lo_prio_rule, - .del_prio_rule = _nl_del_prio_rule, - .del_lo_prio_rule = _nl_del_lo_prio_rule, -}; |