aboutsummaryrefslogtreecommitdiffstats
path: root/hicn-light/src/socket
diff options
context:
space:
mode:
Diffstat (limited to 'hicn-light/src/socket')
-rw-r--r--hicn-light/src/socket/CMakeLists.txt31
-rw-r--r--hicn-light/src/socket/api.c604
-rw-r--r--hicn-light/src/socket/api.h217
-rw-r--r--hicn-light/src/socket/error.c7
-rw-r--r--hicn-light/src/socket/error.h46
-rw-r--r--hicn-light/src/socket/ops.h54
-rw-r--r--hicn-light/src/socket/ops_linux.c1723
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,
-};