From 15ad172a847fa667c57a4594ef4158405db9a984 Mon Sep 17 00:00:00 2001 From: Angelo Mantellini Date: Tue, 31 Mar 2020 17:50:43 +0200 Subject: [HICN-554] hicn-light refactoring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I36f2d393741d4502ce14d3791158e43e3e9cd4cf Signed-off-by: Jordan Augé --- hicn-light/src/hicn/config/configuration.c | 2407 +++++++++++++--------------- 1 file changed, 1157 insertions(+), 1250 deletions(-) (limited to 'hicn-light/src/hicn/config/configuration.c') diff --git a/hicn-light/src/hicn/config/configuration.c b/hicn-light/src/hicn/config/configuration.c index 39d327165..a6f78f9c2 100644 --- a/hicn-light/src/hicn/config/configuration.c +++ b/hicn-light/src/hicn/config/configuration.c @@ -26,531 +26,424 @@ #include #endif #include -#include #include #include #include #include -#include -#include -#include - -#include -#include - #include -#include +#include #include -#include +//#include #ifdef WITH_MAPME #include #endif /* WITH_MAPME */ -#include - -#include -#include -#include - -#include -#include //the listener list -#include // needed to print +#include //the listener list +#include #include #include - -#include +#include +#include +#include #define ETHERTYPE 0x0801 +#define DEFAULT_COST 1 +#define DEFAULT_PORT 1234 + +#define make_ack(msg) msg->header.messageType = ACK_LIGHT +#define make_nack(msg) msg->header.messageType = NACK_LIGHT + +#define msg_malloc_list(msg, N) \ +do { \ + msg = malloc(sizeof((msg)->header) + N * sizeof((msg)->payload)); \ + (msg)->header.messageType = RESPONSE_LIGHT; \ + (msg)->header.length = (uint16_t)(N); \ +} while(0); + +/* + * XXX TODO + * + * Currently the strategy map only stores the strategy type, but it should be + * extended with strategy options. + * + * Or maybe we simply remove this map like in VPP. + * + * prefix_str -> strategy_type + */ +KHASH_INIT(strategy_map, const char *, unsigned, 0, str_hash, str_hash_eq); -struct configuration { - Forwarder *forwarder; - Logger *logger; +struct configuration_s { + forwarder_t * forwarder; - size_t maximumContentObjectStoreSize; + size_t maximumContentObjectStoreSize; - // map from prefix (parcString) to strategy (parcString) - PARCHashMap *strategy_map; + // map from prefix (parcString) to strategy (parcString) + kh_strategy_map_t * strategy_map; - // translates between a symblic name and a connection id - SymbolicNameTable *symbolicNameTable; +#if 0 + // translates between a symblic name and a connection id + // XXX This might be moved as two indices in the listener and connection + // tables to be widely reachable... this has nothing to do with + // configuration. + SymbolicNameTable *symbolic_nameTable; +#endif }; // ======================================================================================== -Connection * -getConnectionBySymbolicOrId(Configuration * config, const char * symbolicOrConnid) +// conn_id = UINT_MAX when symbolic_name is not found +static inline +unsigned +_symbolic_to_conn_id(configuration_t * config, const char * symbolicOrConnid, + bool allow_self, unsigned ingress_id) { - ConnectionTable *table = forwarder_GetConnectionTable(config->forwarder); - unsigned connid; - Connection *conn = NULL; - - /* Try to resolve an eventual symbolic name as input */ - if (utils_IsNumber(symbolicOrConnid)) { - connid = (unsigned int)strtold(symbolicOrConnid, NULL); - - } else { - connid = symbolicNameTable_Get(config->symbolicNameTable, symbolicOrConnid); - if (connid == UINT32_MAX) { - if (logger_IsLoggable(config->logger, LoggerFacility_Config, - PARCLogLevel_Warning)) { - logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Error, - __func__, "Symbolic name '%s' could not be resolved", - symbolicOrConnid); - } - } - } - - /* Get connection by ID */ - conn = (Connection *)connectionTable_FindById( table, connid); - if (!conn) { - if (logger_IsLoggable(config->logger, LoggerFacility_Config, - PARCLogLevel_Warning)) { - logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Error, - __func__, "ConnID not found, check list connections"); + unsigned conn_id; + const connection_table_t * table = forwarder_get_connection_table(config->forwarder); + + if (allow_self && strcmp(symbolicOrConnid, "SELF") == 0) { + conn_id = ingress_id; + } else if (utils_IsNumber(symbolicOrConnid)) { + // case for conn_id as input + // XXX type issue ! XXX No check, see man + int id = atoi(symbolicOrConnid); + if (id < 0) + return CONNECTION_ID_UNDEFINED; + conn_id = id; + + if (!connection_table_validate_id(table, conn_id)) { + ERROR("ConnID not found, check list connections"); + conn_id = CONNECTION_ID_UNDEFINED; + } + } else { + // case for symbolic as input: check if symbolic name can be resolved + conn_id = connection_table_get_id_by_name(table, symbolicOrConnid); + if (connection_id_is_valid(conn_id)) { + DEBUG("Resolved symbolic name '%s' to conn_id %u", symbolicOrConnid, conn_id); + } else { + WARN("Symbolic name '%s' could not be resolved", symbolicOrConnid); + } } - } - return conn; + return conn_id; } -// ======================================================================================== +#define symbolic_to_conn_id(config, symbolic) _symbolic_to_conn_id(config, symbolic, false, 0) + +#define symbolic_to_conn_id_self(config, symbolic, ingress_id) \ + _symbolic_to_conn_id(config, symbolic, true, ingress_id) -Configuration *configuration_Create(Forwarder *forwarder) { - parcAssertNotNull(forwarder, "Parameter hicn-fwd must be non-null"); - Configuration *config = parcMemory_AllocateAndClear(sizeof(Configuration)); - parcAssertNotNull(config, "parcMemory_AllocateAndClear(%zu) returned NULL", - sizeof(Configuration)); - config->forwarder = forwarder; - config->logger = logger_Acquire(forwarder_GetLogger(forwarder)); - config->maximumContentObjectStoreSize = 100000; - config->strategy_map = parcHashMap_Create(); - config->symbolicNameTable = symbolicNameTable_Create(); - - return config; +connection_t * +getConnectionBySymbolicOrId(configuration_t * config, const char * symbolicOrConnid) +{ + connection_table_t * table = forwarder_get_connection_table(config->forwarder); + unsigned conn_id = symbolic_to_conn_id(config, symbolicOrConnid); + if (!connection_id_is_valid(conn_id)) + return NULL; + + /* conn_id is assumed validated here */ + return connection_table_at(table, conn_id); } -void configuration_Destroy(Configuration **configPtr) { - parcAssertNotNull(configPtr, "Parameter must be non-null double poitner"); - parcAssertNotNull(*configPtr, - "Parameter must dereference to non-null pointer"); - - Configuration *config = *configPtr; - logger_Release(&config->logger); - parcHashMap_Release(&(config->strategy_map)); - symbolicNameTable_Destroy(&config->symbolicNameTable); - parcMemory_Deallocate((void **)&config); - *configPtr = NULL; +// ======================================================================================== + +configuration_t * +configuration_create(forwarder_t * forwarder) +{ + assert(forwarder); + + configuration_t * config = malloc(sizeof(configuration_t)); + if (!config) + return NULL; + + config->forwarder = forwarder; + config->maximumContentObjectStoreSize = 100000; + config->strategy_map = kh_init_strategy_map(); +#if 0 + config->symbolic_nameTable = symbolic_nameTable_Create(); +#endif + + return config; } -struct iovec *configuration_ProcessRegisterHicnPrefix(Configuration *config, - struct iovec *request, - unsigned ingressId) { - header_control_message *header = request[0].iov_base; - add_route_command *control = request[1].iov_base; +void +configuration_free(configuration_t * config) +{ + assert(config); - bool success = false; + kh_destroy_strategy_map(config->strategy_map); +#if 0 + symbolic_nameTable_Destroy(&config->symbolic_nameTable); +#endif + free(config); +} - const char *symbolicOrConnid = control->symbolicOrConnid; +/* Listener */ - if (strcmp(symbolicOrConnid, "SELF") == 0) { - success = forwarder_AddOrUpdateRoute(config->forwarder, control, ingressId); - } else if (utils_IsNumber(symbolicOrConnid)) { - // case for connid as input - unsigned connid = (unsigned)strtold(symbolicOrConnid, NULL); - ConnectionTable *table = forwarder_GetConnectionTable(config->forwarder); +uint8_t * +configuration_on_listener_add(configuration_t * config, uint8_t * packet, + unsigned ingress_id) +{ + assert(config); + assert(packet); - // check if iconnID present in the fwd table - if (connectionTable_FindById(table, connid)) { - success = forwarder_AddOrUpdateRoute(config->forwarder, control, connid); - } else { - logger_Log(forwarder_GetLogger(config->forwarder), LoggerFacility_IO, - PARCLogLevel_Error, __func__, - "ConnID not found, check list connections"); - // failure - } + msg_listener_add_t * msg = (msg_listener_add_t *)packet; + cmd_listener_add_t * control = &msg->payload; - } else { - // case for symbolic as input: check if symbolic name can be resolved - unsigned connid = - symbolicNameTable_Get(config->symbolicNameTable, symbolicOrConnid); - // connid = UINT_MAX when symbolicName is not found - if (connid != UINT32_MAX) { - if (logger_IsLoggable(config->logger, LoggerFacility_Config, - PARCLogLevel_Debug)) { - logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Debug, - __func__, "Add route resolve name '%s' to connid %u", - symbolicOrConnid, connid); - } - - success = forwarder_AddOrUpdateRoute(config->forwarder, control, connid); + forwarder_t * forwarder = configuration_get_forwarder(config); + assert(forwarder); - } else { - if (logger_IsLoggable(config->logger, LoggerFacility_Config, - PARCLogLevel_Warning)) { - logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Warning, - __func__, - "Add route symbolic name '%s' could not be resolved", - symbolicOrConnid); - } - // failure - } - } + listener_table_t * table = forwarder_get_listener_table(forwarder); + assert(table); - // generate ACK/NACK - struct iovec *response; + /* Verify that the listener DOES NOT exist */ + listener_t * listener = listener_table_get_by_name(table, control->symbolic); + if (listener) + goto NACK; - if (success) { // ACK - response = utils_CreateAck(header, control, sizeof(add_route_command)); - } else { // NACK - response = utils_CreateNack(header, control, sizeof(add_route_command)); - } + address_t address; + if (address_from_ip_port(&address, control->family, &control->address, + control->port) < 0) { + WARN("Unsupported address type for HICN (ingress id %u): " + "must be either IPV4 or IPV6", ingress_id); + return false; + } - return response; -} + // NOTE: interface_name is expected NULL for hICN listener + face_type_t face_type; + if (!face_type_is_defined(control->listener_type)) + goto NACK; + face_type = (face_type_t)control->listener_type; -struct iovec *configuration_ProcessUnregisterHicnPrefix(Configuration *config, - struct iovec *request) { - header_control_message *header = request[0].iov_base; - remove_route_command *control = request[1].iov_base; - bool success = false; + listener = listener_create(face_type, &address, control->interface_name, control->symbolic, forwarder); + if (!listener) + goto NACK; - const char *symbolicOrConnid = control->symbolicOrConnid; + make_ack(msg); + return (uint8_t*)msg; - if (utils_IsNumber(symbolicOrConnid)) { - // case for connid as input - unsigned connid = (unsigned)strtold(symbolicOrConnid, NULL); - ConnectionTable *table = forwarder_GetConnectionTable(config->forwarder); +NACK: + make_ack(msg); + return (uint8_t*)msg; +} - // check if interface index present in the fwd table - if (connectionTable_FindById(table, connid)) { - success = forwarder_RemoveRoute(config->forwarder, control, connid); +uint8_t * +configuration_on_listener_remove(configuration_t * config, uint8_t * packet, + unsigned ingress_id) +{ + assert(config); + assert(packet); + + msg_listener_remove_t * msg = (msg_listener_remove_t*)packet; + cmd_listener_remove_t * control = &msg->payload; + + const char *symbolicOrListenerid = control->symbolicOrListenerid; + off_t listener_id; + listener_t * listener; + + listener_table_t * listener_table = forwarder_get_listener_table(config->forwarder); + + // Factor like for connections + if (utils_IsNumber(symbolicOrListenerid)) { + // XXX no check + int id = atoi(symbolicOrListenerid); + if (id < 0) + goto NACK; + listener_id = id; + + listener = listener_table_get_by_id(listener_table, listener_id); + if (!listener) { + ERROR("Listener Id not found, check list listeners"); + goto NACK; + } } else { - logger_Log(forwarder_GetLogger(config->forwarder), LoggerFacility_IO, - PARCLogLevel_Error, __func__, - "ConnID not found, check list connections"); - // failure + listener = listener_table_get_by_name(listener_table, symbolicOrListenerid); + listener_id = listener_table_get_listener_id(listener_table, listener); } - } else { - // case for symbolic as input: chech if symbolic name can be resolved - unsigned connid = - symbolicNameTable_Get(config->symbolicNameTable, symbolicOrConnid); - // connid = UINT_MAX when symbolicName is not found - if (connid != UINT32_MAX) { - if (logger_IsLoggable(config->logger, LoggerFacility_Config, - PARCLogLevel_Debug)) { - logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Debug, - __func__, "Remove route resolve name '%s' to connid %u", - symbolicOrConnid, connid); - } - success = forwarder_RemoveRoute(config->forwarder, control, connid); - } else { - if (logger_IsLoggable(config->logger, LoggerFacility_Config, - PARCLogLevel_Warning)) { - logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Warning, - __func__, - "Remove route symbolic name '%s' could not be resolved", - symbolicOrConnid); - } - // failure - } - } + connection_table_t * table = forwarder_get_connection_table(config->forwarder); + connection_t * connection; + connection_table_foreach(table, connection, { + const address_pair_t * pair = connection_get_pair(connection); + if (!address_equals(listener_get_address(listener), + address_pair_get_local(pair))) + continue; + + unsigned conn_id = connection_table_get_connection_id(table, connection); + /* Remove connection from the FIB */ + forwarder_remove_connection_id_from_routes(config->forwarder, conn_id); + + /* Remove connection */ + connection_table_remove_by_id(table, conn_id); + +#if 0 + const char *symbolicConnection = + symbolic_nameTable_GetNameByIndex(config->symbolic_nameTable, conn_id); + symbolic_nameTable_Remove(config->symbolic_nameTable, symbolicConnection); +#endif + }); - // generate ACK/NACK - struct iovec *response; + /* Remove listener */ + listener_table_remove_by_id(listener_table, listener_id); - if (success) { // ACK - response = utils_CreateAck(header, control, sizeof(remove_route_command)); - } else { // NACK - response = utils_CreateNack(header, control, sizeof(remove_route_command)); - } + make_ack(msg); + return (uint8_t*)msg; - return response; +NACK: + make_ack(msg); + return (uint8_t*)msg; } -struct iovec *configuration_ProcessRegistrationList(Configuration *config, - struct iovec *request) { - FibEntryList *fibList = forwarder_GetFibEntries(config->forwarder); - - size_t payloadSize = fibEntryList_Length(fibList); - size_t effective_payloadSize = 0; - size_t pointerLocation = 0; - struct sockaddr_in tmpAddr; - struct sockaddr_in6 tmpAddr6; - - // allocate payload, cast from void* to uint8_t* = bytes granularity - uint8_t *payloadResponse = - parcMemory_AllocateAndClear(sizeof(list_routes_command) * payloadSize); - - for (size_t i = 0; i < fibEntryList_Length(fibList); i++) { - FibEntry *entry = (FibEntry *)fibEntryList_Get(fibList, i); - NameBitvector *prefix = name_GetContentName(fibEntry_GetPrefix(entry)); - const NumberSet *nexthops = fibEntry_GetNexthops(entry); - - if (numberSet_Length(nexthops) == 0) - continue; - - if (numberSet_Length(nexthops) > 1) { - // payload extended, need reallocate, further entries via nexthops - payloadSize = payloadSize + numberSet_Length(nexthops) - 1; - payloadResponse = (uint8_t *) parcMemory_Reallocate( - payloadResponse, sizeof(list_routes_command) * payloadSize); +static inline +void +fill_listener_command(configuration_t * config, listener_t * listener, + cmd_listener_list_item_t * cmd) +{ + assert(config); + assert(listener); + assert(cmd); + + struct sockaddr_in * sin; + struct sockaddr_in6 * sin6; + + const address_t * addr = listener_get_address(listener); + + cmd->id = (uint32_t)listener_get_id(listener); + cmd->type = (uint8_t)listener_get_type(listener); + + switch(addr->ss_family) { + case AF_INET: + sin = (struct sockaddr_in *) addr; + cmd->family = AF_INET; + cmd->address.v4.as_inaddr = sin->sin_addr; + cmd->port = sin->sin_port; + break; + case AF_INET6: + sin6 = (struct sockaddr_in6 *) addr; + cmd->family = AF_INET6; + cmd->address.v6.as_in6addr = sin6->sin6_addr; + cmd->port = sin6->sin6_port; + break; + default: + break; } - for (size_t j = 0; j < numberSet_Length(nexthops); j++) { - list_routes_command *listRouteCommand = - (list_routes_command *)(payloadResponse + - (pointerLocation * - sizeof(list_routes_command))); - - Address *addressEntry = nameBitvector_ToAddress(prefix); - if (addressGetType(addressEntry) == ADDR_INET) { - addressGetInet(addressEntry, &tmpAddr); - listRouteCommand->addressType = ADDR_INET; - listRouteCommand->address.v4.as_inaddr = tmpAddr.sin_addr; - } else if (addressGetType(addressEntry) == ADDR_INET6) { - addressGetInet6(addressEntry, &tmpAddr6); - listRouteCommand->addressType = ADDR_INET6; - listRouteCommand->address.v6.as_in6addr = tmpAddr6.sin6_addr; - } - listRouteCommand->connid = numberSet_GetItem(nexthops, j); - listRouteCommand->len = nameBitvector_GetLength(prefix); - listRouteCommand->cost = 1; // cost - - pointerLocation++; - effective_payloadSize++; - addressDestroy(&addressEntry); - } - } + const char * name = listener_get_name(listener); + snprintf(cmd->name, SYMBOLIC_NAME_LEN, "%s", name); + const char * interface_name = listener_get_interface_name(listener); + snprintf(cmd->interface_name, SYMBOLIC_NAME_LEN, "%s", interface_name); +} - // send response - header_control_message *header = request[0].iov_base; - header->messageType = RESPONSE_LIGHT; - header->length = (unsigned)effective_payloadSize; +uint8_t * +configuration_on_listener_list(configuration_t * config, uint8_t * packet, + unsigned ingress_id) +{ + assert(config); + assert(packet); + + listener_table_t * table = forwarder_get_listener_table(config->forwarder); + size_t n = listener_table_len(table); - struct iovec *response = - parcMemory_AllocateAndClear(sizeof(struct iovec) * 2); + msg_listener_list_reply_t * msg; + msg_malloc_list(msg, n) + if (!msg) + return NULL; - response[0].iov_base = header; - response[0].iov_len = sizeof(header_control_message); - response[1].iov_base = payloadResponse; - response[1].iov_len = sizeof(list_routes_command) * effective_payloadSize; + cmd_listener_list_item_t * payload = &msg->payload; + listener_t * listener; + listener_table_foreach(table, listener, { + fill_listener_command(config, listener, payload); + payload++; + }); - fibEntryList_Destroy(&fibList); - return response; + return (uint8_t*)msg; } -static void configuration_SendResponse(Configuration *config, struct iovec *msg, - unsigned egressId) { - ConnectionTable *connectionTable = - forwarder_GetConnectionTable(config->forwarder); - const Connection *conn = connectionTable_FindById(connectionTable, egressId); +/* Connection */ - if (conn == NULL) { - return; - } - connection_SendIOVBuffer(conn, msg, 2); -} +uint8_t * +configuration_on_connection_add(configuration_t * config, uint8_t * packet, + unsigned ingress_id) +{ + assert(config); + assert(packet); -struct iovec *configuration_ProcessCreateTunnel(Configuration *config, - struct iovec *request) { - header_control_message *header = request[0].iov_base; - add_connection_command *control = request[1].iov_base; - - bool success = false; - - Connection *conn; - const char *symbolicName = control->symbolic; - - Address *source = NULL; - Address *destination = NULL; - - if (symbolicNameTable_Exists(config->symbolicNameTable, symbolicName)) { - logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Error, - __func__, "Connection symbolic name already exists"); - goto ERR; - } - - if (control->ipType == ADDR_INET) { - source = - addressFromInaddr4Port(&control->localIp.v4.as_u32, &control->localPort); - destination = - addressFromInaddr4Port(&control->remoteIp.v4.as_u32, &control->remotePort); - } else if (control->ipType == ADDR_INET6) { - source = - addressFromInaddr6Port(&control->localIp.v6.as_in6addr, &control->localPort); - destination = - addressFromInaddr6Port(&control->remoteIp.v6.as_in6addr, &control->remotePort); - } else { - printf("Invalid IP type.\n"); // will generate a Nack - } - - AddressPair *pair = addressPair_Create(source, destination); - conn = (Connection *)connectionTable_FindByAddressPair( - forwarder_GetConnectionTable(config->forwarder), pair); - - addressPair_Release(&pair); - - if (!conn) { - IoOperations *ops = NULL; - switch (control->connectionType) { - case TCP_CONN: - // logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Error, - // __func__, - // "Unsupported tunnel protocol: TCP"); - ops = tcpTunnel_Create(config->forwarder, source, destination); - break; - case UDP_CONN: - ops = udpTunnel_Create(config->forwarder, source, destination); - break; - case GRE_CONN: - logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Error, - __func__, "Unsupported tunnel protocol: GRE"); - break; -#if !defined(__APPLE__) && !defined(_WIN32) && defined(PUNTING) - case HICN_CONN: - ops = hicnTunnel_Create(config->forwarder, source, destination); - break; -#endif /* __APPLE__ _WIN32*/ - default: - logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Error, - __func__, "Unsupported tunnel protocol: %d", - control->connectionType); - break; - } + msg_connection_add_t * msg = (msg_connection_add_t*)packet; + cmd_connection_add_t * control = &msg->payload; - if (ops != NULL) { - Connection *conn = connection_Create(ops); -#ifdef WITH_POLICY - connection_SetTags(conn, control->tags); - connection_SetPriority(conn, control->priority); -#endif /* WITH_POLICY */ + const char *symbolic_name = control->symbolic; - connection_SetAdminState(conn, control->admin_state); + face_type_t face_type; + if (!face_type_is_defined(control->type)) + goto NACK; + face_type = (face_type_t)control->type; - connectionTable_Add(forwarder_GetConnectionTable(config->forwarder), - conn); - symbolicNameTable_Add(config->symbolicNameTable, symbolicName, - connection_GetConnectionId(conn)); + connection_table_t * table = forwarder_get_connection_table(config->forwarder); + if (connection_table_get_by_name(table, symbolic_name)) { + ERROR("Connection symbolic name already exists"); + goto NACK; + } + + address_pair_t pair; + if (address_pair_from_ip_port(&pair, control->family, + &control->local_ip, control->local_port, + &control->remote_ip, control->remote_port) < 0) + goto NACK; + connection_t * connection = connection_table_get_by_pair(table, &pair); #ifdef WITH_MAPME - /* Hook: new connection created through the control protocol */ - forwarder_onConnectionEvent(config->forwarder, conn, CONNECTION_EVENT_CREATE); + connection_event_t event; #endif /* WITH_MAPME */ - success = true; + if (!connection) { + connection = connection_create(face_type, symbolic_name, &pair, config->forwarder); + if (!connection) { + ERROR("Failed to create %s connection", + face_type_str(connection->type)); + goto NACK; + } - } else { - printf("failed, could not create IoOperations"); - } +#ifdef WITH_MAPME + event = CONNECTION_EVENT_CREATE; +#endif /* WITH_MAPME */ - } else { + } else { #ifdef WITH_POLICY - connection_SetTags(conn, control->tags); - connection_SetPriority(conn, control->priority); - connection_SetAdminState(conn, control->admin_state); - #ifdef WITH_MAPME - /* Hook: new connection created through the control protocol */ - forwarder_onConnectionEvent(config->forwarder, conn, CONNECTION_EVENT_UPDATE); + event = CONNECTION_EVENT_UPDATE; #endif /* WITH_MAPME */ - if (source) - addressDestroy(&source); - if (destination) - addressDestroy(&destination); - - success = true; #else - printf("failed, symbolic name or connection already exist\n"); + ERROR("failed, symbolic name or connection already exist\n"); + goto NACK; #endif /* WITH_POLICY */ - } - - if (source) - addressDestroy(&source); - if (destination) - addressDestroy(&destination); - - if (!success) - goto ERR; - - // ACK - return utils_CreateAck(header, control, sizeof(add_connection_command)); + } -ERR: - return utils_CreateNack(header, control, sizeof(add_connection_command)); -} +#ifdef WITH_POLICY + connection_set_tags(connection, control->tags); + connection_set_priority(connection, control->priority); +#endif /* WITH_POLICY */ -struct iovec *configuration_ProcessRemoveListener(Configuration *config, - struct iovec *request, - unsigned ingressId) { - header_control_message *header = request[0].iov_base; - remove_listener_command *control = request[1].iov_base; - - bool success = false; - - const char *symbolicOrListenerid = control->symbolicOrListenerid; - int listenerId = -1; - ListenerSet *listenerSet = forwarder_GetListenerSet(config->forwarder); - if (utils_IsNumber(symbolicOrListenerid)) { - // case for connid as input - listenerId = (unsigned)strtold(symbolicOrListenerid, NULL); - } else { - listenerId = listenerSet_FindIdByListenerName(listenerSet, symbolicOrListenerid); - } - - if (listenerId >= 0) { - - ConnectionTable *connTable = forwarder_GetConnectionTable(config->forwarder); - ListenerOps *listenerOps = listenerSet_FindById(listenerSet, listenerId); - if (listenerOps) { - ConnectionList *connectionList = connectionTable_GetEntries(connTable); - for (size_t i = 0; i < connectionList_Length(connectionList); i++) { - Connection *connection = connectionList_Get(connectionList, i); - const AddressPair *addressPair = connection_GetAddressPair(connection); - const Address *address = addressPair_GetLocal(addressPair); - if (addressEquals(listenerOps->getListenAddress(listenerOps),address)) { - // case for connid as input - unsigned connid = connection_GetConnectionId(connection); - // remove connection from the FIB - forwarder_RemoveConnectionIdFromRoutes(config->forwarder, connid); - // remove connection - connectionTable_RemoveById(connTable, connid); - const char *symbolicConnection = symbolicNameTable_GetNameByIndex(config->symbolicNameTable,connid); - symbolicNameTable_Remove(config->symbolicNameTable, symbolicConnection); - } - } - connectionList_Destroy(&connectionList); - // remove listener - listenerSet_RemoveById(listenerSet, listenerId); - success = true; - } else { - logger_Log(forwarder_GetLogger(config->forwarder), LoggerFacility_IO, - PARCLogLevel_Error, __func__, - "Listener Id not found, check list listeners"); - } - } + connection_set_admin_state(connection, control->admin_state); - // generate ACK/NACK - struct iovec *response; +#ifdef WITH_MAPME + /* Hook: new connection created through the control protocol */ + forwarder_on_connection_event(config->forwarder, connection, event); +#endif /* WITH_MAPME */ - if (success) { // ACK - response = - utils_CreateAck(header, control, sizeof(remove_listener_command)); - } else { // NACK - response = - utils_CreateNack(header, control, sizeof(remove_connection_command)); - } + make_ack(msg); + return (uint8_t*)msg; - return response; +NACK: + make_ack(msg); + return (uint8_t*)msg; } /** * Add an IP-based tunnel. * - * The call cal fail if the symbolic name is a duplicate. It could also fail if + * The call can fail if the symbolic name is a duplicate. It could also fail if * there's an problem creating the local side of the tunnel (i.e. the local * socket address is not usable). * @@ -558,952 +451,966 @@ struct iovec *configuration_ProcessRemoveListener(Configuration *config, * @return false Tunnel not added (an error) */ -struct iovec *configuration_ProcessRemoveTunnel(Configuration *config, - struct iovec *request, - unsigned ingressId) { - header_control_message *header = request[0].iov_base; - remove_connection_command *control = request[1].iov_base; +uint8_t * +configuration_on_connection_remove(configuration_t * config, uint8_t * packet, + unsigned ingress_id) +{ + assert(config); + assert(packet); - bool success = false; + msg_connection_remove_t * msg = (msg_connection_remove_t*)packet; + cmd_connection_remove_t * control = &msg->payload; - const char *symbolicOrConnid = control->symbolicOrConnid; - ConnectionTable *table = forwarder_GetConnectionTable(config->forwarder); - if (strcmp(symbolicOrConnid, "SELF") == 0) { - forwarder_RemoveConnectionIdFromRoutes(config->forwarder, ingressId); - connectionTable_RemoveById(table, ingressId); + unsigned conn_id = symbolic_to_conn_id_self(config, control->symbolicOrConnid, + ingress_id); + if (!connection_id_is_valid(conn_id)) + goto NACK; -#ifdef WITH_MAPME - /* Hook: new connection created through the control protocol */ - forwarder_onConnectionEvent(config->forwarder, NULL, CONNECTION_EVENT_DELETE); -#endif /* WITH_MAPME */ + /* Remove connection from the FIB */ + forwarder_remove_connection_id_from_routes(config->forwarder, conn_id); - success = true; - } else if (utils_IsNumber(symbolicOrConnid)) { - // case for connid as input - unsigned connid = (unsigned)strtold(symbolicOrConnid, NULL); - - // check if interface index present in the fwd table - //(it was missing and therefore caused a program crash) - if (connectionTable_FindById(table, connid)) { - // remove connection from the FIB - forwarder_RemoveConnectionIdFromRoutes(config->forwarder, connid); - // remove connection - connectionTable_RemoveById(table, connid); - // remove connection from symbolicNameTable - const char *symbolicConnection = symbolicNameTable_GetNameByIndex(config->symbolicNameTable,connid); - symbolicNameTable_Remove(config->symbolicNameTable, symbolicConnection); + /* Remove connection */ + connection_table_t *table = forwarder_get_connection_table(config->forwarder); + connection_table_remove_by_id(table, conn_id); + +#if 0 + /* Remove connection from symbolic_nameTable */ + const char *symbolicConnection = symbolic_nameTable_GetNameByIndex(config->symbolic_nameTable, conn_id); + symbolic_nameTable_Remove(config->symbolic_nameTable, symbolicConnection); +#endif #ifdef WITH_MAPME - /* Hook: new connection created through the control protocol */ - forwarder_onConnectionEvent(config->forwarder, NULL, CONNECTION_EVENT_DELETE); + /* Hook: new connection created through the control protocol */ + forwarder_on_connection_event(config->forwarder, NULL, CONNECTION_EVENT_DELETE); #endif /* WITH_MAPME */ - success = true; - } else { - logger_Log(forwarder_GetLogger(config->forwarder), LoggerFacility_IO, - PARCLogLevel_Error, __func__, - "ConnID not found, check list connections"); - // failure - } + make_ack(msg); + return (uint8_t*)msg; - } else { - // case for symbolic as input - // chech if symbolic name can be resolved - unsigned connid = - symbolicNameTable_Get(config->symbolicNameTable, symbolicOrConnid); - // connid = UINT_MAX when symbolicName is not found - if (connid != UINT32_MAX) { - if (logger_IsLoggable(config->logger, LoggerFacility_Config, - PARCLogLevel_Debug)) { - logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Debug, - __func__, "Remove connection resolve name '%s' to connid %u", - symbolicOrConnid, connid); - } - - // remove connection from the FIB - forwarder_RemoveConnectionIdFromRoutes(config->forwarder, connid); - // remove connection - connectionTable_RemoveById(table, connid); - // remove connection from symbolicNameTable since we have symbolic input - symbolicNameTable_Remove(config->symbolicNameTable, symbolicOrConnid); +NACK: + make_ack(msg); + return (uint8_t*)msg; +} -#ifdef WITH_MAPME - /* Hook: new connection created through the control protocol */ - forwarder_onConnectionEvent(config->forwarder, NULL, CONNECTION_EVENT_DELETE); -#endif /* WITH_MAPME */ +static inline +void +tolower_str(char * str) { + char * p = str; + for (; *p; p++) + *p = tolower(*p); +} - success = true; // to write - } else { - if (logger_IsLoggable(config->logger, LoggerFacility_Config, - PARCLogLevel_Warning)) { - logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Error, - __func__, - "Remove connection symbolic name '%s' could not be resolved", - symbolicOrConnid); - } - // failure - } - } +static inline +void +fill_connections_command(configuration_t * config, connection_t * connection, + cmd_connection_list_item_t * cmd) +{ + assert(config); + assert(connection); + assert(cmd); + struct sockaddr_in * sin; + struct sockaddr_in6 * sin6; + const address_pair_t * pair = connection_get_pair(connection); +#if 0 + const char *name = symbolic_nameTable_GetNameByIndex(config->symbolic_nameTable, + connection_get_id(connection)); +#endif + + *cmd = (cmd_connection_list_item_t) { + .id = connection_get_id(connection), + .state = connection_get_state(connection), + .admin_state = connection_get_admin_state(connection), + .type = connection_get_type(connection), +#ifdef WITH_POLICY + .priority = connection_get_priority(connection), + .tags = connection_get_tags(connection), +#endif /* WITH_POLICY */ + }; + + snprintf(cmd->name, SYMBOLIC_NAME_LEN, "%s", connection_get_name(connection)); + tolower_str(cmd->name); + + snprintf(cmd->interface_name, SYMBOLIC_NAME_LEN, "%s", + connection_get_interface_name(connection)); + + switch(pair->local.ss_family) { + case AF_INET: + cmd->family = AF_INET; + + sin = (struct sockaddr_in *)(&pair->local); + cmd->local_port = sin->sin_port; + cmd->local_ip.v4.as_inaddr = sin->sin_addr; - // generate ACK/NACK - struct iovec *response; + sin = (struct sockaddr_in *)(&pair->remote); + cmd->remote_port = sin->sin_port; + cmd->remote_ip.v4.as_inaddr = sin->sin_addr; + break; - if (success) { // ACK - response = - utils_CreateAck(header, control, sizeof(remove_connection_command)); - } else { // NACK - response = - utils_CreateNack(header, control, sizeof(remove_connection_command)); - } + case AF_INET6: + cmd->family = AF_INET6; - return response; + sin6 = (struct sockaddr_in6 *)(&pair->local); + cmd->local_port = sin6->sin6_port; + cmd->local_ip.v6.as_in6addr = sin6->sin6_addr; + + sin6 = (struct sockaddr_in6 *)(&pair->remote); + cmd->remote_port = sin6->sin6_port; + cmd->remote_ip.v6.as_in6addr = sin6->sin6_addr; + break; + + default: + break; + } } -void _parc_strlwr(char *string) { - char *p = string; - while ((*p = tolower(*p))) { - p++; - } +uint8_t * +configuration_on_connection_list(configuration_t * config, uint8_t * packet, + unsigned ingress_id) +{ + assert(config); + assert(packet); + + connection_table_t *table = forwarder_get_connection_table(config->forwarder); + size_t n = connection_table_len(table); + + msg_connection_list_reply_t * msg; + msg_malloc_list(msg, n) + if (!msg) + return NULL; + + cmd_connection_list_item_t * payload = &msg->payload; + connection_t * connection; + connection_table_foreach(table, connection, { + fill_connections_command(config, connection, payload); + payload++; + }); + + return (uint8_t*)msg; } -struct iovec *configuration_ProcessConnectionList(Configuration *config, - struct iovec *request) { - ConnectionTable *table = forwarder_GetConnectionTable(config->forwarder); - ConnectionList *connList = connectionTable_GetEntries(table); - struct sockaddr_in tmpAddr; - struct sockaddr_in6 tmpAddr6; +uint8_t * +configuration_on_connection_set_admin_state(configuration_t * config, + uint8_t * packet, unsigned ingress_id) +{ + assert(config); + assert(packet); - // allocate payload, cast from void* to uint8_t* fot bytes granularity - uint8_t *payloadResponse = parcMemory_AllocateAndClear( - sizeof(list_connections_command) * connectionList_Length(connList)); + msg_connection_set_admin_state_t * msg = (msg_connection_set_admin_state_t *)packet; + cmd_connection_set_admin_state_t *control = &msg->payload; - for (size_t i = 0; i < connectionList_Length(connList); i++) { - // Don't release original, it is not stored - Connection *original = connectionList_Get(connList, i); + if ((control->admin_state != FACE_STATE_UP) && + (control->admin_state != FACE_STATE_DOWN)) + goto NACK; - const AddressPair *addressPair = connection_GetAddressPair(original); - Address *localAddress = addressCopy(addressPair_GetLocal(addressPair)); - Address *remoteAddress = addressCopy(addressPair_GetRemote(addressPair)); + connection_t * conn = getConnectionBySymbolicOrId(config, control->symbolicOrConnid); + if (!conn) + goto NACK; - // Fill payload by shifting and casting at each 'i' step. - list_connections_command *listConnectionsCommand = - (list_connections_command *)(payloadResponse + - (i * sizeof(list_connections_command))); - // set structure fields + connection_set_admin_state(conn, control->admin_state); - listConnectionsCommand->connid = connection_GetConnectionId(original); +#ifdef WITH_MAPME + /* Hook: connection event */ + forwarder_on_connection_event(config->forwarder, conn, + control->admin_state == FACE_STATE_UP + ? CONNECTION_EVENT_SET_UP + : CONNECTION_EVENT_SET_DOWN); +#endif /* WITH_MAPME */ - const char *connectionName = symbolicNameTable_GetNameByIndex(config->symbolicNameTable, connection_GetConnectionId(original)); - snprintf(listConnectionsCommand->connectionName, SYMBOLIC_NAME_LEN, "%s", connectionName); - _parc_strlwr(listConnectionsCommand->connectionName); + make_ack(msg); + return (uint8_t*)msg; - snprintf(listConnectionsCommand->interfaceName, SYMBOLIC_NAME_LEN, "%s", ioOperations_GetInterfaceName(connection_GetIoOperations(original))); +NACK: + make_ack(msg); + return (uint8_t*)msg; +} - listConnectionsCommand->state = - connection_IsUp(original) ? IFACE_UP : IFACE_DOWN; - listConnectionsCommand->connectionData.admin_state = - (connection_GetAdminState(original) == CONNECTION_STATE_UP) ? IFACE_UP : IFACE_DOWN; - listConnectionsCommand->connectionData.connectionType = - ioOperations_GetConnectionType(connection_GetIoOperations(original)); - listConnectionsCommand->connectionData.admin_state = connection_GetAdminState(original); +uint8_t * +configuration_on_connection_update(configuration_t * config, uint8_t * packet, + unsigned ingress_id) +{ + assert(config); + assert(packet); #ifdef WITH_POLICY - listConnectionsCommand->connectionData.priority = connection_GetPriority(original); - listConnectionsCommand->connectionData.tags = connection_GetTags(original); -#endif /* WITH_POLICY */ + msg_connection_update_t * msg = (msg_connection_update_t *)packet; + cmd_connection_update_t * control = &msg->payload; + + connection_t * conn = getConnectionBySymbolicOrId(config, control->symbolicOrConnid); + if (!conn) + goto NACK; + + connection_set_tags(conn, control->tags); + connection_set_admin_state(conn, control->admin_state); + if (control->priority > 0) + connection_set_priority(conn, control->priority); - if (addressGetType(localAddress) == ADDR_INET && - addressGetType(remoteAddress) == ADDR_INET) { - listConnectionsCommand->connectionData.ipType = ADDR_INET; - - // get local port/address - addressGetInet(localAddress, &tmpAddr); - listConnectionsCommand->connectionData.localPort = tmpAddr.sin_port; - listConnectionsCommand->connectionData.localIp.v4.as_inaddr = - tmpAddr.sin_addr; - memset(&tmpAddr, 0, sizeof(tmpAddr)); - // get remote port/address - addressGetInet(remoteAddress, &tmpAddr); - listConnectionsCommand->connectionData.remotePort = tmpAddr.sin_port; - listConnectionsCommand->connectionData.remoteIp.v4.as_inaddr = - tmpAddr.sin_addr; - - } else if (addressGetType(localAddress) == ADDR_INET6 && - addressGetType(remoteAddress) == ADDR_INET6) { - listConnectionsCommand->connectionData.ipType = ADDR_INET6; - - // get local port/address - addressGetInet6(localAddress, &tmpAddr6); - listConnectionsCommand->connectionData.localPort = tmpAddr6.sin6_port; - listConnectionsCommand->connectionData.localIp.v6.as_in6addr = tmpAddr6.sin6_addr; - memset(&tmpAddr6, 0, sizeof(tmpAddr6)); - // get remote port/address - addressGetInet6(remoteAddress, &tmpAddr6); - listConnectionsCommand->connectionData.remotePort = tmpAddr6.sin6_port; - listConnectionsCommand->connectionData.remoteIp.v6.as_in6addr = tmpAddr6.sin6_addr; - - } // no need further else, control on the addressed already done at the - // time of insertion in the connection table - addressDestroy(&localAddress); - addressDestroy(&remoteAddress); - } - - // send response - header_control_message *header = request[0].iov_base; - header->messageType = RESPONSE_LIGHT; - header->length = (uint16_t)connectionList_Length(connList); - - struct iovec *response = - parcMemory_AllocateAndClear(sizeof(struct iovec) * 2); - - response[0].iov_base = header; - response[0].iov_len = sizeof(header_control_message); - response[1].iov_base = payloadResponse; - response[1].iov_len = - sizeof(list_connections_command) * connectionList_Length(connList); - - connectionList_Destroy(&connList); - return response; + make_ack(msg); + return (uint8_t*)msg; + +NACK: +#endif /* WITH_POLICY */ + make_ack(msg); + return (uint8_t*)msg; } -struct iovec *configuration_ProcessListenersList(Configuration *config, - struct iovec *request) { - ListenerSet *listenerList = forwarder_GetListenerSet(config->forwarder); - struct sockaddr_in tmpAddr; - struct sockaddr_in6 tmpAddr6; - - // allocate payload, cast from void* to uint8_t* fot bytes granularity - uint8_t *payloadResponse = parcMemory_AllocateAndClear( - sizeof(list_listeners_command) * listenerSet_Length(listenerList)); - - for (size_t i = 0; i < listenerSet_Length(listenerList); i++) { - ListenerOps *listenerEntry = listenerSet_Get(listenerList, i); - - // Fill payload by shifting and casting at each 'i' step. - list_listeners_command *listListenersCommand = - (list_listeners_command *)(payloadResponse + - (i * sizeof(list_listeners_command))); - - listListenersCommand->connid = - (uint32_t)listenerEntry->getInterfaceIndex(listenerEntry); - listListenersCommand->encapType = - (uint8_t)listenerEntry->getEncapType(listenerEntry); - if (addressGetType((const Address *)listenerEntry->getListenAddress( - listenerEntry)) == ADDR_INET) { - addressGetInet( - (const Address *)listenerEntry->getListenAddress(listenerEntry), - &tmpAddr); - listListenersCommand->addressType = ADDR_INET; - listListenersCommand->address.v4.as_inaddr = tmpAddr.sin_addr; - listListenersCommand->port = tmpAddr.sin_port; - } else if (addressGetType((const Address *)listenerEntry->getListenAddress( - listenerEntry)) == ADDR_INET6) { - addressGetInet6( - (const Address *)listenerEntry->getListenAddress(listenerEntry), - &tmpAddr6); - listListenersCommand->addressType = ADDR_INET6; - listListenersCommand->address.v6.as_in6addr = tmpAddr6.sin6_addr; - listListenersCommand->port = tmpAddr6.sin6_port; - } +uint8_t * +configuration_on_connection_set_priority(configuration_t * config, + uint8_t * packet, unsigned ingress_id) +{ + assert(config); + assert(packet); - const char * listenerName = listenerEntry->getListenerName(listenerEntry); - snprintf(listListenersCommand->listenerName, SYMBOLIC_NAME_LEN, "%s", listenerName); - if (listenerEntry->getEncapType(listenerEntry) == ENCAP_TCP || - listenerEntry->getEncapType(listenerEntry) == ENCAP_UDP) { - const char * interfaceName = listenerEntry->getInterfaceName(listenerEntry); - snprintf(listListenersCommand->interfaceName, SYMBOLIC_NAME_LEN, "%s", interfaceName); - } - } +#ifdef WITH_POLICY + msg_connection_set_priority_t * msg = (msg_connection_set_priority_t *)packet; + cmd_connection_set_priority_t * control = &msg->payload; - // send response - header_control_message *header = request[0].iov_base; - header->messageType = RESPONSE_LIGHT; - header->length = (uint16_t)listenerSet_Length(listenerList); + connection_t * conn = getConnectionBySymbolicOrId(config, control->symbolicOrConnid); + if (!conn) + goto NACK; - struct iovec *response = - parcMemory_AllocateAndClear(sizeof(struct iovec) * 2); + connection_set_priority(conn, control->priority); - response[0].iov_base = header; - response[0].iov_len = sizeof(header_control_message); - response[1].iov_base = payloadResponse; - response[1].iov_len = - sizeof(list_listeners_command) * listenerSet_Length(listenerList); +#ifdef WITH_MAPME + /* Hook: connection event */ + forwarder_on_connection_event(config->forwarder, conn, + CONNECTION_EVENT_PRIORITY_CHANGED); +#endif /* WITH_MAPME */ - return response; -} + make_ack(msg); + return (uint8_t*)msg; -struct iovec *configuration_ProcessCacheStore(Configuration *config, - struct iovec *request) { - header_control_message *header = request[0].iov_base; - ; - cache_store_command *control = request[1].iov_base; - ; - - bool success = false; - - switch (control->activate) { - case ACTIVATE_ON: - forwarder_SetChacheStoreFlag(config->forwarder, true); - if (forwarder_GetChacheStoreFlag(config->forwarder)) { - success = true; - } - break; - - case ACTIVATE_OFF: - forwarder_SetChacheStoreFlag(config->forwarder, false); - if (!forwarder_GetChacheStoreFlag(config->forwarder)) { - success = true; - } - break; - - default: - break; - } - - struct iovec *response; - if (success) { // ACK - response = utils_CreateAck(header, control, sizeof(cache_store_command)); - } else { // NACK - response = utils_CreateNack(header, control, sizeof(cache_store_command)); - } - - return response; +NACK: +#endif /* WITH_POLICY */ + make_ack(msg); + return (uint8_t*)msg; } -struct iovec *configuration_ProcessCacheServe(Configuration *config, - struct iovec *request) { - header_control_message *header = request[0].iov_base; - cache_serve_command *control = request[1].iov_base; - - bool success = false; - - switch (control->activate) { - case ACTIVATE_ON: - forwarder_SetChacheServeFlag(config->forwarder, true); - if (forwarder_GetChacheServeFlag(config->forwarder)) { - success = true; - } - break; - - case ACTIVATE_OFF: - forwarder_SetChacheServeFlag(config->forwarder, false); - if (!forwarder_GetChacheServeFlag(config->forwarder)) { - success = true; - } - break; - - default: - break; - } - - struct iovec *response; - if (success) { // ACK - response = utils_CreateAck(header, control, sizeof(cache_store_command)); - } else { // NACK - response = utils_CreateNack(header, control, sizeof(cache_store_command)); - } - - return response; -} +uint8_t * +configuration_on_connection_set_tags(configuration_t * config, uint8_t * packet, + unsigned ingress_id) +{ + assert(config); + assert(packet); + +#ifdef WITH_POLICY + msg_connection_set_tags_t * msg = (msg_connection_set_tags_t *)packet; + cmd_connection_set_tags_t * control = &msg->payload; -struct iovec *configuration_ProcessCacheClear(Configuration *config, - struct iovec *request) { - header_control_message *header = request[0].iov_base; + connection_t * conn = getConnectionBySymbolicOrId(config, control->symbolicOrConnid); + if (!conn) + goto NACK; - forwarder_ClearCache(config->forwarder); + connection_set_tags(conn, control->tags); - struct iovec *response = utils_CreateAck(header, NULL, 0); - return response; -} +#ifdef WITH_MAPME + /* Hook: connection event */ + forwarder_on_connection_event(config->forwarder, conn, + CONNECTION_EVENT_TAGS_CHANGED); +#endif /* WITH_MAPME */ -size_t configuration_GetObjectStoreSize(Configuration *config) { - return config->maximumContentObjectStoreSize; + make_ack(msg); + return (uint8_t*)msg; + +NACK: +#endif /* WITH_POLICY */ + make_ack(msg); + return (uint8_t*)msg; } -void _configuration_StoreFwdStrategy(Configuration *config, const char *prefix, - strategy_type strategy) { - PARCString *prefixStr = parcString_Create(prefix); - PARCUnsigned *strategyValue = parcUnsigned_Create((unsigned)strategy); - parcHashMap_Put(config->strategy_map, prefixStr, strategyValue); - parcUnsigned_Release(&strategyValue); - parcString_Release(&prefixStr); + +/* Route */ + +uint8_t * +configuration_on_route_add(configuration_t * config, uint8_t * packet, + unsigned ingress_id) +{ + assert(config); + assert(packet); + + msg_route_add_t * msg = (msg_route_add_t *)packet; + cmd_route_add_t * control = &msg->payload; + + unsigned conn_id = symbolic_to_conn_id_self(config, + control->symbolicOrConnid, ingress_id); + if (!connection_id_is_valid(conn_id)) + goto NACK; + + ip_prefix_t prefix = { + .family = control->family, + .address = control->address, + .len = control->len + }; + + if (!forwarder_add_or_update_route(config->forwarder, &prefix, conn_id)) + goto NACK; + + make_ack(msg); + return (uint8_t*)msg; + +NACK: + make_ack(msg); + return (uint8_t*)msg; } -struct iovec *configuration_SetWldr(Configuration *config, - struct iovec *request) { - header_control_message *header = request[0].iov_base; - set_wldr_command *control = request[1].iov_base; - ConnectionTable *table = forwarder_GetConnectionTable(config->forwarder); - Connection *conn = NULL; - bool success = false; - - const char *symbolicOrConnid = control->symbolicOrConnid; - - if (utils_IsNumber(symbolicOrConnid)) { - // case for connid as input: check if connID present in the fwd table - conn = (Connection *)connectionTable_FindById( - table, (unsigned)strtold(symbolicOrConnid, NULL)); - if (conn) { - success = true; - } else { - logger_Log(forwarder_GetLogger(config->forwarder), LoggerFacility_IO, - PARCLogLevel_Error, __func__, - "ConnID not found, check list connections"); // failure - } - } else { - // case for symbolic as input: check if symbolic name can be resolved - unsigned connid = - symbolicNameTable_Get(config->symbolicNameTable, symbolicOrConnid); - if (connid != UINT32_MAX) { - conn = (Connection *)connectionTable_FindById(table, connid); - if (conn) { - if (logger_IsLoggable(config->logger, LoggerFacility_Config, - PARCLogLevel_Debug)) { - logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Debug, - __func__, "Set wldr resolve name '%s' to connid %u", - symbolicOrConnid, connid); - } - success = true; - } - } else { - if (logger_IsLoggable(config->logger, LoggerFacility_Config, - PARCLogLevel_Warning)) { - logger_Log(config->logger, LoggerFacility_Config, PARCLogLevel_Error, - __func__, "Symbolic name '%s' could not be resolved", - symbolicOrConnid); - } // failure - } - } - - // generate ACK/NACK - struct iovec *response; - - if (success) { - switch (control->activate) { - case ACTIVATE_ON: - connection_EnableWldr(conn); - response = utils_CreateAck(header, control, sizeof(set_wldr_command)); - break; - - case ACTIVATE_OFF: - connection_DisableWldr(conn); - response = utils_CreateAck(header, control, sizeof(set_wldr_command)); - break; - - default: // received wrong value - response = utils_CreateNack(header, control, sizeof(set_wldr_command)); - break; - } - } else { - response = utils_CreateNack(header, control, sizeof(set_wldr_command)); - } +uint8_t * +configuration_on_route_remove(configuration_t * config, uint8_t * packet, + unsigned ingress_id) +{ + assert(config); + assert(packet); + + msg_route_remove_t * msg = (msg_route_remove_t *)packet; + cmd_route_remove_t * control = &msg->payload; + + unsigned conn_id = symbolic_to_conn_id(config, control->symbolicOrConnid); + if (!connection_id_is_valid(conn_id)) + goto NACK; + + ip_prefix_t prefix = { + .family = control->family, + .address = control->address, + .len = control->len + }; + + if (!forwarder_remove_route(config->forwarder, &prefix, conn_id)) + goto NACK; - return response; + make_ack(msg); + return (uint8_t*)msg; + +NACK: + make_ack(msg); + return (uint8_t*)msg; } -strategy_type configuration_GetForwardingStrategy(Configuration *config, - const char *prefix) { - PARCString *prefixStr = parcString_Create(prefix); - const unsigned *val = parcHashMap_Get(config->strategy_map, prefixStr); - parcString_Release(&prefixStr); - - if (val == NULL) { - return LAST_STRATEGY_VALUE; - } else { - return (strategy_type)*val; - } +uint8_t * +configuration_on_route_list(configuration_t * config, uint8_t * packet, + unsigned ingress_id) +{ + assert(config); + assert(packet); + + const fib_t * fib = forwarder_get_fib(config->forwarder); + fib_entry_t * entry; + + /* + * Two step approach to precompute the number of entries to allocate + * + * NOTE: we might have routes with no or multiple next hops. + */ + size_t n = 0; + fib_foreach_entry(fib, entry, { + const nexthops_t * nexthops = fib_entry_get_nexthops(entry); + assert(nexthops_get_len(nexthops) == nexthops_get_curlen(nexthops)); + n += nexthops_get_len(nexthops); + }); + + msg_route_list_reply_t * msg; + msg_malloc_list(msg, n); + if (!msg) + return NULL; + + cmd_route_list_item_t * payload = &msg->payload; + fib_foreach_entry(fib, entry, { + const nexthops_t * nexthops = fib_entry_get_nexthops(entry); + assert(nexthops_get_len(nexthops) == nexthops_get_curlen(nexthops)); + size_t num_nexthops = nexthops_get_len(nexthops); + + if (num_nexthops == 0) + continue; + + NameBitvector *prefix = name_GetContentName(fib_entry_get_prefix(entry)); + + unsigned nexthop; + nexthops_foreach(nexthops, nexthop, { + + address_t address; + nameBitvector_ToAddress(prefix, &address); + switch(address_family(&address)) { + case AF_INET: + payload->family = AF_INET; + payload->address.v4.as_inaddr = address4_ip(&address); + break; + case AF_INET6: + payload->family = AF_INET6; + payload->address.v6.as_in6addr = address6_ip(&address); + break; + default: + break; + } + payload->connection_id = nexthop; + payload->len = nameBitvector_GetLength(prefix); + payload->cost = DEFAULT_COST; + + payload++; + }); + }); + + return (uint8_t*)msg; } -struct iovec *configuration_SetForwardingStrategy(Configuration *config, - struct iovec *request) { - header_control_message *header = request[0].iov_base; - set_strategy_command *control = request[1].iov_base; - - const char *prefix = utils_PrefixLenToString( - control->addressType, &control->address, &control->len); - strategy_type strategy = control->strategyType; - strategy_type existingFwdStrategy = - configuration_GetForwardingStrategy(config, prefix); - - if (existingFwdStrategy == LAST_STRATEGY_VALUE || - strategy != existingFwdStrategy) { - // means such a new strategy is not present in the hash table or has to be - // updated - _configuration_StoreFwdStrategy(config, prefix, strategy); - Name *hicnPrefix = name_CreateFromAddress(control->addressType, - control->address, control->len); - Name *related_prefixes[MAX_FWD_STRATEGY_RELATED_PREFIXES]; - if(control->related_prefixes != 0){ - for(int i = 0; i < control->related_prefixes; i++){ - related_prefixes[i] = name_CreateFromAddress( - control->addresses_type[i], - control->addresses[i], control->lens[i]); - } - } - forwarder_SetStrategy(config->forwarder, hicnPrefix, strategy, - control->related_prefixes, related_prefixes); - name_Release(&hicnPrefix); - if(control->related_prefixes != 0){ - for(int i = 0; i < control->related_prefixes; i++){ - name_Release(&related_prefixes[i]); - } - } - } - free((char *) prefix); - struct iovec *response = - utils_CreateAck(header, control, sizeof(set_strategy_command)); +/* Cache */ - return response; -} +uint8_t * +configuration_on_cache_set_store(configuration_t * config, uint8_t * packet, + unsigned ingress_id) +{ + assert(config); + assert(packet); + + msg_cache_set_store_t * msg = (msg_cache_set_store_t *)packet; + cmd_cache_set_store_t * control = &msg->payload; + + if ((control->activate != 0) && (control->activate != 1)) + goto NACK; + bool value = (bool)control->activate; -void configuration_SetObjectStoreSize(Configuration *config, - size_t maximumObjectCount) { - config->maximumContentObjectStoreSize = maximumObjectCount; + forwarder_content_store_set_store(config->forwarder, value); + /* XXX Why do we need to check ? */ + if (forwarder_content_store_get_store(config->forwarder) != value) + goto NACK; - forwarder_SetContentObjectStoreSize(config->forwarder, - config->maximumContentObjectStoreSize); + make_ack(msg); + return (uint8_t*)msg; + +NACK: + make_ack(msg); + return (uint8_t*)msg; } -Forwarder *configuration_GetForwarder(const Configuration *config) { - return config->forwarder; +uint8_t * +configuration_on_cache_set_serve(configuration_t * config, uint8_t * packet, + unsigned ingress_id) +{ + assert(config); + assert(packet); + + msg_cache_set_serve_t * msg = (msg_cache_set_serve_t *)packet; + cmd_cache_set_serve_t * control = &msg->payload; + + if ((control->activate != 0) && (control->activate != 1)) + goto NACK; + bool value = (bool)control->activate; + + forwarder_content_store_set_serve(config->forwarder, value); + /* XXX Why do we need to check ? */ + if (forwarder_content_store_get_serve(config->forwarder) != value) + goto NACK; + + make_ack(msg); + return (uint8_t*)msg; + +NACK: + make_ack(msg); + return (uint8_t*)msg; } -Logger *configuration_GetLogger(const Configuration *config) { - return config->logger; +uint8_t * +configuration_on_cache_clear(configuration_t * config, uint8_t * packet, + unsigned ingress_id) +{ + assert(config); + assert(packet); + + msg_cache_clear_t * msg = (msg_cache_clear_t *)packet; + + forwarder_content_store_clear(config->forwarder); + + make_ack(msg); + return (uint8_t*)msg; } -struct iovec *configuration_MapMeEnable(Configuration *config, - struct iovec *request) { - header_control_message *header = request[0].iov_base; - mapme_activator_command *control = request[1].iov_base; - const char *stateString[2] = {"on", "off"}; - - PARCBufferComposer *composer = parcBufferComposer_Create(); - parcBufferComposer_Format(composer, - "The mapme enable setting received is: %s", - stateString[control->activate]); - - PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer); - char *result = parcBuffer_ToString(tempBuffer); - parcBuffer_Release(&tempBuffer); - puts(result); - parcMemory_Deallocate((void **)&result); - parcBufferComposer_Release(&composer); - - return utils_CreateAck(header, control, sizeof(mapme_timing_command)); +/* Strategy */ + +strategy_type_t +configuration_get_strategy(configuration_t * config, const char *prefix) +{ + khiter_t k = kh_get_strategy_map(config->strategy_map, prefix); + if (k == kh_end(config->strategy_map)) + return STRATEGY_TYPE_UNDEFINED; + return kh_val(config->strategy_map, k); } -struct iovec *configuration_MapMeDiscovery(Configuration *config, - struct iovec *request) { - header_control_message *header = request[0].iov_base; - mapme_activator_command *control = request[1].iov_base; - const char *stateString[2] = {"on", "off"}; - - PARCBufferComposer *composer = parcBufferComposer_Create(); - parcBufferComposer_Format(composer, - "The mapme discovery setting received is: %s", - stateString[control->activate]); - - PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer); - char *result = parcBuffer_ToString(tempBuffer); - parcBuffer_Release(&tempBuffer); - puts(result); - parcMemory_Deallocate((void **)&result); - parcBufferComposer_Release(&composer); - - return utils_CreateAck(header, control, sizeof(mapme_timing_command)); +uint8_t * +configuration_on_strategy_set(configuration_t * config, uint8_t * packet, + unsigned ingress_id) +{ + assert(config); + assert(packet); + + msg_strategy_set_t * msg = (msg_strategy_set_t *)packet; + cmd_strategy_set_t * control = &msg->payload; + + char prefix_s[MAXSZ_IP_PREFIX]; + ip_prefix_t prefix = { + .family = control->family, + .address = control->address, + .len = control->len, + }; + int rc = ip_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX, &prefix); + assert(rc < MAXSZ_IP_PREFIX); + if (rc < 0) + goto NACK; + + strategy_type_t strategy = control->strategy_type; + strategy_type_t existingFwdStrategy = + configuration_get_strategy(config, prefix_s); + + strategy_options_t options; + + if (existingFwdStrategy == STRATEGY_TYPE_UNDEFINED || + strategy != existingFwdStrategy) { + // means such a new strategy is not present in the hash table or has to be + // updated + int res; + khiter_t k = kh_put_strategy_map(config->strategy_map, prefix_s, &res); + kh_value(config->strategy_map, k) = strategy; + + Name *name_prefix = name_CreateFromAddress(control->family, + control->address, control->len); + // XXX TODO error handling + + switch(control->strategy_type) { + case STRATEGY_TYPE_LOW_LATENCY: + options.low_latency.related_prefixes_len = control->related_prefixes; + Name **related_prefixes = options.low_latency.related_prefixes; + + if(control->related_prefixes != 0){ + for(int i = 0; i < control->related_prefixes; i++){ + related_prefixes[i] = name_CreateFromAddress( + control->low_latency.families[i], + control->low_latency.addresses[i], + control->low_latency.lens[i]); + } + // XXX TODO error handling + } + forwarder_set_strategy(config->forwarder, name_prefix, strategy, &options); + + if (control->related_prefixes != 0) { + for(int i = 0; i < control->related_prefixes; i++) + name_Release(&related_prefixes[i]); + } + break; + default: + break; + } + name_Release(&name_prefix); + } + + make_ack(msg); + return (uint8_t*)msg; + +NACK: + make_nack(msg); + return (uint8_t*)msg; } -struct iovec *configuration_MapMeTimescale(Configuration *config, - struct iovec *request) { - header_control_message *header = request[0].iov_base; - mapme_timing_command *control = request[1].iov_base; +/* WLDR */ - PARCBufferComposer *composer = parcBufferComposer_Create(); - parcBufferComposer_Format(composer, - "The mapme timescale value received is: %u", - control->timePeriod); +uint8_t * +configuration_on_wldr_set(configuration_t * config, uint8_t * packet, + unsigned ingress_id) +{ + assert(config); + assert(packet); - PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer); - char *result = parcBuffer_ToString(tempBuffer); - parcBuffer_Release(&tempBuffer); - puts(result); - parcMemory_Deallocate((void **)&result); - parcBufferComposer_Release(&composer); + msg_wldr_set_t * msg = (msg_wldr_set_t *)packet; + cmd_wldr_set_t * control = &msg->payload; - return utils_CreateAck(header, control, sizeof(mapme_timing_command)); -} + if ((control->activate != 0) && (control->activate != 1)) + goto NACK; + bool value = (bool)control->activate; -struct iovec *configuration_MapMeRetx(Configuration *config, - struct iovec *request) { - header_control_message *header = request[0].iov_base; - mapme_timing_command *control = request[1].iov_base; + unsigned conn_id = symbolic_to_conn_id(config, control->symbolicOrConnid); + if (!connection_id_is_valid(conn_id)) + goto NACK; - PARCBufferComposer *composer = parcBufferComposer_Create(); - parcBufferComposer_Format( - composer, "The mapme retransmission time value received is: %u", - control->timePeriod); + connection_table_t * table = forwarder_get_connection_table(config->forwarder); + connection_t * conn = connection_table_at(table, conn_id); - PARCBuffer *tempBuffer = parcBufferComposer_ProduceBuffer(composer); - char *result = parcBuffer_ToString(tempBuffer); - parcBuffer_Release(&tempBuffer); - puts(result); - parcMemory_Deallocate((void **)&result); - parcBufferComposer_Release(&composer); + if (value) + connection_wldr_enable(conn, value); - return utils_CreateAck(header, control, sizeof(mapme_timing_command)); + make_ack(msg); + return (uint8_t*)msg; + +NACK: + make_ack(msg); + return (uint8_t*)msg; } -struct iovec * configuration_MapMeSendUpdate(Configuration *config, - struct iovec *request, unsigned ingressId) { - header_control_message *header = request[0].iov_base; - mapme_send_update_command *control = request[1].iov_base; - - FIB * fib = forwarder_getFib(config->forwarder); - if (!fib) - goto ERR; - Name *prefix = name_CreateFromAddress(control->addressType, control->address, - control->len); - if (!prefix) - goto ERR; - FibEntry *entry = fib_Contains(fib, prefix); - name_Release(&prefix); - if (!entry) - goto ERR; - - const NumberSet * nexthops = fibEntry_GetNexthops(entry); - unsigned size = (unsigned) numberSet_Length(nexthops); - - /* The command is accepted iif triggered by (one of) the producer of this prefix */ - for (unsigned i = 0; i < size; i++) { - unsigned nhop = numberSet_GetItem(nexthops, i); - if (nhop == ingressId) { - MapMe * mapme = forwarder_getMapmeInstance(config->forwarder); - mapme_send_updates(mapme, entry, nexthops); - return utils_CreateAck(header, control, sizeof(mapme_timing_command)); +/* Punting */ + +uint8_t * +configuration_on_punting_add(configuration_t * config, uint8_t * packet, + unsigned ingress_id) +{ +#if !defined(__APPLE__) && !defined(_WIN32) && defined(PUNTING) + msg_punting_add_t * msg = (msg_punting_add_t *)packet; + cmd_punting_add_t * control = &msg->payload; + + if (ip_address_empty(&control->address)) + goto NACK; + + /* This is for hICN listeners only */ + // XXX add check ! + // comments: + // EncapType: I use the Hicn encap since the punting 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 + address_t fakeaddr; + memset(&fakeaddr, 0, sizeof(address_t)); + fakeaddr = ADDRESS_ANY(control->family, DEFAULT_PORT); + + forwarder_t * forwarder = configuration_get_forwarder(config); + listener_table_t * table = forwarder_get_listener_table(forwarder); + listener_t * listener = listener_table_get_by_address(table, FACE_TYPE_HICN, &fakeaddr); + if (!listener) { + ERROR("the main listener does not exist"); + goto NACK; + } + + + ip_prefix_t prefix = { + .family = control->family, + .address = control->address, + .len = control->len + }; + char prefix_s[MAXSZ_IP_PREFIX]; + int rc = ip_prefix_snprintf(prefix_s, MAXSZ_IP_PREFIX, &prefix); + assert(rc < MAXSZ_IP_PREFIX); + if (rc < 0) + goto NACK; + + if (listener_punt(listener, prefix_s) < 0) { + ERROR("error while adding the punting rule\n"); + goto NACK; } - } -ERR: - return utils_CreateNack(header, control, sizeof(connection_set_admin_state_command)); + make_ack(msg); + return (uint8_t*)msg; + +NACK: +#endif + make_ack(msg); + return (uint8_t*)msg; } +/* MAP-Me */ -struct iovec *configuration_ConnectionSetAdminState(Configuration *config, - struct iovec *request) { - header_control_message *header = request[0].iov_base; - connection_set_admin_state_command *control = request[1].iov_base; +uint8_t * +configuration_on_mapme_enable(configuration_t * config, uint8_t * packet, + unsigned ingress_id) +{ + assert(config); + assert(packet); - if ((control->admin_state != CONNECTION_STATE_UP) && (control->admin_state != CONNECTION_STATE_DOWN)) - return utils_CreateNack(header, control, sizeof(connection_set_admin_state_command)); + msg_mapme_enable_t * msg = (msg_mapme_enable_t *)packet; + cmd_mapme_enable_t * control = &msg->payload; - Connection * conn = getConnectionBySymbolicOrId(config, control->symbolicOrConnid); - if (!conn) - return utils_CreateNack(header, control, sizeof(connection_set_admin_state_command)); + if ((control->activate != 0) && (control->activate != 1)) + goto NACK; + bool value = (bool)control->activate; - connection_SetAdminState(conn, control->admin_state); + INFO("MAP-Me SET enable: %s", value ? "on" : "off"); -#ifdef WITH_MAPME - /* Hook: connection event */ - forwarder_onConnectionEvent(config->forwarder, conn, - control->admin_state == CONNECTION_STATE_UP - ? CONNECTION_EVENT_SET_UP - : CONNECTION_EVENT_SET_DOWN); -#endif /* WITH_MAPME */ + make_ack(msg); + return (uint8_t*)msg; - return utils_CreateAck(header, control, sizeof(connection_set_admin_state_command)); +NACK: + make_ack(msg); + return (uint8_t*)msg; } -#ifdef WITH_POLICY +uint8_t * +configuration_on_mapme_set_discovery(configuration_t * config, uint8_t * packet, + unsigned ingress_id) +{ + assert(config); + assert(packet); -struct iovec *configuration_ConnectionSetPriority(Configuration *config, - struct iovec *request) { - header_control_message *header = request[0].iov_base; - connection_set_priority_command *control = request[1].iov_base; + msg_mapme_set_discovery_t * msg = (msg_mapme_set_discovery_t *)packet; + cmd_mapme_set_discovery_t * control = &msg->payload; - Connection * conn = getConnectionBySymbolicOrId(config, control->symbolicOrConnid); - if (!conn) - return utils_CreateNack(header, control, sizeof(connection_set_priority_command)); + if ((control->activate != 0) && (control->activate != 1)) + goto NACK; + bool value = (bool)control->activate; - connection_SetPriority(conn, control->priority); + INFO("MAP-Me SET discovery: %s", value ? "on" : "off"); -#ifdef WITH_MAPME - /* Hook: connection event */ - forwarder_onConnectionEvent(config->forwarder, conn, - CONNECTION_EVENT_PRIORITY_CHANGED); -#endif /* WITH_MAPME */ + make_ack(msg); + return (uint8_t*)msg; - return utils_CreateAck(header, control, sizeof(connection_set_priority_command)); +NACK: + make_ack(msg); + return (uint8_t*)msg; } -struct iovec *configuration_ConnectionSetTags(Configuration *config, - struct iovec *request) { - header_control_message *header = request[0].iov_base; - connection_set_tags_command *control = request[1].iov_base; +uint8_t * +configuration_on_mapme_set_timescale(configuration_t * config, uint8_t * packet, + unsigned ingress_id) +{ + assert(config); + assert(packet); - Connection * conn = getConnectionBySymbolicOrId(config, control->symbolicOrConnid); - if (!conn) - return utils_CreateNack(header, control, sizeof(connection_set_tags_command)); + msg_mapme_set_timescale_t * msg = (msg_mapme_set_timescale_t *)packet; + cmd_mapme_set_timescale_t * control = &msg->payload; - connection_SetTags(conn, control->tags); + INFO("MAP-Me SET timescale: %u", control->timePeriod); -#ifdef WITH_MAPME - /* Hook: connection event */ - forwarder_onConnectionEvent(config->forwarder, conn, - CONNECTION_EVENT_TAGS_CHANGED); -#endif /* WITH_MAPME */ + make_ack(msg); + return (uint8_t*)msg; +} + +uint8_t * +configuration_on_mapme_set_retx(configuration_t * config, uint8_t * packet, + unsigned ingress_id) +{ + assert(config); + assert(packet); + + msg_mapme_set_retx_t * msg = (msg_mapme_set_retx_t *)packet; + cmd_mapme_set_retx_t * control = &msg->payload; - return utils_CreateAck(header, control, sizeof(connection_set_tags_command)); + INFO("MAP-Me SET retx: %u", control->timePeriod); + + make_ack(msg); + return (uint8_t*)msg; } -struct iovec *configuration_ProcessPolicyAdd(Configuration *config, - struct iovec *request) { - header_control_message *header = request[0].iov_base; - add_policy_command *control = request[1].iov_base; - if (forwarder_AddOrUpdatePolicy(config->forwarder, control)) { - return utils_CreateAck(header, control, sizeof(add_policy_command)); - } else { - return utils_CreateNack(header, control, sizeof(add_policy_command)); - } +uint8_t * +configuration_on_mapme_send_update(configuration_t * config, uint8_t * packet, + unsigned ingress_id) +{ + assert(config); + assert(packet); + + msg_mapme_send_update_t * msg = (msg_mapme_send_update_t *)packet; + cmd_mapme_send_update_t * control = &msg->payload; + + fib_t * fib = forwarder_get_fib(config->forwarder); + if (!fib) + goto NACK; + Name *prefix = name_CreateFromAddress(control->family, control->address, + control->len); + if (!prefix) + goto NACK; + fib_entry_t *entry = fib_contains(fib, prefix); + name_Release(&prefix); + if (!entry) + goto NACK; + + /* The command is accepted iif triggered by (one of) the producer of this prefix */ + const nexthops_t * nexthops = fib_entry_get_nexthops(entry); + + unsigned nexthop; + nexthops_foreach(nexthops, nexthop, { + if (nexthop != ingress_id) + continue; + mapme_t * mapme = forwarder_get_mapme(config->forwarder); + mapme_send_to_all_nexthops(mapme, entry); + make_ack(msg); + return (uint8_t*)msg; + }); + +NACK: + make_ack(msg); + return (uint8_t*)msg; } -struct iovec *configuration_ProcessPolicyList(Configuration *config, - struct iovec *request) { - FibEntryList *fibList = forwarder_GetFibEntries(config->forwarder); - - size_t payloadSize = fibEntryList_Length(fibList); - struct sockaddr_in tmpAddr; - struct sockaddr_in6 tmpAddr6; - - // allocate payload, cast from void* to uint8_t* = bytes granularity - uint8_t *payloadResponse = - parcMemory_AllocateAndClear(sizeof(list_policies_command) * payloadSize); - - for (size_t i = 0; i < fibEntryList_Length(fibList); i++) { - FibEntry *entry = (FibEntry *)fibEntryList_Get(fibList, i); - NameBitvector *prefix = name_GetContentName(fibEntry_GetPrefix(entry)); - - list_policies_command *listPoliciesCommand = - (list_policies_command *)(payloadResponse + - (i * sizeof(list_policies_command))); - - Address *addressEntry = nameBitvector_ToAddress(prefix); - if (addressGetType(addressEntry) == ADDR_INET) { - addressGetInet(addressEntry, &tmpAddr); - listPoliciesCommand->addressType = ADDR_INET; - listPoliciesCommand->address.v4.as_inaddr = tmpAddr.sin_addr; - } else if (addressGetType(addressEntry) == ADDR_INET6) { - addressGetInet6(addressEntry, &tmpAddr6); - listPoliciesCommand->addressType = ADDR_INET6; - listPoliciesCommand->address.v6.as_in6addr = tmpAddr6.sin6_addr; - } - listPoliciesCommand->len = nameBitvector_GetLength(prefix); - listPoliciesCommand->policy = fibEntry_GetPolicy(entry); +/* Policy */ - addressDestroy(&addressEntry); - } +uint8_t * +configuration_on_policy_add(configuration_t * config, uint8_t * packet, + unsigned ingress_id) +{ + assert(config); + assert(packet); - // send response - header_control_message *header = request[0].iov_base; - header->messageType = RESPONSE_LIGHT; - header->length = (unsigned)payloadSize; +#ifdef WITH_POLICY + msg_policy_add_t * msg = (msg_policy_add_t *)packet; + cmd_policy_add_t * control = &msg->payload; + + ip_prefix_t prefix = { + .family = control->family, + .address = control->address, + .len = control->len + }; - struct iovec *response = - parcMemory_AllocateAndClear(sizeof(struct iovec) * 2); + if (!forwarder_add_or_update_policy(config->forwarder, &prefix, &control->policy)) + goto NACK; - response[0].iov_base = header; - response[0].iov_len = sizeof(header_control_message); - response[1].iov_base = payloadResponse; - response[1].iov_len = sizeof(list_policies_command) * payloadSize; + make_ack(msg); + return (uint8_t*)msg; - fibEntryList_Destroy(&fibList); - return response; +NACK: +#endif /* WITH_POLICY */ + make_ack(msg); + return (uint8_t*)msg; } -struct iovec *configuration_ProcessPolicyRemove(Configuration *config, - struct iovec *request) { - header_control_message *header = request[0].iov_base; - remove_policy_command *control = request[1].iov_base; - if (forwarder_RemovePolicy(config->forwarder, control)) - return utils_CreateAck(header, control, sizeof(remove_policy_command)); - else - return utils_CreateNack(header, control, sizeof(remove_policy_command)); -} +uint8_t * +configuration_on_policy_remove(configuration_t * config, uint8_t * packet, + unsigned ingress_id) +{ + assert(config); + assert(packet); -struct iovec *configuration_UpdateConnection(Configuration *config, - struct iovec *request) { - header_control_message *header = request[0].iov_base; - update_connection_command *control = request[1].iov_base; +#ifdef WITH_POLICY + msg_policy_remove_t * msg = (msg_policy_remove_t *)packet; + cmd_policy_remove_t * control = &msg->payload; - Connection * conn = getConnectionBySymbolicOrId(config, control->symbolicOrConnid); - if (!conn) - return utils_CreateNack(header, control, sizeof(update_connection_command)); + ip_prefix_t prefix = { + .family = control->family, + .address = control->address, + .len = control->len + }; - connection_SetTags(conn, control->tags); - connection_SetAdminState(conn, control->admin_state); - if (control->priority > 0) - connection_SetPriority(conn, control->priority); + if (!forwarder_remove_policy(config->forwarder, &prefix)) + goto NACK; - return utils_CreateAck(header, control, sizeof(update_connection_command)); -} + make_ack(msg); + return (uint8_t*)msg; + +NACK: #endif /* WITH_POLICY */ + make_ack(msg); + return (uint8_t*)msg; +} -// =========================== -// Main functions that deal with receiving commands, executing them, and sending -// ACK/NACK +uint8_t * +configuration_on_policy_list(configuration_t * config, uint8_t * packet, + unsigned ingress_id) +{ + assert(config); + assert(packet); -struct iovec *configuration_DispatchCommand(Configuration *config, - command_id command, - struct iovec *control, - unsigned ingressId) { - struct iovec *response = NULL; - switch (command) { - case ADD_LISTENER: - response = configurationListeners_Add(config, control, ingressId); - break; - - case ADD_CONNECTION: - response = configuration_ProcessCreateTunnel(config, control); - break; - - case LIST_CONNECTIONS: - response = configuration_ProcessConnectionList(config, control); - break; - - case ADD_ROUTE: - response = - configuration_ProcessRegisterHicnPrefix(config, control, ingressId); - break; - - case LIST_ROUTES: - response = configuration_ProcessRegistrationList(config, control); - break; - - case REMOVE_CONNECTION: - response = configuration_ProcessRemoveTunnel(config, control, ingressId); - break; - - case REMOVE_LISTENER: - response = configuration_ProcessRemoveListener(config, control, ingressId); - break; - - case REMOVE_ROUTE: - response = configuration_ProcessUnregisterHicnPrefix(config, control); - break; - - case CACHE_STORE: - response = configuration_ProcessCacheStore(config, control); - break; - - case CACHE_SERVE: - response = configuration_ProcessCacheServe(config, control); - break; - - case CACHE_CLEAR: - response = configuration_ProcessCacheClear(config, control); - break; - - case SET_STRATEGY: - response = configuration_SetForwardingStrategy(config, control); - break; - - case SET_WLDR: - response = configuration_SetWldr(config, control); - break; - - case ADD_PUNTING: - response = configurationListeners_AddPunting(config, control, ingressId); - break; - - case LIST_LISTENERS: - response = configuration_ProcessListenersList(config, control); - break; - - case MAPME_ENABLE: - response = configuration_MapMeEnable(config, control); - break; - - case MAPME_DISCOVERY: - response = configuration_MapMeDiscovery(config, control); - break; - - case MAPME_TIMESCALE: - response = configuration_MapMeTimescale(config, control); - break; - - case MAPME_RETX: - response = configuration_MapMeRetx(config, control); - break; - - case MAPME_SEND_UPDATE: - response = configuration_MapMeSendUpdate(config, control, ingressId); - break; - - case CONNECTION_SET_ADMIN_STATE: - response = configuration_ConnectionSetAdminState(config, control); - break; + const fib_t * fib = forwarder_get_fib(config->forwarder); + assert(fib); + size_t n = fib_get_size(fib); #ifdef WITH_POLICY - case ADD_POLICY: - response = configuration_ProcessPolicyAdd(config, control); - break; + msg_policy_list_reply_t * msg; + msg_malloc_list(msg, n); + if (!msg) + return NULL; + + cmd_policy_list_item_t * payload = &msg->payload; + + fib_entry_t * entry; - case LIST_POLICIES: - response = configuration_ProcessPolicyList(config, control); - break; + fib_foreach_entry(fib, entry, { + NameBitvector *prefix = name_GetContentName(fib_entry_get_prefix(entry)); + address_t address; + nameBitvector_ToAddress(prefix, &address); - case REMOVE_POLICY: - response = configuration_ProcessPolicyRemove(config, control); - break; + switch(address_family(&address)) { + case AF_INET: + payload->family = AF_INET; + payload->address.v4.as_inaddr = address4_ip(&address); + break; - case UPDATE_CONNECTION: - response = configuration_UpdateConnection(config, control); - break; + case AF_INET6: + payload->family = AF_INET6; + payload->address.v6.as_in6addr = address6_ip(&address); + break; - case CONNECTION_SET_PRIORITY: - response = configuration_ConnectionSetPriority(config, control); - break; + default: + break; + } + payload->len = nameBitvector_GetLength(prefix); + payload->policy = fib_entry_get_policy(entry); + + payload++; + }); - case CONNECTION_SET_TAGS: - response = configuration_ConnectionSetTags(config, control); - break; + return (uint8_t*)msg; +#else + return NULL; #endif /* WITH_POLICY */ +} - default: - break; - } +size_t +configuration_content_store_get_size(configuration_t * config) +{ + return config->maximumContentObjectStoreSize; +} + +void +configuration_content_store_set_size(configuration_t * config, size_t size) +{ + config->maximumContentObjectStoreSize = size; - return response; + forwarder_content_store_set_size(config->forwarder, + config->maximumContentObjectStoreSize); } -void configuration_ReceiveCommand(Configuration *config, command_id command, - struct iovec *request, unsigned ingressId) { - parcAssertNotNull(config, "Parameter config must be non-null"); - parcAssertNotNull(request, "Parameter request must be non-null"); - struct iovec *response = - configuration_DispatchCommand(config, command, request, ingressId); - configuration_SendResponse(config, response, ingressId); - - switch (command) { - case LIST_CONNECTIONS: - case LIST_ROUTES: // case LIST_INTERFACES: case ETC...: - case LIST_LISTENERS: - parcMemory_Deallocate( - &response[1] - .iov_base); // deallocate payload only if generated at fwd side - break; - default: - break; - } - - // deallocate received request. It coincides with response[0].iov_base memory - // parcMemory_Deallocate(&request); //deallocate header and payload (if - // same sent by controller) - parcMemory_Deallocate(&response); // deallocate iovec pointer +forwarder_t * +configuration_get_forwarder(const configuration_t * config) { + return config->forwarder; +} + + +// =========================== +// Main functions that deal with receiving commands, executing them, and sending +// ACK/NACK + +uint8_t * +configuration_dispatch_command(configuration_t * config, command_type_t command_type, + uint8_t * packet, unsigned ingress_id) +{ + switch (command_type) { +#define _(l, u) \ + case COMMAND_TYPE_ ## u: \ + return configuration_on_ ## l(config, packet, ingress_id); + foreach_command_type +#undef _ + case COMMAND_TYPE_UNDEFINED: + case COMMAND_TYPE_N: + ERROR("Unexpected command type"); + break; + } + return NULL; +} + +void configuration_receive_command(configuration_t * config, + command_type_t command_type, uint8_t * packet, unsigned ingress_id) +{ + assert(config); + assert(command_type_is_valid(command_type)); + assert(packet); + + bool nack = false; + + uint8_t * reply = configuration_dispatch_command(config, command_type, packet, ingress_id); + if (!reply) { + reply = packet; + msg_header_t * hdr = (msg_header_t *)reply; + make_nack(hdr); + nack = true; + } + + connection_table_t * table = forwarder_get_connection_table(config->forwarder); + const connection_t *connection = connection_table_at(table, ingress_id); + connection_send_packet(connection, reply, false); + + switch (command_type) { + case COMMAND_TYPE_LISTENER_LIST: + case COMMAND_TYPE_CONNECTION_LIST: + case COMMAND_TYPE_ROUTE_LIST: + case COMMAND_TYPE_POLICY_LIST: + if (!nack) + free(reply); + break; + default: + break; + } } -- cgit 1.2.3-korg