From eb323e056e747d71867cf965434811c1de925de2 Mon Sep 17 00:00:00 2001 From: Luca Muscariello Date: Sat, 23 Mar 2019 14:13:53 +0100 Subject: [HICN-141] Definition of a C API for hicn-light Change-Id: Id861f0abe58b1e3c9ba8cc76701da0f9c6801748 Signed-off-by: Luca Muscariello Signed-off-by: Angelo Mantellini --- hicn-light/src/socket/ops_linux.c | 1723 ------------------------------------- 1 file changed, 1723 deletions(-) delete mode 100644 hicn-light/src/socket/ops_linux.c (limited to 'hicn-light/src/socket/ops_linux.c') 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 // ioctl -#include // needed by linux/if.h -//#include -#include -#include // '' -#include -#include // PATH_MAX -#include // fprintf -#include // memset -#include // open -#include // writev -#include // 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 -#include - -// 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 // inet_pton -#include // errno -#include // fib_rule_hdr, FRA_* -#include -#include -#include // IFF_UP -#include // in6addr -#include // perror -#include -#include // '' -#include // socket -#include // read - -#include // '' -#include // 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 -// 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, -}; -- cgit 1.2.3-korg