From bac3da61644515f05663789b122554dc77549286 Mon Sep 17 00:00:00 2001 From: Luca Muscariello Date: Thu, 17 Jan 2019 13:47:57 +0100 Subject: This is the first commit of the hicn project Change-Id: I6f2544ad9b9f8891c88cc4bcce3cf19bd3cc863f Signed-off-by: Luca Muscariello --- hicn-light/src/config/configurationListeners.c | 535 +++++++++++++++++++++++++ 1 file changed, 535 insertions(+) create mode 100755 hicn-light/src/config/configurationListeners.c (limited to 'hicn-light/src/config/configurationListeners.c') diff --git a/hicn-light/src/config/configurationListeners.c b/hicn-light/src/config/configurationListeners.c new file mode 100755 index 000000000..be30e2a49 --- /dev/null +++ b/hicn-light/src/config/configurationListeners.c @@ -0,0 +1,535 @@ +/* + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +static bool _setupHIcnListenerOnInet4(Forwarder *forwarder, + const char *symbolic, Address *address) { + bool success = false; +#ifndef __APPLE__ + ListenerOps *ops = + hicnListener_CreateInet(forwarder, (char *)symbolic, address); + if (ops != NULL) { + success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops); + parcAssertTrue(success, "Failed to add HIcn listener %s to ListenerSet", + symbolic); + } +#endif /* __APPLE__ */ + return success; +} + +static bool _setupHIcnListenerOnInet6(Forwarder *forwarder, + const char *symbolic, Address *address) { + bool success = false; +#ifndef __APPLE__ + ListenerOps *ops = + hicnListener_CreateInet6(forwarder, (char *)symbolic, address); + if (ops != NULL) { + success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops); + parcAssertTrue(success, "Failed to add HIcn listener %s to ListenerSet", + symbolic); + } +#endif /* __APPLE__ */ + return success; +} + +bool configurationListeners_Remove(const Configuration *config) { + Logger *logger = configuration_GetLogger(config); + if (logger_IsLoggable(logger, LoggerFacility_Config, PARCLogLevel_Warning)) { + logger_Log(logger, LoggerFacility_Config, PARCLogLevel_Warning, __func__, + "Removing a listener not supported: ingress %u control %s"); + } + + return false; +} + +bool _AddPuntingInet(const Configuration *config, Punting *punting, + unsigned ingressId) { +#ifndef __APPLE__ + struct sockaddr *addr = parcNetwork_SockAddress("0.0.0.0", 1234); + if (addr == NULL) { + printf("Error creating address\n"); + return false; + } + + Address *fakeAddr = addressCreateFromInet((struct sockaddr_in *)addr); + + ListenerOps *listenerOps = listenerSet_Find( + forwarder_GetListenerSet(configuration_GetForwarder(config)), ENCAP_HICN, + fakeAddr); + addressDestroy(&fakeAddr); + + if (listenerOps == NULL) { + printf("the main listener (IPV4) does not exists\n"); + return false; + } + + struct sockaddr_in puntingAddr; + + Address *address = puntingGetAddress(punting); + if (address == NULL) return false; + + bool res = addressGetInet(address, &puntingAddr); + if (!res) { + printf("unable to read the punting address\n"); + return false; + } + + char prefix[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &(puntingAddr.sin_addr), prefix, INET_ADDRSTRLEN); + + char len[5]; + sprintf(len, "%d", puntingPrefixLen(punting)); + + char *prefixStr = + malloc(strlen(prefix) + strlen(len) + 2); //+1 for the zero-terminator + if (prefixStr == NULL) { + printf("error while create the prefix string\n"); + return false; + } + strcpy(prefixStr, prefix); + strcat(prefixStr, "/"); + strcat(prefixStr, len); + + res = hicnListener_Punting(listenerOps, prefixStr); + if (!res) { + printf("error while adding the punting rule\n"); + return false; + } + + return true; +#else + return false; +#endif +} + +bool _AddPuntingInet6(const Configuration *config, Punting *punting, + unsigned ingressId) { +#ifndef __APPLE__ + struct sockaddr *addr = parcNetwork_SockAddress("0::0", 1234); + if (addr == NULL) { + printf("Error creating address\n"); + return false; + } + + Address *fakeAddr = addressCreateFromInet6((struct sockaddr_in6 *)addr); + + // comments: + // EncapType: I use the HIcn encap since the puting is available only for HIcn + // listeners LocalAddress: The only listern for which we need punting rules is + // the main one, which has no address + // so I create a fake empty address. This need to be consistent + // with the address set at creation time + + ListenerOps *listenerOps = listenerSet_Find( + forwarder_GetListenerSet(configuration_GetForwarder(config)), ENCAP_HICN, + fakeAddr); + addressDestroy(&fakeAddr); + + if (listenerOps == NULL) { + printf("the main listener does not exists\n"); + return false; + } + + struct sockaddr_in6 puntingAddr; + bool res = addressGetInet6(puntingGetAddress(punting), &puntingAddr); + if (!res) { + printf("unable to read the punting address\n"); + return false; + } + + char prefix[INET6_ADDRSTRLEN]; + inet_ntop(AF_INET6, &(puntingAddr.sin6_addr), prefix, INET6_ADDRSTRLEN); + + char len[5]; + sprintf(len, "%d", puntingPrefixLen(punting)); + + char *prefixStr = + malloc(strlen(prefix) + strlen(len) + 2); //+1 for the zero-terminator + if (prefixStr == NULL) { + printf("error while create the prefix string\n"); + return false; + } + strcpy(prefixStr, prefix); + strcat(prefixStr, "/"); + strcat(prefixStr, len); + + res = hicnListener_Punting(listenerOps, prefixStr); + if (!res) { + printf("error while adding the punting rule\n"); + return false; + } + + return true; +#else + return false; +#endif +} + +//============= LIGHT COMMAN =============== + +static bool _addEther(Configuration *config, add_listener_command *control, + unsigned ingressId) { + // Not implemented + return false; +} + +static bool _setupTcpListenerOnInet(Forwarder *forwarder, ipv4_addr_t *addr4, + uint16_t *port) { + bool success = false; + + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = *port; + addr.sin_addr.s_addr = *addr4; + + ListenerOps *ops = tcpListener_CreateInet(forwarder, addr); + if (ops) { + success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops); + parcAssertTrue(success, "Failed to add TCP listener on %s to ListenerSet", + addressToString(ops->getListenAddress(ops))); + } + return success; +} + +static bool _setupUdpListenerOnInet(Forwarder *forwarder, ipv4_addr_t *addr4, + uint16_t *port) { + bool success = false; + + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = *port; + addr.sin_addr.s_addr = *addr4; + + ListenerOps *ops = udpListener_CreateInet(forwarder, addr); + if (ops) { + success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops); + parcAssertTrue(success, "Failed to add UDP listener on %s to ListenerSet", + addressToString(ops->getListenAddress(ops))); + } + return success; +} + +static bool _setupTcpListenerOnInet6Light(Forwarder *forwarder, + ipv6_addr_t *addr6, uint16_t *port, + uint32_t scopeId) { + bool success = false; + + struct sockaddr_in6 addr; + memset(&addr, 0, sizeof(addr)); + addr.sin6_family = AF_INET6; + addr.sin6_port = *port; + addr.sin6_addr = *addr6; + addr.sin6_scope_id = scopeId; + + ListenerOps *ops = tcpListener_CreateInet6(forwarder, addr); + if (ops) { + success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops); + parcAssertTrue(success, "Failed to add TCP6 listener on %s to ListenerSet", + addressToString(ops->getListenAddress(ops))); + } + return success; +} + +static bool _setupUdpListenerOnInet6Light(Forwarder *forwarder, + ipv6_addr_t *addr6, uint16_t *port) { + bool success = false; + + struct sockaddr_in6 addr; + memset(&addr, 0, sizeof(addr)); + addr.sin6_family = AF_INET6; + addr.sin6_port = *port; + addr.sin6_addr = *addr6; + addr.sin6_scope_id = 0; + + ListenerOps *ops = udpListener_CreateInet6(forwarder, addr); + if (ops) { + success = listenerSet_Add(forwarder_GetListenerSet(forwarder), ops); + parcAssertTrue(success, "Failed to add UDP6 listener on %s to ListenerSet", + addressToString(ops->getListenAddress(ops))); + } + return success; +} + +bool _addHicn(Configuration *config, add_listener_command *control, + unsigned ingressId) { + bool success = false; + const char *symbolic = control->symbolic; + Address *localAddress = NULL; + + switch (control->addressType) { + case ADDR_INET: { + localAddress = + utils_AddressFromInet(&control->address.ipv4, &control->port); + success = _setupHIcnListenerOnInet4(configuration_GetForwarder(config), + symbolic, localAddress); + break; + } + + case ADDR_INET6: { + localAddress = + utils_AddressFromInet6(&control->address.ipv6, &control->port); + success = _setupHIcnListenerOnInet6(configuration_GetForwarder(config), + symbolic, localAddress); + break; + } + + default: + if (logger_IsLoggable(configuration_GetLogger(config), + LoggerFacility_Config, PARCLogLevel_Warning)) { + logger_Log(configuration_GetLogger(config), LoggerFacility_Config, + PARCLogLevel_Warning, __func__, + "Unsupported address type for HICN (ingress id %u): " + "must be either IPV4 or IPV6", + ingressId); + } + break; + } + + if (success == true && localAddress != NULL) { + if (logger_IsLoggable(configuration_GetLogger(config), + LoggerFacility_Config, PARCLogLevel_Info)) { + logger_Log(configuration_GetLogger(config), LoggerFacility_Config, + PARCLogLevel_Info, __func__, + "Setup hicn listener on address %s", + addressToString(localAddress)); + } + } + + addressDestroy(&localAddress); + + return success; +} + +bool _addIP(Configuration *config, add_listener_command *control, + unsigned ingressId) { + bool success = false; + + switch (control->addressType) { + case ADDR_INET: { + if (control->connectionType == UDP_CONN) { + success = + _setupUdpListenerOnInet(configuration_GetForwarder(config), + &control->address.ipv4, &control->port); + } else if (control->connectionType == TCP_CONN) { + success = + _setupTcpListenerOnInet(configuration_GetForwarder(config), + &control->address.ipv4, &control->port); + } + break; + } + + case ADDR_INET6: { + if (control->connectionType == UDP_CONN) { + success = _setupUdpListenerOnInet6Light( + configuration_GetForwarder(config), &control->address.ipv6, + &control->port); + } else if (control->connectionType == TCP_CONN) { + success = _setupTcpListenerOnInet6Light( + configuration_GetForwarder(config), &control->address.ipv6, + &control->port, 0); + } + break; + } + + default: + if (logger_IsLoggable(configuration_GetLogger(config), + LoggerFacility_Config, PARCLogLevel_Warning)) { + char *addrStr = utils_CommandAddressToString( + control->addressType, &control->address, &control->port); + logger_Log( + configuration_GetLogger(config), LoggerFacility_Config, + PARCLogLevel_Warning, __func__, + "Unsupported address type for IP encapsulation ingress id %u: %s", + ingressId, addrStr); + parcMemory_Deallocate((void **)&addrStr); + } + break; + } + + if (success) { + if (logger_IsLoggable(configuration_GetLogger(config), + LoggerFacility_Config, PARCLogLevel_Info)) { + char *addrStr = utils_CommandAddressToString( + control->addressType, &control->address, &control->port); + logger_Log(configuration_GetLogger(config), LoggerFacility_Config, + PARCLogLevel_Info, __func__, "Setup listener on address %s", + addrStr); + parcMemory_Deallocate((void **)&addrStr); + } + } + + return success; +} + +struct iovec *configurationListeners_Add(Configuration *config, + struct iovec *request, + unsigned ingressId) { + header_control_message *header = request[0].iov_base; + add_listener_command *control = request[1].iov_base; + + bool success = false; + + if (control->listenerMode == ETHER_MODE) { + parcTrapNotImplemented("Add Ethernet Listener is not supported"); + success = _addEther(config, control, ingressId); + // it is a failure + } else if (control->listenerMode == IP_MODE) { + success = _addIP(config, control, ingressId); + } else if (control->listenerMode == HICN_MODE) { + success = _addHicn(config, control, ingressId); + } else { + Logger *logger = configuration_GetLogger(config); + if (logger_IsLoggable(logger, LoggerFacility_Config, + PARCLogLevel_Warning)) { + logger_Log(logger, LoggerFacility_Config, PARCLogLevel_Warning, __func__, + "Unsupported encapsulation mode (ingress id %u)", ingressId); + } + } + + // generate ACK/NACK + struct iovec *response; + + if (success) { // ACK + response = utils_CreateAck(header, control, sizeof(add_listener_command)); + } else { // NACK + response = utils_CreateNack(header, control, sizeof(add_listener_command)); + } + + return response; +} + +struct iovec *configurationListeners_AddPunting(Configuration *config, + struct iovec *request, + unsigned ingressId) { + header_control_message *header = request[0].iov_base; + add_punting_command *control = request[1].iov_base; + + const char *symbolicOrConnid = control->symbolicOrConnid; + uint32_t len = control->len; + in_port_t port = htons(1234); + bool success = false; + + if (control->addressType == ADDR_INET) { + Address *address = utils_AddressFromInet(&control->address.ipv4, &port); + Punting *punting = puntingCreate(symbolicOrConnid, address, len); + success = _AddPuntingInet(config, punting, ingressId); + addressDestroy(&address); + } else if (control->addressType == ADDR_INET6) { + Address *address = utils_AddressFromInet6(&control->address.ipv6, &port); + Punting *punting = puntingCreate(symbolicOrConnid, address, len); + success = _AddPuntingInet6(config, punting, ingressId); + addressDestroy(&address); + } else { + printf("Invalid IP type.\n"); // will generate a Nack + return utils_CreateNack(header, control, sizeof(add_punting_command)); + } + + // generate ACK/NACK + struct iovec *response; + if (success) { // ACK + response = utils_CreateAck(header, control, sizeof(add_punting_command)); + } else { // NACK + response = utils_CreateNack(header, control, sizeof(add_punting_command)); + } + + return response; +} + +//=========================== INITIAL LISTENERS ==================== + +static void _setupListenersOnAddress(Forwarder *forwarder, + const Address *address, uint16_t port, + const char *interfaceName) { + address_type type = addressGetType(address); + switch (type) { + case ADDR_INET: { + struct sockaddr_in tmp; + addressGetInet(address, &tmp); + _setupTcpListenerOnInet(forwarder, &tmp.sin_addr.s_addr, &port); + break; + } + + case ADDR_INET6: { + struct sockaddr_in6 tmp; + addressGetInet6(address, &tmp); + _setupTcpListenerOnInet6Light(forwarder, &tmp.sin6_addr, &port, + tmp.sin6_scope_id); + break; + } + + case ADDR_LINK: + // not used + break; + + default: + // dont' know how to handle this, so no listeners + break; + } +} + +void configurationListeners_SetupAll(const Configuration *config, uint16_t port, + const char *localPath) { + Forwarder *forwarder = configuration_GetForwarder(config); + InterfaceSet *set = system_Interfaces(forwarder); + + size_t interfaceSetLen = interfaceSetLength(set); + for (size_t i = 0; i < interfaceSetLen; i++) { + Interface *iface = interfaceSetGetByOrdinalIndex(set, i); + + const AddressList *addresses = interfaceGetAddresses(iface); + size_t addressListLen = addressListLength(addresses); + + for (size_t j = 0; j < addressListLen; j++) { + const Address *address = addressListGetItem(addresses, j); + + // Do not start on link address + if (addressGetType(address) != ADDR_LINK) { + _setupListenersOnAddress(forwarder, address, htons(port), + interfaceGetName(iface)); + } + } + } + + // if (localPath != NULL) { + // _setupLocalListener(forwarder, localPath); + //} + + interfaceSetDestroy(&set); +} -- cgit 1.2.3-korg