diff options
Diffstat (limited to 'ctrl/facemgr/src/interfaces')
26 files changed, 2893 insertions, 2788 deletions
diff --git a/ctrl/facemgr/src/interfaces/CMakeLists.txt b/ctrl/facemgr/src/interfaces/CMakeLists.txt index e4d4423e9..02fb0eb48 100644 --- a/ctrl/facemgr/src/interfaces/CMakeLists.txt +++ b/ctrl/facemgr/src/interfaces/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021-2022 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: @@ -16,28 +16,33 @@ list(APPEND SOURCE_FILES) list(APPEND INCLUDE_DIRS) list(APPEND LIBRARIES) + +############################################################## +# Add components +############################################################## add_subdirectory(hicn_light) if(APPLE) -add_subdirectory(network_framework) + add_subdirectory(network_framework) endif() if(LINUX) -add_subdirectory(netlink) -add_subdirectory(bonjour) -endif() - -if(ANDROID) -add_subdirectory(android_utility) -add_subdirectory(priority_controller) + if(ANDROID) + add_subdirectory(android) + add_subdirectory(priority_controller) + else() + add_subdirectory(netlink) + endif() + + add_subdirectory(bonjour) endif() if(WITH_EXAMPLE_DUMMY) -add_subdirectory(dummy) + add_subdirectory(dummy) endif() if(WITH_EXAMPLE_UPDOWN) -add_subdirectory(updown) + add_subdirectory(updown) endif() set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE) diff --git a/ctrl/facemgr/src/interfaces/android_utility/CMakeLists.txt b/ctrl/facemgr/src/interfaces/android/CMakeLists.txt index 0ebe87745..beabc1280 100644 --- a/ctrl/facemgr/src/interfaces/android_utility/CMakeLists.txt +++ b/ctrl/facemgr/src/interfaces/android/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021 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: @@ -11,16 +11,19 @@ # See the License for the specific language governing permissions and # limitations under the License. -list(APPEND SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/android_utility.c +list(APPEND HEADER_FILES ) -list(APPEND INCLUDE_DIRS +list(APPEND SOURCE_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/android.c ) list(APPEND LIBRARIES ) +list(APPEND INCLUDE_DIRS +) + set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE) set(HEADER_FILES ${HEADER_FILES} PARENT_SCOPE) set(INCLUDE_DIRS ${INCLUDE_DIRS} PARENT_SCOPE) diff --git a/ctrl/facemgr/src/interfaces/android/android.c b/ctrl/facemgr/src/interfaces/android/android.c new file mode 100644 index 000000000..4e084d76d --- /dev/null +++ b/ctrl/facemgr/src/interfaces/android/android.c @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2021 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file interfaces/android/android.c + * \brief Netlink interface + */ + +#include <assert.h> +#include <pthread.h> +#include <sys/eventfd.h> +#include <unistd.h> // close + +#include <hicn/facemgr.h> +#include <hicn/util/ip_address.h> +#include <hicn/util/log.h> + +#include "../../common.h" +#include "../../interface.h" +#include "../../facelet_array.h" + +#include "android.h" + +/* + * aar_modules/FaceMgrLibrary/facemgrLibrary/src/main/java/com/cisco/hicn/facemgrlibrary/supportlibrary/FacemgrUtility.java + */ +#define FACEMGR_ANDROID_CLASS \ + "com/cisco/hicn/facemgrlibrary/supportlibrary/FacemgrUtility" + +/* Internal data storage */ +typedef struct { + int fd; + android_cfg_t cfg; + JNIEnv *env; + jclass cls; + bool attached_to_vm; + facelet_array_t *facelets; + pthread_mutex_t mutex; +} android_data_t; + +// might replace android utility + +jclass find_class_global(JNIEnv *env, const char *name) { + jclass c = (*env)->FindClass(env, name); + jclass c_global = 0; + if (c) { + c_global = (jclass)(*env)->NewGlobalRef(env, c); + (*env)->DeleteLocalRef(env, c); + } + return c_global; +} + +int android_on_network_event(interface_t *interface, const char *interface_name, + netdevice_type_t netdevice_type, bool up, + int family, const char *ip_address) { + android_data_t *data = (android_data_t *)interface->data; + + netdevice_t *netdevice = netdevice_create_from_name(interface_name); + if (!netdevice) { + ERROR("[android_on_network_event] error creating netdevice '%s'", + interface_name); + goto ERR_ND; + } + + ip_address_t local_addr = IP_ADDRESS_EMPTY; + if (ip_address) { + if (ip_address_pton(ip_address, &local_addr) < 0) { + ERROR("[android_on_network_event] error processing IP address"); + goto ERR_IP_ADDRESS; + } + } + + facelet_t *facelet = facelet_create(); + if (!facelet) { + ERROR("[android_on_network_event] error creating facelet"); + goto ERR_FACELET; + } + + if (facelet_set_netdevice(facelet, *netdevice) < 0) { + ERROR("[android_on_network_event] error setting netdevice"); + goto ERR; + } + + if (netdevice_type != NETDEVICE_TYPE_UNDEFINED) { + if (facelet_set_netdevice_type(facelet, netdevice_type) < 0) { + ERROR("[android_on_network_event] error setting netdevice type"); + goto ERR; + } + } + + if (facelet_set_family(facelet, family) < 0) { + ERROR("[android_on_network_event] error setting family"); + goto ERR; + } + + if (ip_address) { + if (facelet_set_local_addr(facelet, local_addr) < 0) { + ERROR("[android_on_network_event] error setting local address"); + goto ERR; + } + } + netdevice_free(netdevice); + + facelet_set_event(facelet, up ? FACELET_EVENT_CREATE : FACELET_EVENT_DELETE); + // FACELET_EVENT_UPDATE, FACELET_EVENT_SET_DOWN + facelet_set_attr_clean(facelet); + + pthread_mutex_lock(&data->mutex); + if (facelet_array_add(data->facelets, facelet)) { + ERROR("[android_on_network_event] Could not add facelet to buffer"); + goto ERR_ADD; + } + + pthread_mutex_unlock(&data->mutex); + + eventfd_write(data->fd, 1); + return 0; + +ERR_ADD: + pthread_mutex_unlock(&data->mutex); +ERR: + facelet_free(facelet); +ERR_FACELET: +ERR_IP_ADDRESS: + netdevice_free(netdevice); +ERR_ND: + return -1; +} + +bool get_jni_env(JavaVM *jvm, JNIEnv **env) { + bool did_attach_thread = false; + INFO("initialize: get_jni_env"); + *env = NULL; + // Check if the current thread is attached to the VM + int get_env_result = (*jvm)->GetEnv(jvm, (void **)env, JNI_VERSION_1_6); + if (get_env_result == JNI_EDETACHED) { + INFO("initialize: detached!"); + if ((*jvm)->AttachCurrentThread(jvm, env, NULL) == JNI_OK) { + INFO("initialize: attached..."); + did_attach_thread = true; + } else { + INFO("initialize: failed to attach"); + // Failed to attach thread. Throw an exception if you want to. + } + } else if (get_env_result == JNI_EVERSION) { + // Unsupported JNI version. Throw an exception if you want to. + INFO("initialize: unsupported"); + } + return did_attach_thread; +} + +int android_initialize(interface_t *interface, void *cfg) { + android_data_t *data = malloc(sizeof(android_data_t)); + if (!data) goto ERR_MALLOC; + interface->data = data; + + if (!cfg) goto ERR_CFG; + data->cfg = *(android_cfg_t *)cfg; + + JavaVM *jvm = data->cfg.jvm; + if (!jvm) goto ERR_JVM; + + data->facelets = facelet_array_create(); + if (!data->facelets) goto ERR_FACELETS; + + if ((data->fd = eventfd(0, EFD_SEMAPHORE)) == -1) goto ERR_EVENTFD; + + if (interface_register_fd(interface, data->fd, NULL) < 0) { + ERROR("[android_initialize] Error registering fd"); + goto ERR_REGISTER_FD; + } + + pthread_mutex_init(&data->mutex, NULL); + + data->attached_to_vm = get_jni_env(jvm, &data->env); + + if (!data->env) goto ERR_ENV; + + data->cls = find_class_global(data->env, FACEMGR_ANDROID_CLASS); + if (data->cls == 0) goto ERR_CLS; + + jmethodID mid_initialize = + (*data->env) + ->GetStaticMethodID(data->env, data->cls, "initialize", "()I"); + if (!mid_initialize) goto ERR_MID; + + (*data->env) + ->CallStaticIntMethod(data->env, data->cls, mid_initialize, + &android_on_network_event, interface); + + return 0; + +ERR_MID: + (*data->env)->DeleteGlobalRef(data->env, data->cls); +ERR_CLS: + if (data->attached_to_vm) { + (*jvm)->DetachCurrentThread(jvm); + data->attached_to_vm = false; + } + data->env = NULL; +ERR_ENV: + interface_unregister_fd(interface, data->fd); +ERR_REGISTER_FD: + close(data->fd); +ERR_EVENTFD: + facelet_array_free(data->facelets); +ERR_FACELETS: +ERR_JVM: +ERR_CFG: + free(data); +ERR_MALLOC: + return -1; +} + +int android_finalize(interface_t *interface) { + android_data_t *data = (android_data_t *)interface->data; + + jmethodID mid_terminate = + (*data->env)->GetStaticMethodID(data->env, data->cls, "terminate", "()I"); + if (mid_terminate) { + (*data->env) + ->CallStaticIntMethod(data->env, data->cls, mid_terminate, + &android_on_network_event, interface); + } + + (*data->env)->DeleteGlobalRef(data->env, data->cls); + + JavaVM *jvm = data->cfg.jvm; + if (data->attached_to_vm) { + (*jvm)->DetachCurrentThread(jvm); + data->attached_to_vm = false; + } + data->env = NULL; + + pthread_mutex_destroy(&data->mutex); + + // interface_unregister_fd(interface, data->fd); // XXX done in + // facemgr_delete_interface... + close(data->fd); + facelet_array_free(data->facelets); + + free(data); + + return 0; +} + +int android_callback(interface_t *interface, int fd, void *unused) { + android_data_t *data = (android_data_t *)interface->data; + + uint64_t ret; + if (read(data->fd, &ret, sizeof(ret)) < 0) return -1; + if (ret == 0) // EOF + return 0; + + pthread_mutex_lock(&data->mutex); + for (unsigned i = 0; i < facelet_array_len(data->facelets); i++) { + facelet_t *facelet; + if (facelet_array_get_index(data->facelets, i, &facelet) < 0) { + ERROR("[android_callback] Error getting facelet in array"); + continue; + } + + interface_raise_event(interface, facelet); + } + + for (unsigned i = 0; i < facelet_array_len(data->facelets); i++) { + if (facelet_array_remove_index(data->facelets, i, NULL) < 0) { + ERROR("[android_callback] Could not purge facelet from array"); + } + } + pthread_mutex_unlock(&data->mutex); + + return 0; +} + +const interface_ops_t android_ops = { + .type = "android", + .initialize = android_initialize, + .callback = android_callback, + .finalize = android_finalize, + .on_event = NULL, +}; diff --git a/ctrl/facemgr/src/interfaces/android/android.h b/ctrl/facemgr/src/interfaces/android/android.h new file mode 100644 index 000000000..319bfe10a --- /dev/null +++ b/ctrl/facemgr/src/interfaces/android/android.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * \file android/android.h + * \brief Android utility. + */ + +#ifndef FACEMGR_INTERFACE_ANDROID_H +#define FACEMGR_INTERFACE_ANDROID_H + +#ifdef __ANDROID__ + +#include <jni.h> +#include "../../interface.h" + +typedef struct { + JavaVM *jvm; +} android_cfg_t; + +int android_on_network_event(interface_t *interface, const char *interface_name, + netdevice_type_t netdevice_type, bool up, + int family, const char *ip_address); + +#endif /* __ANDROID__ */ + +#endif /* FACEMGR_INTERFACE_ANDROID_H */ diff --git a/ctrl/facemgr/src/interfaces/android_utility/android_utility.c b/ctrl/facemgr/src/interfaces/android_utility/android_utility.c deleted file mode 100644 index d8e20659a..000000000 --- a/ctrl/facemgr/src/interfaces/android_utility/android_utility.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * \file interfaces/android_utility/android_utility.c - * \brief Implementation of Android utility. - */ - -#include <assert.h> - -#include <hicn/facemgr.h> -#include <hicn/ctrl/face.h> -#include <hicn/util/log.h> -#include "../../common.h" -#include "../../interface.h" - -#include "android_utility.h" - -#define FACEMGR_UTILITY_CLASS "com/cisco/hicn/facemgrlibrary/supportlibrary/FacemgrUtility" - - -#define AU_INTERFACE_TYPE_UNDEFINED 0 -#define AU_INTERFACE_TYPE_WIRED 1 -#define AU_INTERFACE_TYPE_WIFI 2 -#define AU_INTERFACE_TYPE_CELLULAR 3 -#define AU_INTERFACE_TYPE_LOOPBACK 4 -#define AU_INTERFACE_TYPE_UNAVAILABLE 5 - -#define ERR_STR_JAVA "Java VM parameters are required in the interface configuration." - -typedef struct { - android_utility_cfg_t cfg; -} au_data_t; - -int au_initialize(interface_t * interface, void * cfg) -{ - au_data_t * data = malloc(sizeof(au_data_t)); - if (!data) - return -1; - interface->data = data; - - if (!cfg) - goto ERR_CFG; - - data->cfg = * (android_utility_cfg_t *) cfg; - - if (!data->cfg.jvm) - goto ERR_CFG; - - return 0; - -ERR_CFG: - fprintf(stderr, ERR_STR_JAVA); - return -1; -} - -int au_finalize(interface_t * interface) -{ - /* Nothing to do */ - return 0; -} - -int au_on_event(interface_t * interface, facelet_t * facelet) -{ - /* - * This function is responsible to annotate every face we receive with the - * correct interface type, based on the value returned by the Android - * utility shipped with the Android forwarder. - */ - au_data_t * data = (au_data_t*)interface->data; - - netdevice_t netdevice = NETDEVICE_EMPTY; - int rc = facelet_get_netdevice(facelet, &netdevice); - if (rc < 0) - return -1; - - JNIEnv *env; - JavaVM *jvm = data->cfg.jvm; - (*jvm)->AttachCurrentThread(jvm, &env, NULL); - jclass cls = (*env)->FindClass(env, FACEMGR_UTILITY_CLASS); - jmethodID getNetworkType = (*env)->GetStaticMethodID(env, cls, - "getNetworkType", "(Ljava/lang/String;)I"); - jint interface_type = (*env)->CallStaticIntMethod(env, cls, getNetworkType, - (*env)->NewStringUTF(env, netdevice.name)); - - netdevice_type_t netdevice_type = AU_INTERFACE_TYPE_UNDEFINED; - switch(interface_type) { - case AU_INTERFACE_TYPE_UNDEFINED: - break; - case AU_INTERFACE_TYPE_WIRED: - netdevice_type = NETDEVICE_TYPE_WIRED; - break; - case AU_INTERFACE_TYPE_WIFI: - netdevice_type = NETDEVICE_TYPE_WIFI; - break; - case AU_INTERFACE_TYPE_CELLULAR: - netdevice_type = NETDEVICE_TYPE_CELLULAR; - break; - case AU_INTERFACE_TYPE_LOOPBACK: - netdevice_type = NETDEVICE_TYPE_LOOPBACK; - break; - default: - DEBUG("AU RETURNED ERROR"); - return -1; - } - - DEBUG("AU RETURNED %s : %s", netdevice.name, netdevice_type_str[netdevice_type]); - - facelet_t * facelet_new = facelet_create(); - facelet_set_netdevice(facelet_new, netdevice); - facelet_set_attr_clean(facelet_new); - facelet_set_netdevice_type(facelet_new, netdevice_type); - - facelet_set_event(facelet_new, FACELET_EVENT_UPDATE); - interface_raise_event(interface, facelet_new); - - return 0; -} - -const interface_ops_t android_utility_ops = { - .type = "android_utility", - .initialize = au_initialize, - .finalize = au_finalize, - .callback = NULL, - .on_event = au_on_event, -}; diff --git a/ctrl/facemgr/src/interfaces/android_utility/android_utility.h b/ctrl/facemgr/src/interfaces/android_utility/android_utility.h deleted file mode 100644 index 53adfedf6..000000000 --- a/ctrl/facemgr/src/interfaces/android_utility/android_utility.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/** - * \file android_utility/android_utility.h - * \brief Android utility. - * - * This class relies on a small utility wrapper shipped with the Android - * application to access to Java SDK APIs for information not available to - * native code. - * - * For instance, we currently don't have on Linux any mean to get the type - * associated to an interface, especially for cellular interfaces. WiFi and - * Bluetooth information is for instance available through specific netlink - * subsystems, or by means of a support library, but cellular detection mostly - * relies on heuristics based on interface names (eg. in network manager). - * - * Android ship a Radio Interface Layer (RIL) daemon that exposes a control - * socket to the Java API to control the radio layer, but there is no working - * code exploiting it and no proper documentation. - */ - -#ifndef FACEMGR_INTERFACE_ANDROID_UTILITY_H -#define FACEMGR_INTERFACE_ANDROID_UTILITY_H - -#ifdef __ANDROID__ - -#include <jni.h> - -typedef struct { - JavaVM *jvm; -} android_utility_cfg_t; - -#endif /* __ANDROID__ */ - -#endif /* FACEMGR_INTERFACE_ANDROID_UTILITY_H */ diff --git a/ctrl/facemgr/src/interfaces/bonjour/CMakeLists.txt b/ctrl/facemgr/src/interfaces/bonjour/CMakeLists.txt index 8a0ddc888..90ca0e47f 100644 --- a/ctrl/facemgr/src/interfaces/bonjour/CMakeLists.txt +++ b/ctrl/facemgr/src/interfaces/bonjour/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021 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: diff --git a/ctrl/facemgr/src/interfaces/bonjour/bonjour.c b/ctrl/facemgr/src/interfaces/bonjour/bonjour.c index 40b7f5f90..90f18c299 100644 --- a/ctrl/facemgr/src/interfaces/bonjour/bonjour.c +++ b/ctrl/facemgr/src/interfaces/bonjour/bonjour.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -25,6 +25,7 @@ #include <hicn/facemgr.h> #include <hicn/util/log.h> #include <hicn/util/map.h> +#include <hicn/util/sstrncpy.h> #include "../../common.h" #include "../../interface.h" @@ -40,368 +41,357 @@ #define DEFAULT_SERVICE_DOMAIN "local" typedef struct { - bonjour_cfg_t cfg; - int sock; - size_t buffer_size; - void* buffer; + bonjour_cfg_t cfg; + int sock; + size_t buffer_size; + void* buffer; - /* The face being resolved, non-NULL values indicate interface is busy... */ - face_t * face; + /* The face being resolved, non-NULL values indicate interface is busy... */ + face_t* face; } bj_data_t; -int bj_initialize(interface_t * interface, void * cfg) -{ - bj_data_t * data = malloc(sizeof(bj_data_t)); - if (!data) - goto ERR_MALLOC; - interface->data = data; +int bj_initialize(interface_t* interface, void* cfg) { + bj_data_t* data = malloc(sizeof(bj_data_t)); + if (!data) goto ERR_MALLOC; + interface->data = data; - if (cfg) { + if (cfg) { #ifndef __linux__ - if (cfg->netdevice) - WARN("Binding to interface is (currently) only supported on Linux"); + if (cfg->netdevice) + WARN("Binding to interface is (currently) only supported on Linux"); #endif /* ! __linux__ */ - data->cfg = * (bonjour_cfg_t *) cfg; - } else { - memset(&data->cfg, 0, sizeof(bonjour_cfg_t)); - } + data->cfg = *(bonjour_cfg_t*)cfg; + } else { + memset(&data->cfg, 0, sizeof(bonjour_cfg_t)); + } - if (!data->cfg.service_name) - data->cfg.service_name = DEFAULT_SERVICE_NAME; + if (!data->cfg.service_name) data->cfg.service_name = DEFAULT_SERVICE_NAME; - if (!data->cfg.service_protocol) - data->cfg.service_protocol = DEFAULT_SERVICE_PROTOCOL; + if (!data->cfg.service_protocol) + data->cfg.service_protocol = DEFAULT_SERVICE_PROTOCOL; - if (!data->cfg.service_domain) - data->cfg.service_domain = DEFAULT_SERVICE_DOMAIN; + if (!data->cfg.service_domain) + data->cfg.service_domain = DEFAULT_SERVICE_DOMAIN; - data->sock = mdns_socket_open_ipv4(); - if (data->sock < 0) { - printf("Failed to open socket: %s\n", strerror(errno)); - goto ERR_SOCK; - } + data->sock = mdns_socket_open_ipv4(); + if (data->sock < 0) { + printf("Failed to open socket: %s\n", strerror(errno)); + goto ERR_SOCK; + } - /* Netdevice configuration */ + /* Netdevice configuration */ #ifdef __linux__ #ifndef __ANDROID__ - if (IS_VALID_NETDEVICE(data->cfg.netdevice)) { - int rc = setsockopt(data->sock, SOL_SOCKET, SO_BINDTODEVICE, - &data->cfg.netdevice.name, strlen(data->cfg.netdevice.name) + 1); - if (rc == -1) { - ERROR("setsockopt"); - goto ERR_SOCK_OPT; - } + if (IS_VALID_NETDEVICE(data->cfg.netdevice)) { + int rc = setsockopt(data->sock, SOL_SOCKET, SO_BINDTODEVICE, + &data->cfg.netdevice.name, + strnlen_s(data->cfg.netdevice.name, IFNAMSIZ)); + if (rc == -1) { + ERROR("setsockopt"); + goto ERR_SOCK_OPT; } + } #endif #endif /* __linux__ */ - data->buffer_size = DEFAULT_BUFFER_SIZE; - data->buffer = malloc(data->buffer_size); - if (!data->buffer) - goto ERR_BUFFER; + data->buffer_size = DEFAULT_BUFFER_SIZE; + data->buffer = malloc(data->buffer_size); + if (!data->buffer) goto ERR_BUFFER; #ifdef _WIN32 - WORD versionWanted = MAKEWORD(1, 1); - WSADATA wsaData; - WSAStartup(versionWanted, &wsaData); + WORD versionWanted = MAKEWORD(1, 1); + WSADATA wsaData; + WSAStartup(versionWanted, &wsaData); #endif - if (interface_register_fd(interface, data->sock, NULL) < 0) { - ERROR("[bj_initialize] Error registering fd"); - goto ERR_FD; - } + if (interface_register_fd(interface, data->sock, NULL) < 0) { + ERROR("[bj_initialize] Error registering fd"); + goto ERR_FD; + } - return 0; + return 0; ERR_FD: - free(data->buffer); + free(data->buffer); ERR_BUFFER: #ifndef __ANDROID__ ERR_SOCK_OPT: #endif - mdns_socket_close(data->sock); + mdns_socket_close(data->sock); #ifdef _WIN32 - WSACleanup(); + WSACleanup(); #endif ERR_SOCK: - free(data); + free(data); ERR_MALLOC: - return -1; + return -1; } /* * We reuse the callback to be triggered upon external events * TODO: move to a cleaner interface architecture later... */ -int bj_on_event(interface_t * interface, facelet_t * facelet) -{ - bj_data_t * data = (bj_data_t*)interface->data; - - /* - printf("Sending DNS-SD discovery\n"); - if (mdns_discovery_send(sock)) { - printf("Failed to send DNS-DS discovery: %s\n", strerror(errno)); - goto quit; - } - - printf("Reading DNS-SD replies\n"); - for (int i = 0; i < 10; ++i) { - records = mdns_discovery_recv(sock, buffer, capacity, callback, - user_data); - sleep(1); - } - */ - - DEBUG("Sending mDNS query"); - char service_string[SERVICE_STRING_SIZE]; - - int rc = snprintf(service_string, SERVICE_STRING_SIZE, "_%s._%s.%s.", - data->cfg.service_name, data->cfg.service_protocol, - data->cfg.service_domain); - if (rc < 0) - ; // error - else if (rc >= SERVICE_STRING_SIZE) - ; //truncated - - if (mdns_query_send(data->sock, MDNS_RECORDTYPE_PTR, - service_string, - strlen(service_string), - data->buffer, data->buffer_size)) { - printf("Failed to send mDNS query: %s\n", strerror(errno)); - return -1; - } - return 0; +int bj_on_event(interface_t* interface, facelet_t* facelet) { + bj_data_t* data = (bj_data_t*)interface->data; + + /* + printf("Sending DNS-SD discovery\n"); + if (mdns_discovery_send(sock)) { + printf("Failed to send DNS-DS discovery: %s\n", strerror(errno)); + goto quit; + } + + printf("Reading DNS-SD replies\n"); + for (int i = 0; i < 10; ++i) { + records = mdns_discovery_recv(sock, buffer, capacity, callback, + user_data); + sleep(1); + } + */ + + DEBUG("Sending mDNS query"); + char service_string[SERVICE_STRING_SIZE]; + + int rc = snprintf(service_string, SERVICE_STRING_SIZE, "_%s._%s.%s.", + data->cfg.service_name, data->cfg.service_protocol, + data->cfg.service_domain); + if (rc < 0) + ; // error + else if (rc >= SERVICE_STRING_SIZE) + ; // truncated + + if (mdns_query_send(data->sock, MDNS_RECORDTYPE_PTR, service_string, + strnlen_s(service_string, SERVICE_STRING_SIZE), + data->buffer, data->buffer_size)) { + printf("Failed to send mDNS query: %s\n", strerror(errno)); + return -1; + } + return 0; } static char addrbuffer[64]; static char namebuffer[256]; static mdns_record_txt_t txtbuffer[128]; -static mdns_string_t -ipv4_address_to_string(char* buffer, size_t capacity, const struct sockaddr_in* addr) { - char host[NI_MAXHOST] = {0}; - char service[NI_MAXSERV] = {0}; - int ret = getnameinfo((const struct sockaddr*)addr, sizeof(struct sockaddr_in), - host, NI_MAXHOST, service, NI_MAXSERV, - NI_NUMERICSERV | NI_NUMERICHOST); - int len = 0; - if (ret == 0) { - if (addr->sin_port != 0) - len = snprintf(buffer, capacity, "%s:%s", host, service); - else - len = snprintf(buffer, capacity, "%s", host); - } - if (len >= (int)capacity) - len = (int)capacity - 1; - mdns_string_t str = {buffer, len}; - return str; +static mdns_string_t ipv4_address_to_string(char* buffer, size_t capacity, + const struct sockaddr_in* addr) { + char host[NI_MAXHOST] = {0}; + char service[NI_MAXSERV] = {0}; + int ret = getnameinfo((const struct sockaddr*)addr, + sizeof(struct sockaddr_in), host, NI_MAXHOST, service, + NI_MAXSERV, NI_NUMERICSERV | NI_NUMERICHOST); + int len = 0; + if (ret == 0) { + if (addr->sin_port != 0) + len = snprintf(buffer, capacity, "%s:%s", host, service); + else + len = snprintf(buffer, capacity, "%s", host); + } + if (len >= (int)capacity) len = (int)capacity - 1; + mdns_string_t str = {buffer, len}; + return str; } -static mdns_string_t -ipv6_address_to_string(char* buffer, size_t capacity, const struct sockaddr_in6* addr) { - char host[NI_MAXHOST] = {0}; - char service[NI_MAXSERV] = {0}; - int ret = getnameinfo((const struct sockaddr*)addr, sizeof(struct sockaddr_in6), - host, NI_MAXHOST, service, NI_MAXSERV, - NI_NUMERICSERV | NI_NUMERICHOST); - int len = 0; - if (ret == 0) { - if (addr->sin6_port != 0) - len = snprintf(buffer, capacity, "[%s]:%s", host, service); - else - len = snprintf(buffer, capacity, "%s", host); - } - if (len >= (int)capacity) - len = (int)capacity - 1; - mdns_string_t str = {buffer, len}; - return str; +static mdns_string_t ipv6_address_to_string(char* buffer, size_t capacity, + const struct sockaddr_in6* addr) { + char host[NI_MAXHOST] = {0}; + char service[NI_MAXSERV] = {0}; + int ret = getnameinfo((const struct sockaddr*)addr, + sizeof(struct sockaddr_in6), host, NI_MAXHOST, service, + NI_MAXSERV, NI_NUMERICSERV | NI_NUMERICHOST); + int len = 0; + if (ret == 0) { + if (addr->sin6_port != 0) + len = snprintf(buffer, capacity, "[%s]:%s", host, service); + else + len = snprintf(buffer, capacity, "%s", host); + } + if (len >= (int)capacity) len = (int)capacity - 1; + mdns_string_t str = {buffer, len}; + return str; } -static mdns_string_t -ip_address_to_string(char* buffer, size_t capacity, const struct sockaddr* addr) { - if (addr->sa_family == AF_INET6) - return ipv6_address_to_string(buffer, capacity, (const struct sockaddr_in6*)addr); - return ipv4_address_to_string(buffer, capacity, (const struct sockaddr_in*)addr); +static mdns_string_t ip_address_to_string(char* buffer, size_t capacity, + const struct sockaddr* addr) { + if (addr->sa_family == AF_INET6) + return ipv6_address_to_string(buffer, capacity, + (const struct sockaddr_in6*)addr); + return ipv4_address_to_string(buffer, capacity, + (const struct sockaddr_in*)addr); } -int -ip_address_set_sockaddr(ip_address_t * ip_address, struct sockaddr * sa) -{ - switch(sa->sa_family) { - case AF_INET: - ip_address->v4.as_inaddr = ((struct sockaddr_in *)sa)->sin_addr; - break; - case AF_INET6: - ip_address->v6.as_in6addr = ((struct sockaddr_in6 *)sa)->sin6_addr; - break; - default: - return -1; - } - - return 0; +int ip_address_set_sockaddr(ip_address_t* ip_address, struct sockaddr* sa) { + switch (sa->sa_family) { + case AF_INET: + ip_address->v4.as_inaddr = ((struct sockaddr_in*)sa)->sin_addr; + break; + case AF_INET6: + ip_address->v6.as_in6addr = ((struct sockaddr_in6*)sa)->sin6_addr; + break; + default: + return -1; + } + + return 0; } -static int -callback(const struct sockaddr* from, mdns_entry_type_t entry, uint16_t type, - uint16_t rclass, uint32_t ttl, const void* data, size_t size, size_t - offset, size_t length, void* user_data) -{ - interface_t * interface = (interface_t*)user_data; - bj_data_t * bj_data = (bj_data_t *)interface->data; - - struct sockaddr_storage addr; - - mdns_string_t fromaddrstr = ip_address_to_string(addrbuffer, sizeof(addrbuffer), from); - const char* entrytype = (entry == MDNS_ENTRYTYPE_ANSWER) ? "answer" : - ((entry == MDNS_ENTRYTYPE_AUTHORITY) ? "authority" : "additional"); - - switch(type) { - case MDNS_RECORDTYPE_A: - { - ip_address_t ip_address; - mdns_record_parse_a(data, size, offset, length, (struct sockaddr_in*)&addr); - ip_address_set_sockaddr(&ip_address, (struct sockaddr *)&addr); - - mdns_string_t addrstr = ipv4_address_to_string(namebuffer, sizeof(namebuffer), (struct sockaddr_in *)&addr); - DEBUG("%.*s : %s A %.*s", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(addrstr)); - - facelet_t * facelet = facelet_create(); - facelet_set_netdevice(facelet, bj_data->cfg.netdevice); - facelet_set_family(facelet, AF_INET); - facelet_set_remote_addr(facelet, ip_address); - //facelet_set_remote_port(facelet, ((struct sockaddr_in*)&addr)->sin_port); - - facelet_set_event(facelet, FACELET_EVENT_UPDATE); - interface_raise_event(interface, facelet); - break; - } +static int callback(const struct sockaddr* from, mdns_entry_type_t entry, + uint16_t type, uint16_t rclass, uint32_t ttl, + const void* data, size_t size, size_t offset, size_t length, + void* user_data) { + interface_t* interface = (interface_t*)user_data; + bj_data_t* bj_data = (bj_data_t*)interface->data; + + struct sockaddr_storage addr; + + mdns_string_t fromaddrstr = + ip_address_to_string(addrbuffer, sizeof(addrbuffer), from); + const char* entrytype = + (entry == MDNS_ENTRYTYPE_ANSWER) + ? "answer" + : ((entry == MDNS_ENTRYTYPE_AUTHORITY) ? "authority" : "additional"); + + switch (type) { + case MDNS_RECORDTYPE_A: { + ip_address_t ip_address; + mdns_record_parse_a(data, size, offset, length, + (struct sockaddr_in*)&addr); + ip_address_set_sockaddr(&ip_address, (struct sockaddr*)&addr); + + mdns_string_t addrstr = ipv4_address_to_string( + namebuffer, sizeof(namebuffer), (struct sockaddr_in*)&addr); + DEBUG("%.*s : %s A %.*s", MDNS_STRING_FORMAT(fromaddrstr), entrytype, + MDNS_STRING_FORMAT(addrstr)); + + facelet_t* facelet = facelet_create(); + facelet_set_netdevice(facelet, bj_data->cfg.netdevice); + facelet_set_family(facelet, AF_INET); + facelet_set_remote_addr(facelet, ip_address); + // facelet_set_remote_port(facelet, ((struct + // sockaddr_in*)&addr)->sin_port); + + facelet_set_event(facelet, FACELET_EVENT_UPDATE); + interface_raise_event(interface, facelet); + break; + } - case MDNS_RECORDTYPE_AAAA: - { - ip_address_t ip_address; - mdns_record_parse_aaaa(data, size, offset, length, (struct sockaddr_in6*)&addr); - ip_address_set_sockaddr(&ip_address, (struct sockaddr *)&addr); - - mdns_string_t addrstr = ipv6_address_to_string(namebuffer, - sizeof(namebuffer), (struct sockaddr_in6*)&addr); - DEBUG("%.*s : %s AAAA %.*s", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(addrstr)); - - facelet_t * facelet = facelet_create(); - facelet_set_netdevice(facelet, bj_data->cfg.netdevice); - facelet_set_family(facelet, AF_INET6); - facelet_set_remote_addr(facelet, ip_address); - //facelet_set_remote_port(facelet, ((struct sockaddr_in6*)&addr)->sin6_port); - - facelet_set_event(facelet, FACELET_EVENT_UPDATE); - interface_raise_event(interface, facelet); - break; - } + case MDNS_RECORDTYPE_AAAA: { + ip_address_t ip_address; + mdns_record_parse_aaaa(data, size, offset, length, + (struct sockaddr_in6*)&addr); + ip_address_set_sockaddr(&ip_address, (struct sockaddr*)&addr); + + mdns_string_t addrstr = ipv6_address_to_string( + namebuffer, sizeof(namebuffer), (struct sockaddr_in6*)&addr); + DEBUG("%.*s : %s AAAA %.*s", MDNS_STRING_FORMAT(fromaddrstr), entrytype, + MDNS_STRING_FORMAT(addrstr)); + + facelet_t* facelet = facelet_create(); + facelet_set_netdevice(facelet, bj_data->cfg.netdevice); + facelet_set_family(facelet, AF_INET6); + facelet_set_remote_addr(facelet, ip_address); + // facelet_set_remote_port(facelet, ((struct + // sockaddr_in6*)&addr)->sin6_port); + + facelet_set_event(facelet, FACELET_EVENT_UPDATE); + interface_raise_event(interface, facelet); + break; + } - case MDNS_RECORDTYPE_SRV: /* same port for both v4 and v6 */ - { - mdns_record_srv_t srv = mdns_record_parse_srv(data, size, offset, length, - namebuffer, sizeof(namebuffer)); - - DEBUG("%.*s : %s SRV %.*s priority %d weight %d port %d", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(srv.name), srv.priority, srv.weight, srv.port); - - /* We raise both v4 and v6 - * - * Unless we choose whether we query A and/or AAAA, this might leave - * us with an unused pending facelet, eg. we might not have an IPv6 - * but we raise an IPv6 bonjour event... - */ - - facelet_t * facelet = facelet_create(); - facelet_set_netdevice(facelet, bj_data->cfg.netdevice); - facelet_set_family(facelet, AF_INET); - facelet_set_remote_port(facelet, srv.port); - - facelet_set_event(facelet, FACELET_EVENT_UPDATE); - interface_raise_event(interface, facelet); - - facelet = facelet_create(); - facelet_set_netdevice(facelet, bj_data->cfg.netdevice); - facelet_set_family(facelet, AF_INET6); - facelet_set_remote_port(facelet, srv.port); - - facelet_set_event(facelet, FACELET_EVENT_UPDATE); - interface_raise_event(interface, facelet); - break; - } + case MDNS_RECORDTYPE_SRV: /* same port for both v4 and v6 */ + { + mdns_record_srv_t srv = mdns_record_parse_srv( + data, size, offset, length, namebuffer, sizeof(namebuffer)); + + DEBUG("%.*s : %s SRV %.*s priority %d weight %d port %d", + MDNS_STRING_FORMAT(fromaddrstr), entrytype, + MDNS_STRING_FORMAT(srv.name), srv.priority, srv.weight, srv.port); + + /* We raise both v4 and v6 + * + * Unless we choose whether we query A and/or AAAA, this might leave + * us with an unused pending facelet, eg. we might not have an IPv6 + * but we raise an IPv6 bonjour event... + */ + + facelet_t* facelet = facelet_create(); + facelet_set_netdevice(facelet, bj_data->cfg.netdevice); + facelet_set_family(facelet, AF_INET); + facelet_set_remote_port(facelet, srv.port); + + facelet_set_event(facelet, FACELET_EVENT_UPDATE); + interface_raise_event(interface, facelet); + + facelet = facelet_create(); + facelet_set_netdevice(facelet, bj_data->cfg.netdevice); + facelet_set_family(facelet, AF_INET6); + facelet_set_remote_port(facelet, srv.port); + + facelet_set_event(facelet, FACELET_EVENT_UPDATE); + interface_raise_event(interface, facelet); + break; + } - case MDNS_RECORDTYPE_PTR: - { - mdns_string_t namestr = mdns_record_parse_ptr(data, size, offset, length, - namebuffer, sizeof(namebuffer)); - DEBUG("%.*s : %s PTR %.*s type %u rclass 0x%x ttl %u length %d", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(namestr), type, rclass, ttl, (int)length); - break; - } + case MDNS_RECORDTYPE_PTR: { + mdns_string_t namestr = mdns_record_parse_ptr( + data, size, offset, length, namebuffer, sizeof(namebuffer)); + DEBUG("%.*s : %s PTR %.*s type %u rclass 0x%x ttl %u length %d", + MDNS_STRING_FORMAT(fromaddrstr), entrytype, + MDNS_STRING_FORMAT(namestr), type, rclass, ttl, (int)length); + break; + } - case MDNS_RECORDTYPE_TXT: - { - size_t parsed = mdns_record_parse_txt(data, size, offset, length, - txtbuffer, sizeof(txtbuffer) / sizeof(mdns_record_txt_t)); - for (size_t itxt = 0; itxt < parsed; ++itxt) { - if (txtbuffer[itxt].value.length) { - DEBUG("%.*s : %s TXT %.*s = %.*s", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(txtbuffer[itxt].key), - MDNS_STRING_FORMAT(txtbuffer[itxt].value)); - } - else { - DEBUG("%.*s : %s TXT %.*s", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(txtbuffer[itxt].key)); - } - } - break; + case MDNS_RECORDTYPE_TXT: { + size_t parsed = + mdns_record_parse_txt(data, size, offset, length, txtbuffer, + sizeof(txtbuffer) / sizeof(mdns_record_txt_t)); + for (size_t itxt = 0; itxt < parsed; ++itxt) { + if (txtbuffer[itxt].value.length) { + DEBUG("%.*s : %s TXT %.*s = %.*s", MDNS_STRING_FORMAT(fromaddrstr), + entrytype, MDNS_STRING_FORMAT(txtbuffer[itxt].key), + MDNS_STRING_FORMAT(txtbuffer[itxt].value)); + } else { + DEBUG("%.*s : %s TXT %.*s", MDNS_STRING_FORMAT(fromaddrstr), + entrytype, MDNS_STRING_FORMAT(txtbuffer[itxt].key)); } - - default: - /* Silently ignore the received record */ - DEBUG("%.*s : %s type %u rclass 0x%x ttl %u length %d", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - type, rclass, ttl, (int)length); - return 0; + } + break; } - return 0; + default: + /* Silently ignore the received record */ + DEBUG("%.*s : %s type %u rclass 0x%x ttl %u length %d", + MDNS_STRING_FORMAT(fromaddrstr), entrytype, type, rclass, ttl, + (int)length); + return 0; + } + return 0; } /* * The fact we use a single fd does not allow us to get user_data associated to * the query. */ -int bj_callback(interface_t * interface, int fd, void * unused) -{ - bj_data_t * data = (bj_data_t*)interface->data; - DEBUG("Got an mDNS reply"); - /* size_t records = */ mdns_query_recv(data->sock, data->buffer, data->buffer_size, callback, interface, 1); +int bj_callback(interface_t* interface, int fd, void* unused) { + bj_data_t* data = (bj_data_t*)interface->data; + DEBUG("Got an mDNS reply"); + /* size_t records = */ mdns_query_recv( + data->sock, data->buffer, data->buffer_size, callback, interface, 1); - return 0; + return 0; } -int bj_finalize(interface_t * interface) -{ - bj_data_t * data = (bj_data_t*)interface->data; +int bj_finalize(interface_t* interface) { + bj_data_t* data = (bj_data_t*)interface->data; - free(data->buffer); - mdns_socket_close(data->sock); + free(data->buffer); + mdns_socket_close(data->sock); #ifdef _WIN32 - WSACleanup(); + WSACleanup(); #endif - return 0; - + return 0; } const interface_ops_t bonjour_ops = { @@ -410,5 +400,5 @@ const interface_ops_t bonjour_ops = { .on_event = bj_on_event, .callback = bj_callback, .finalize = bj_finalize, - // .on_event = NULL, + // .on_event = NULL, }; diff --git a/ctrl/facemgr/src/interfaces/bonjour/bonjour.h b/ctrl/facemgr/src/interfaces/bonjour/bonjour.h index fe053079d..6458423ea 100644 --- a/ctrl/facemgr/src/interfaces/bonjour/bonjour.h +++ b/ctrl/facemgr/src/interfaces/bonjour/bonjour.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -25,11 +25,11 @@ * queries... */ -#include <hicn/ctrl/face.h> /* netdevice_t */ +#include <hicn/face.h> /* netdevice_t */ typedef struct { - netdevice_t netdevice; - char * service_name; - char * service_protocol; - char * service_domain; + netdevice_t netdevice; + char* service_name; + char* service_protocol; + char* service_domain; } bonjour_cfg_t; diff --git a/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.c b/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.c index a8e97e8e0..e2bb4f432 100644 --- a/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.c +++ b/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.c @@ -1,6 +1,6 @@ #ifdef _WIN32 -# define _CRT_SECURE_NO_WARNINGS 1 +#define _CRT_SECURE_NO_WARNINGS 1 #endif #include "mdns.h" @@ -9,184 +9,176 @@ #include <errno.h> #ifdef _WIN32 -# define sleep(x) Sleep(x * 1000) +#define sleep(x) Sleep(x * 1000) #else -# include <netdb.h> +#include <netdb.h> #endif static char addrbuffer[64]; static char namebuffer[256]; static mdns_record_txt_t txtbuffer[128]; -static mdns_string_t -ipv4_address_to_string(char* buffer, size_t capacity, const struct sockaddr_in* addr) { - char host[NI_MAXHOST] = {0}; - char service[NI_MAXSERV] = {0}; - int ret = getnameinfo((const struct sockaddr*)addr, sizeof(struct sockaddr_in), - host, NI_MAXHOST, service, NI_MAXSERV, - NI_NUMERICSERV | NI_NUMERICHOST); - int len = 0; - if (ret == 0) { - if (addr->sin_port != 0) - len = snprintf(buffer, capacity, "%s:%s", host, service); - else - len = snprintf(buffer, capacity, "%s", host); - } - if (len >= (int)capacity) - len = (int)capacity - 1; - mdns_string_t str = {buffer, len}; - return str; +static mdns_string_t ipv4_address_to_string(char* buffer, size_t capacity, + const struct sockaddr_in* addr) { + char host[NI_MAXHOST] = {0}; + char service[NI_MAXSERV] = {0}; + int ret = getnameinfo((const struct sockaddr*)addr, + sizeof(struct sockaddr_in), host, NI_MAXHOST, service, + NI_MAXSERV, NI_NUMERICSERV | NI_NUMERICHOST); + int len = 0; + if (ret == 0) { + if (addr->sin_port != 0) + len = snprintf(buffer, capacity, "%s:%s", host, service); + else + len = snprintf(buffer, capacity, "%s", host); + } + if (len >= (int)capacity) len = (int)capacity - 1; + mdns_string_t str = {buffer, len}; + return str; } -static mdns_string_t -ipv6_address_to_string(char* buffer, size_t capacity, const struct sockaddr_in6* addr) { - char host[NI_MAXHOST] = {0}; - char service[NI_MAXSERV] = {0}; - int ret = getnameinfo((const struct sockaddr*)addr, sizeof(struct sockaddr_in6), - host, NI_MAXHOST, service, NI_MAXSERV, - NI_NUMERICSERV | NI_NUMERICHOST); - int len = 0; - if (ret == 0) { - if (addr->sin6_port != 0) - len = snprintf(buffer, capacity, "[%s]:%s", host, service); - else - len = snprintf(buffer, capacity, "%s", host); - } - if (len >= (int)capacity) - len = (int)capacity - 1; - mdns_string_t str = {buffer, len}; - return str; +static mdns_string_t ipv6_address_to_string(char* buffer, size_t capacity, + const struct sockaddr_in6* addr) { + char host[NI_MAXHOST] = {0}; + char service[NI_MAXSERV] = {0}; + int ret = getnameinfo((const struct sockaddr*)addr, + sizeof(struct sockaddr_in6), host, NI_MAXHOST, service, + NI_MAXSERV, NI_NUMERICSERV | NI_NUMERICHOST); + int len = 0; + if (ret == 0) { + if (addr->sin6_port != 0) + len = snprintf(buffer, capacity, "[%s]:%s", host, service); + else + len = snprintf(buffer, capacity, "%s", host); + } + if (len >= (int)capacity) len = (int)capacity - 1; + mdns_string_t str = {buffer, len}; + return str; } -static mdns_string_t -ip_address_to_string(char* buffer, size_t capacity, const struct sockaddr* addr) { - if (addr->sa_family == AF_INET6) - return ipv6_address_to_string(buffer, capacity, (const struct sockaddr_in6*)addr); - return ipv4_address_to_string(buffer, capacity, (const struct sockaddr_in*)addr); +static mdns_string_t ip_address_to_string(char* buffer, size_t capacity, + const struct sockaddr* addr) { + if (addr->sa_family == AF_INET6) + return ipv6_address_to_string(buffer, capacity, + (const struct sockaddr_in6*)addr); + return ipv4_address_to_string(buffer, capacity, + (const struct sockaddr_in*)addr); } -static int -callback(const struct sockaddr* from, - mdns_entry_type_t entry, uint16_t type, - uint16_t rclass, uint32_t ttl, - const void* data, size_t size, size_t offset, size_t length, - void* user_data) { - mdns_string_t fromaddrstr = ip_address_to_string(addrbuffer, sizeof(addrbuffer), from); - const char* entrytype = (entry == MDNS_ENTRYTYPE_ANSWER) ? "answer" : - ((entry == MDNS_ENTRYTYPE_AUTHORITY) ? "authority" : "additional"); - if (type == MDNS_RECORDTYPE_PTR) { - mdns_string_t namestr = mdns_record_parse_ptr(data, size, offset, length, - namebuffer, sizeof(namebuffer)); - INFO("%.*s : %s PTR %.*s type %u rclass 0x%x ttl %u length %d\n", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(namestr), type, rclass, ttl, (int)length); - } - else if (type == MDNS_RECORDTYPE_SRV) { - mdns_record_srv_t srv = mdns_record_parse_srv(data, size, offset, length, - namebuffer, sizeof(namebuffer)); - INFO("%.*s : %s SRV %.*s priority %d weight %d port %d\n", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(srv.name), srv.priority, srv.weight, srv.port); - } - else if (type == MDNS_RECORDTYPE_A) { - struct sockaddr_in addr; - mdns_record_parse_a(data, size, offset, length, &addr); - mdns_string_t addrstr = ipv4_address_to_string(namebuffer, sizeof(namebuffer), &addr); - INFO("%.*s : %s A %.*s\n", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(addrstr)); - } - else if (type == MDNS_RECORDTYPE_AAAA) { - struct sockaddr_in6 addr; - mdns_record_parse_aaaa(data, size, offset, length, &addr); - mdns_string_t addrstr = ipv6_address_to_string(namebuffer, sizeof(namebuffer), &addr); - INFO("%.*s : %s AAAA %.*s\n", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(addrstr)); - } - else if (type == MDNS_RECORDTYPE_TXT) { - size_t parsed = mdns_record_parse_txt(data, size, offset, length, - txtbuffer, sizeof(txtbuffer) / sizeof(mdns_record_txt_t)); - for (size_t itxt = 0; itxt < parsed; ++itxt) { - if (txtbuffer[itxt].value.length) { - INFO("%.*s : %s TXT %.*s = %.*s\n", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(txtbuffer[itxt].key), - MDNS_STRING_FORMAT(txtbuffer[itxt].value)); - } - else { - INFO("%.*s : %s TXT %.*s\n", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - MDNS_STRING_FORMAT(txtbuffer[itxt].key)); - } - } - } - else { - INFO("%.*s : %s type %u rclass 0x%x ttl %u length %d\n", - MDNS_STRING_FORMAT(fromaddrstr), entrytype, - type, rclass, ttl, (int)length); - } - return 0; +static int callback(const struct sockaddr* from, mdns_entry_type_t entry, + uint16_t type, uint16_t rclass, uint32_t ttl, + const void* data, size_t size, size_t offset, size_t length, + void* user_data) { + mdns_string_t fromaddrstr = + ip_address_to_string(addrbuffer, sizeof(addrbuffer), from); + const char* entrytype = + (entry == MDNS_ENTRYTYPE_ANSWER) + ? "answer" + : ((entry == MDNS_ENTRYTYPE_AUTHORITY) ? "authority" : "additional"); + if (type == MDNS_RECORDTYPE_PTR) { + mdns_string_t namestr = mdns_record_parse_ptr( + data, size, offset, length, namebuffer, sizeof(namebuffer)); + INFO("%.*s : %s PTR %.*s type %u rclass 0x%x ttl %u length %d\n", + MDNS_STRING_FORMAT(fromaddrstr), entrytype, + MDNS_STRING_FORMAT(namestr), type, rclass, ttl, (int)length); + } else if (type == MDNS_RECORDTYPE_SRV) { + mdns_record_srv_t srv = mdns_record_parse_srv( + data, size, offset, length, namebuffer, sizeof(namebuffer)); + INFO("%.*s : %s SRV %.*s priority %d weight %d port %d\n", + MDNS_STRING_FORMAT(fromaddrstr), entrytype, + MDNS_STRING_FORMAT(srv.name), srv.priority, srv.weight, srv.port); + } else if (type == MDNS_RECORDTYPE_A) { + struct sockaddr_in addr; + mdns_record_parse_a(data, size, offset, length, &addr); + mdns_string_t addrstr = + ipv4_address_to_string(namebuffer, sizeof(namebuffer), &addr); + INFO("%.*s : %s A %.*s\n", MDNS_STRING_FORMAT(fromaddrstr), entrytype, + MDNS_STRING_FORMAT(addrstr)); + } else if (type == MDNS_RECORDTYPE_AAAA) { + struct sockaddr_in6 addr; + mdns_record_parse_aaaa(data, size, offset, length, &addr); + mdns_string_t addrstr = + ipv6_address_to_string(namebuffer, sizeof(namebuffer), &addr); + INFO("%.*s : %s AAAA %.*s\n", MDNS_STRING_FORMAT(fromaddrstr), entrytype, + MDNS_STRING_FORMAT(addrstr)); + } else if (type == MDNS_RECORDTYPE_TXT) { + size_t parsed = + mdns_record_parse_txt(data, size, offset, length, txtbuffer, + sizeof(txtbuffer) / sizeof(mdns_record_txt_t)); + for (size_t itxt = 0; itxt < parsed; ++itxt) { + if (txtbuffer[itxt].value.length) { + INFO("%.*s : %s TXT %.*s = %.*s\n", MDNS_STRING_FORMAT(fromaddrstr), + entrytype, MDNS_STRING_FORMAT(txtbuffer[itxt].key), + MDNS_STRING_FORMAT(txtbuffer[itxt].value)); + } else { + INFO("%.*s : %s TXT %.*s\n", MDNS_STRING_FORMAT(fromaddrstr), entrytype, + MDNS_STRING_FORMAT(txtbuffer[itxt].key)); + } + } + } else { + INFO("%.*s : %s type %u rclass 0x%x ttl %u length %d\n", + MDNS_STRING_FORMAT(fromaddrstr), entrytype, type, rclass, ttl, + (int)length); + } + return 0; } -int -main() { - size_t capacity = 2048; - void* buffer = 0; - void* user_data = 0; - size_t records; +int main() { + size_t capacity = 2048; + void* buffer = 0; + void* user_data = 0; + size_t records; #ifdef _WIN32 - WORD versionWanted = MAKEWORD(1, 1); - WSADATA wsaData; - WSAStartup(versionWanted, &wsaData); + WORD versionWanted = MAKEWORD(1, 1); + WSADATA wsaData; + WSAStartup(versionWanted, &wsaData); #endif - int sock = mdns_socket_open_ipv4(); - if (sock < 0) { - INFO("Failed to open socket: %s\n", strerror(errno)); - return -1; - } - INFO("Opened IPv4 socket for mDNS/DNS-SD\n"); - buffer = malloc(capacity); -/* - INFO("Sending DNS-SD discovery\n"); - if (mdns_discovery_send(sock)) { - INFO("Failed to send DNS-DS discovery: %s\n", strerror(errno)); - goto quit; - } - - INFO("Reading DNS-SD replies\n"); - for (int i = 0; i < 10; ++i) { - records = mdns_discovery_recv(sock, buffer, capacity, callback, - user_data); - sleep(1); - } - */ - - INFO("Sending mDNS query\n"); - if (mdns_query_send(sock, MDNS_RECORDTYPE_PTR, - MDNS_STRING_CONST("_hicn._udp.local."), - buffer, capacity)) { - INFO("Failed to send mDNS query: %s\n", strerror(errno)); - goto quit; - } - - INFO("Reading mDNS replies\n"); - for (int i = 0; i < 10; ++i) { - records = mdns_query_recv(sock, buffer, capacity, callback, user_data, 1); - sleep(1); - } + int sock = mdns_socket_open_ipv4(); + if (sock < 0) { + INFO("Failed to open socket: %s\n", strerror(errno)); + return -1; + } + INFO("Opened IPv4 socket for mDNS/DNS-SD\n"); + buffer = malloc(capacity); + /* + INFO("Sending DNS-SD discovery\n"); + if (mdns_discovery_send(sock)) { + INFO("Failed to send DNS-DS discovery: %s\n", + strerror(errno)); goto quit; + } + + INFO("Reading DNS-SD replies\n"); + for (int i = 0; i < 10; ++i) { + records = mdns_discovery_recv(sock, buffer, capacity, + callback, user_data); sleep(1); + } + */ + + INFO("Sending mDNS query\n"); + if (mdns_query_send(sock, MDNS_RECORDTYPE_PTR, + MDNS_STRING_CONST("_hicn._udp.local."), buffer, + capacity)) { + INFO("Failed to send mDNS query: %s\n", strerror(errno)); + goto quit; + } + + INFO("Reading mDNS replies\n"); + for (int i = 0; i < 10; ++i) { + records = mdns_query_recv(sock, buffer, capacity, callback, user_data, 1); + sleep(1); + } quit: - free(buffer); + free(buffer); - mdns_socket_close(sock); - INFO("Closed socket\n"); + mdns_socket_close(sock); + INFO("Closed socket\n"); #ifdef _WIN32 - WSACleanup(); + WSACleanup(); #endif - return 0; + return 0; } diff --git a/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.h b/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.h index ff04b5d72..4b8e7a7f4 100644 --- a/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.h +++ b/ctrl/facemgr/src/interfaces/bonjour/mdns/mdns.h @@ -7,7 +7,8 @@ * * https://github.com/mjansson/mdns * - * This library is put in the public domain; you can redistribute it and/or modify it without any restrictions. + * This library is put in the public domain; you can redistribute it and/or + * modify it without any restrictions. * */ @@ -31,76 +32,73 @@ #define MDNS_INVALID_POS ((size_t)-1) -#define MDNS_STRING_CONST(s) (s), (sizeof((s))-1) +#define MDNS_STRING_CONST(s) (s), (sizeof((s)) - 1) #define MDNS_STRING_FORMAT(s) (int)((s).length), s.str enum mdns_record_type { - MDNS_RECORDTYPE_IGNORE = 0, - //Address - MDNS_RECORDTYPE_A = 1, - //Domain Name pointer - MDNS_RECORDTYPE_PTR = 12, - //Arbitrary text string - MDNS_RECORDTYPE_TXT = 16, - //IP6 Address [Thomson] - MDNS_RECORDTYPE_AAAA = 28, - //Server Selection [RFC2782] - MDNS_RECORDTYPE_SRV = 33 + MDNS_RECORDTYPE_IGNORE = 0, + // Address + MDNS_RECORDTYPE_A = 1, + // Domain Name pointer + MDNS_RECORDTYPE_PTR = 12, + // Arbitrary text string + MDNS_RECORDTYPE_TXT = 16, + // IP6 Address [Thomson] + MDNS_RECORDTYPE_AAAA = 28, + // Server Selection [RFC2782] + MDNS_RECORDTYPE_SRV = 33 }; enum mdns_entry_type { - MDNS_ENTRYTYPE_ANSWER = 1, - MDNS_ENTRYTYPE_AUTHORITY = 2, - MDNS_ENTRYTYPE_ADDITIONAL = 3 + MDNS_ENTRYTYPE_ANSWER = 1, + MDNS_ENTRYTYPE_AUTHORITY = 2, + MDNS_ENTRYTYPE_ADDITIONAL = 3 }; -enum mdns_class { - MDNS_CLASS_IN = 1 -}; +enum mdns_class { MDNS_CLASS_IN = 1 }; -typedef enum mdns_record_type mdns_record_type_t; -typedef enum mdns_entry_type mdns_entry_type_t; -typedef enum mdns_class mdns_class_t; +typedef enum mdns_record_type mdns_record_type_t; +typedef enum mdns_entry_type mdns_entry_type_t; +typedef enum mdns_class mdns_class_t; -typedef int (* mdns_record_callback_fn)(const struct sockaddr* from, - mdns_entry_type_t entry, uint16_t type, - uint16_t rclass, uint32_t ttl, - const void* data, size_t size, size_t offset, size_t length, - void* user_data); +typedef int (*mdns_record_callback_fn)(const struct sockaddr* from, + mdns_entry_type_t entry, uint16_t type, + uint16_t rclass, uint32_t ttl, + const void* data, size_t size, + size_t offset, size_t length, + void* user_data); -typedef struct mdns_string_t mdns_string_t; -typedef struct mdns_string_pair_t mdns_string_pair_t; -typedef struct mdns_record_srv_t mdns_record_srv_t; -typedef struct mdns_record_txt_t mdns_record_txt_t; +typedef struct mdns_string_t mdns_string_t; +typedef struct mdns_string_pair_t mdns_string_pair_t; +typedef struct mdns_record_srv_t mdns_record_srv_t; +typedef struct mdns_record_txt_t mdns_record_txt_t; struct mdns_string_t { - const char* str; - size_t length; + const char* str; + size_t length; }; struct mdns_string_pair_t { - size_t offset; - size_t length; - int ref; + size_t offset; + size_t length; + int ref; }; struct mdns_record_srv_t { - uint16_t priority; - uint16_t weight; - uint16_t port; - mdns_string_t name; + uint16_t priority; + uint16_t weight; + uint16_t port; + mdns_string_t name; }; struct mdns_record_txt_t { - mdns_string_t key; - mdns_string_t value; + mdns_string_t key; + mdns_string_t value; }; -static int -mdns_socket_open_ipv4(void); +static int mdns_socket_open_ipv4(void); -static int -mdns_socket_setup_ipv4(int sock); +static int mdns_socket_setup_ipv4(int sock); #if 0 static int @@ -112,8 +110,7 @@ static int mdns_socket_setup_ipv6(int sock); #endif -static void -mdns_socket_close(int sock); +static void mdns_socket_close(int sock); #if 0 static int @@ -125,21 +122,18 @@ mdns_discovery_recv(int sock, void* buffer, size_t capacity, mdns_record_callback_fn callback, void* user_data); #endif -static int -mdns_query_send(int sock, mdns_record_type_t type, const char* name, size_t length, - void* buffer, size_t capacity); +static int mdns_query_send(int sock, mdns_record_type_t type, const char* name, + size_t length, void* buffer, size_t capacity); -static size_t -mdns_query_recv(int sock, void* buffer, size_t capacity, - mdns_record_callback_fn callback, void* user_data, - uint8_t one_shot); +static size_t mdns_query_recv(int sock, void* buffer, size_t capacity, + mdns_record_callback_fn callback, void* user_data, + uint8_t one_shot); -static mdns_string_t -mdns_string_extract(const void* buffer, size_t size, size_t* offset, - char* str, size_t capacity); +static mdns_string_t mdns_string_extract(const void* buffer, size_t size, + size_t* offset, char* str, + size_t capacity); -static int -mdns_string_skip(const void* buffer, size_t size, size_t* offset); +static int mdns_string_skip(const void* buffer, size_t size, size_t* offset); #if 0 static int @@ -147,78 +141,80 @@ mdns_string_equal(const void* buffer_lhs, size_t size_lhs, size_t* ofs_lhs, const void* buffer_rhs, size_t size_rhs, size_t* ofs_rhs); #endif -static void* -mdns_string_make(void* data, size_t capacity, const char* name, size_t length); +static void* mdns_string_make(void* data, size_t capacity, const char* name, + size_t length); -static mdns_string_t -mdns_record_parse_ptr(const void* buffer, size_t size, size_t offset, size_t length, - char* strbuffer, size_t capacity); +static mdns_string_t mdns_record_parse_ptr(const void* buffer, size_t size, + size_t offset, size_t length, + char* strbuffer, size_t capacity); -static mdns_record_srv_t -mdns_record_parse_srv(const void* buffer, size_t size, size_t offset, size_t length, - char* strbuffer, size_t capacity); +static mdns_record_srv_t mdns_record_parse_srv(const void* buffer, size_t size, + size_t offset, size_t length, + char* strbuffer, + size_t capacity); -static struct sockaddr_in* -mdns_record_parse_a(const void* buffer, size_t size, size_t offset, size_t length, - struct sockaddr_in* addr); +static struct sockaddr_in* mdns_record_parse_a(const void* buffer, size_t size, + size_t offset, size_t length, + struct sockaddr_in* addr); -static struct sockaddr_in6* -mdns_record_parse_aaaa(const void* buffer, size_t size, size_t offset, size_t length, - struct sockaddr_in6* addr); +static struct sockaddr_in6* mdns_record_parse_aaaa(const void* buffer, + size_t size, size_t offset, + size_t length, + struct sockaddr_in6* addr); -static size_t -mdns_record_parse_txt(const void* buffer, size_t size, size_t offset, size_t length, - mdns_record_txt_t* records, size_t capacity); +static size_t mdns_record_parse_txt(const void* buffer, size_t size, + size_t offset, size_t length, + mdns_record_txt_t* records, + size_t capacity); // Implementations -static int -mdns_socket_open_ipv4(void) { - int sock = (int)socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (sock < 0) - return -1; - if (mdns_socket_setup_ipv4(sock)) { - mdns_socket_close(sock); - return -1; - } - return sock; +static int mdns_socket_open_ipv4(void) { + int sock = (int)socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (sock < 0) return -1; + if (mdns_socket_setup_ipv4(sock)) { + mdns_socket_close(sock); + return -1; + } + return sock; } -static int -mdns_socket_setup_ipv4(int sock) { - struct sockaddr_in saddr; - memset(&saddr, 0, sizeof(saddr)); - saddr.sin_family = AF_INET; - saddr.sin_addr.s_addr = INADDR_ANY; +static int mdns_socket_setup_ipv4(int sock) { + struct sockaddr_in saddr; + memset(&saddr, 0, sizeof(saddr)); + saddr.sin_family = AF_INET; + saddr.sin_addr.s_addr = INADDR_ANY; #ifdef __APPLE__ - saddr.sin_len = sizeof(saddr); + saddr.sin_len = sizeof(saddr); #endif - if (bind(sock, (struct sockaddr*)&saddr, sizeof(saddr))) - return -1; + if (bind(sock, (struct sockaddr*)&saddr, sizeof(saddr))) return -1; #ifdef _WIN32 - unsigned long param = 1; - ioctlsocket(sock, FIONBIO, ¶m); + unsigned long param = 1; + ioctlsocket(sock, FIONBIO, ¶m); #else - const int flags = fcntl(sock, F_GETFL, 0); - fcntl(sock, F_SETFL, flags | O_NONBLOCK); + const int flags = fcntl(sock, F_GETFL, 0); + fcntl(sock, F_SETFL, flags | O_NONBLOCK); #endif - unsigned char ttl = 1; - unsigned char loopback = 1; - struct ip_mreq req; + unsigned char ttl = 1; + unsigned char loopback = 1; + struct ip_mreq req; - setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)&ttl, sizeof(ttl)); - setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, (const char*)&loopback, sizeof(loopback)); + setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)&ttl, + sizeof(ttl)); + setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, (const char*)&loopback, + sizeof(loopback)); - memset(&req, 0, sizeof(req)); - req.imr_multiaddr.s_addr = htonl((((uint32_t)224U) << 24U) | ((uint32_t)251U)); - req.imr_interface.s_addr = INADDR_ANY; - if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&req, sizeof(req))) - return -1; + memset(&req, 0, sizeof(req)); + req.imr_multiaddr.s_addr = + htonl((((uint32_t)224U) << 24U) | ((uint32_t)251U)); + req.imr_interface.s_addr = INADDR_ANY; + if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&req, sizeof(req))) + return -1; - return 0; + return 0; } #if 0 @@ -274,67 +270,58 @@ mdns_socket_setup_ipv6(int sock) { } #endif -static void -mdns_socket_close(int sock) { +static void mdns_socket_close(int sock) { #ifdef _WIN32 - closesocket(sock); + closesocket(sock); #else - close(sock); + close(sock); #endif } -static int -mdns_is_string_ref(uint8_t val) { - return (0xC0 == (val & 0xC0)); -} +static int mdns_is_string_ref(uint8_t val) { return (0xC0 == (val & 0xC0)); } -static mdns_string_pair_t -mdns_get_next_substring(const void* rawdata, size_t size, size_t offset) { - const uint8_t* buffer = rawdata; - mdns_string_pair_t pair = {MDNS_INVALID_POS, 0, 0}; - if (!buffer[offset]) { - pair.offset = offset; - return pair; - } - if (mdns_is_string_ref(buffer[offset])) { - if (size < offset + 2) - return pair; +static mdns_string_pair_t mdns_get_next_substring(const void* rawdata, + size_t size, size_t offset) { + const uint8_t* buffer = rawdata; + mdns_string_pair_t pair = {MDNS_INVALID_POS, 0, 0}; + if (!buffer[offset]) { + pair.offset = offset; + return pair; + } + if (mdns_is_string_ref(buffer[offset])) { + if (size < offset + 2) return pair; - offset = (((size_t)(0x3f & buffer[offset]) << 8) | (size_t)buffer[offset + 1]); - if (offset >= size) - return pair; + offset = + (((size_t)(0x3f & buffer[offset]) << 8) | (size_t)buffer[offset + 1]); + if (offset >= size) return pair; - pair.ref = 1; - } + pair.ref = 1; + } - size_t length = (size_t)buffer[offset++]; - if (size < offset + length) - return pair; + size_t length = (size_t)buffer[offset++]; + if (size < offset + length) return pair; - pair.offset = offset; - pair.length = length; + pair.offset = offset; + pair.length = length; - return pair; + return pair; } -static int -mdns_string_skip(const void* buffer, size_t size, size_t* offset) { - size_t cur = *offset; - mdns_string_pair_t substr; - do { - substr = mdns_get_next_substring(buffer, size, cur); - if (substr.offset == MDNS_INVALID_POS) - return 0; - if (substr.ref) { - *offset = cur + 2; - return 1; - } - cur = substr.offset + substr.length; - } - while (substr.length); - - *offset = cur + 1; - return 1; +static int mdns_string_skip(const void* buffer, size_t size, size_t* offset) { + size_t cur = *offset; + mdns_string_pair_t substr; + do { + substr = mdns_get_next_substring(buffer, size, cur); + if (substr.offset == MDNS_INVALID_POS) return 0; + if (substr.ref) { + *offset = cur + 2; + return 1; + } + cur = substr.offset + substr.length; + } while (substr.length); + + *offset = cur + 1; + return 1; } #if 0 @@ -378,142 +365,133 @@ mdns_string_equal(const void* buffer_lhs, size_t size_lhs, size_t* ofs_lhs, } #endif -static mdns_string_t -mdns_string_extract(const void* buffer, size_t size, size_t* offset, - char* str, size_t capacity) { - size_t cur = *offset; - size_t end = MDNS_INVALID_POS; - mdns_string_pair_t substr; - mdns_string_t result = {str, 0}; - char* dst = str; - size_t remain = capacity; - do { - substr = mdns_get_next_substring(buffer, size, cur); - if (substr.offset == MDNS_INVALID_POS) - return result; - if (substr.ref && (end == MDNS_INVALID_POS)) - end = cur + 2; - if (substr.length) { - size_t to_copy = (substr.length < remain) ? substr.length : remain; - memcpy(dst, (const char*)buffer + substr.offset, to_copy); - dst += to_copy; - remain -= to_copy; - if (remain) { - *dst++ = '.'; - --remain; - } - } - cur = substr.offset + substr.length; - } - while (substr.length); - - if (end == MDNS_INVALID_POS) - end = cur + 1; - *offset = end; - - result.length = capacity - remain; - return result; +static mdns_string_t mdns_string_extract(const void* buffer, size_t size, + size_t* offset, char* str, + size_t capacity) { + size_t cur = *offset; + size_t end = MDNS_INVALID_POS; + mdns_string_pair_t substr; + mdns_string_t result = {str, 0}; + char* dst = str; + size_t remain = capacity; + do { + substr = mdns_get_next_substring(buffer, size, cur); + if (substr.offset == MDNS_INVALID_POS) return result; + if (substr.ref && (end == MDNS_INVALID_POS)) end = cur + 2; + if (substr.length) { + size_t to_copy = (substr.length < remain) ? substr.length : remain; + memcpy(dst, (const char*)buffer + substr.offset, to_copy); + dst += to_copy; + remain -= to_copy; + if (remain) { + *dst++ = '.'; + --remain; + } + } + cur = substr.offset + substr.length; + } while (substr.length); + + if (end == MDNS_INVALID_POS) end = cur + 1; + *offset = end; + + result.length = capacity - remain; + return result; } -static size_t -mdns_string_find(const char* str, size_t length, char c, size_t offset) { - const void* found; - if (offset >= length) - return MDNS_INVALID_POS; - found = memchr(str + offset, c, length - offset); - if (found) - return (size_t)((const char*)found - str); - return MDNS_INVALID_POS; +static size_t mdns_string_find(const char* str, size_t length, char c, + size_t offset) { + const void* found; + if (offset >= length) return MDNS_INVALID_POS; + found = memchr(str + offset, c, length - offset); + if (found) return (size_t)((const char*)found - str); + return MDNS_INVALID_POS; } -static void* -mdns_string_make(void* data, size_t capacity, const char* name, size_t length) { - size_t pos = 0; - size_t last_pos = 0; - size_t remain = capacity; - unsigned char* dest = data; - while ((last_pos < length) && ((pos = mdns_string_find(name, length, '.', last_pos)) != MDNS_INVALID_POS)) { - size_t sublength = pos - last_pos; - if (sublength < remain) { - *dest = (unsigned char)sublength; - memcpy(dest + 1, name + last_pos, sublength); - dest += sublength + 1; - remain -= sublength + 1; - } - else { - return 0; - } - last_pos = pos + 1; - } - if (last_pos < length) { - size_t sublength = length - last_pos; - if (sublength < capacity) { - *dest = (unsigned char)sublength; - memcpy(dest + 1, name + last_pos, sublength); - dest += sublength + 1; - remain -= sublength + 1; - } - else { - return 0; - } - } - if (!remain) - return 0; - *dest++ = 0; - return dest; +static void* mdns_string_make(void* data, size_t capacity, const char* name, + size_t length) { + size_t pos = 0; + size_t last_pos = 0; + size_t remain = capacity; + unsigned char* dest = data; + while ((last_pos < length) && + ((pos = mdns_string_find(name, length, '.', last_pos)) != + MDNS_INVALID_POS)) { + size_t sublength = pos - last_pos; + if (sublength < remain) { + *dest = (unsigned char)sublength; + memcpy(dest + 1, name + last_pos, sublength); + dest += sublength + 1; + remain -= sublength + 1; + } else { + return 0; + } + last_pos = pos + 1; + } + if (last_pos < length) { + size_t sublength = length - last_pos; + if (sublength < capacity) { + *dest = (unsigned char)sublength; + memcpy(dest + 1, name + last_pos, sublength); + dest += sublength + 1; + remain -= sublength + 1; + } else { + return 0; + } + } + if (!remain) return 0; + *dest++ = 0; + return dest; } -static size_t -mdns_records_parse(const struct sockaddr* from, const void* buffer, size_t size, size_t* offset, - mdns_entry_type_t type, size_t records, mdns_record_callback_fn callback, - void* user_data) { - size_t parsed = 0; - int do_callback = 1; - for (size_t i = 0; i < records; ++i) { - mdns_string_skip(buffer, size, offset); - const uint16_t* data = (const uint16_t*)((const char*)buffer + (*offset)); - - uint16_t rtype = ntohs(*data++); - uint16_t rclass = ntohs(*data++); - uint32_t ttl = ntohs(*(const uint32_t*)(const void*)data); data += 2; - uint16_t length = ntohs(*data++); - - *offset += 10; - - if (do_callback) { - ++parsed; - if (callback(from, type, rtype, rclass, ttl, buffer, size, *offset, length, - user_data)) - do_callback = 0; - } - - *offset += length; - } - return parsed; +static size_t mdns_records_parse(const struct sockaddr* from, + const void* buffer, size_t size, + size_t* offset, mdns_entry_type_t type, + size_t records, + mdns_record_callback_fn callback, + void* user_data) { + size_t parsed = 0; + int do_callback = 1; + for (size_t i = 0; i < records; ++i) { + mdns_string_skip(buffer, size, offset); + const uint16_t* data = (const uint16_t*)((const char*)buffer + (*offset)); + + uint16_t rtype = ntohs(*data++); + uint16_t rclass = ntohs(*data++); + uint32_t ttl = ntohs(*(const uint32_t*)(const void*)data); + data += 2; + uint16_t length = ntohs(*data++); + + *offset += 10; + + if (do_callback) { + ++parsed; + if (callback(from, type, rtype, rclass, ttl, buffer, size, *offset, + length, user_data)) + do_callback = 0; + } + + *offset += length; + } + return parsed; } static const uint8_t mdns_services_query[] = { - // Transaction ID - 0x00, 0x00, - // Flags - 0x00, 0x00, - // 1 question - 0x00, 0x01, - // No answer, authority or additional RRs - 0x00, 0x00, - 0x00, 0x00, - 0x00, 0x00, - // _services._dns-sd._udp.local. - 0x09, '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', 's', - 0x07, '_', 'd', 'n', 's', '-', 's', 'd', - 0x04, '_', 'u', 'd', 'p', - 0x05, 'l', 'o', 'c', 'a', 'l', - 0x00, - // PTR record - 0x00, MDNS_RECORDTYPE_PTR, - // QU (unicast response) and class IN - 0x80, MDNS_CLASS_IN -}; + // Transaction ID + 0x00, 0x00, + // Flags + 0x00, 0x00, + // 1 question + 0x00, 0x01, + // No answer, authority or additional RRs + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // _services._dns-sd._udp.local. + 0x09, '_', 's', 'e', 'r', 'v', 'i', 'c', 'e', 's', 0x07, '_', 'd', 'n', 's', + '-', 's', 'd', 0x04, '_', 'u', 'd', 'p', 0x05, 'l', 'o', 'c', 'a', 'l', + 0x00, + // PTR record + 0x00, MDNS_RECORDTYPE_PTR, + // QU (unicast response) and class IN + 0x80, MDNS_CLASS_IN}; #if 0 static int @@ -645,233 +623,223 @@ mdns_discovery_recv(int sock, void* buffer, size_t capacity, static uint16_t mdns_transaction_id = 0; -static int -mdns_query_send(int sock, mdns_record_type_t type, const char* name, size_t length, - void* buffer, size_t capacity) { - if (capacity < (17 + length)) - return -1; - - uint16_t* data = buffer; - //Transaction ID - *data++ = htons(++mdns_transaction_id); - //Flags - *data++ = 0; - //Questions - *data++ = htons(1); - //No answer, authority or additional RRs - *data++ = 0; - *data++ = 0; - *data++ = 0; - //Name string - data = mdns_string_make(data, capacity - 17, name, length); - if (!data) - return -1; - //Record type - *data++ = htons(type); - //! Unicast response, class IN - *data++ = htons(0x8000U | MDNS_CLASS_IN); - - struct sockaddr_storage addr_storage; - struct sockaddr_in addr; - struct sockaddr_in6 addr6; - struct sockaddr* saddr = (struct sockaddr*)&addr_storage; - socklen_t saddrlen = sizeof(struct sockaddr_storage); - if (getsockname(sock, saddr, &saddrlen)) - return -1; - if (saddr->sa_family == AF_INET6) { - memset(&addr6, 0, sizeof(struct sockaddr_in6)); - addr6.sin6_family = AF_INET6; +static int mdns_query_send(int sock, mdns_record_type_t type, const char* name, + size_t length, void* buffer, size_t capacity) { + if (capacity < (17 + length)) return -1; + + uint16_t* data = buffer; + // Transaction ID + *data++ = htons(++mdns_transaction_id); + // Flags + *data++ = 0; + // Questions + *data++ = htons(1); + // No answer, authority or additional RRs + *data++ = 0; + *data++ = 0; + *data++ = 0; + // Name string + data = mdns_string_make(data, capacity - 17, name, length); + if (!data) return -1; + // Record type + *data++ = htons(type); + //! Unicast response, class IN + *data++ = htons(0x8000U | MDNS_CLASS_IN); + + struct sockaddr_storage addr_storage; + struct sockaddr_in addr; + struct sockaddr_in6 addr6; + struct sockaddr* saddr = (struct sockaddr*)&addr_storage; + socklen_t saddrlen = sizeof(struct sockaddr_storage); + if (getsockname(sock, saddr, &saddrlen)) return -1; + if (saddr->sa_family == AF_INET6) { + memset(&addr6, 0, sizeof(struct sockaddr_in6)); + addr6.sin6_family = AF_INET6; #ifdef __APPLE__ - addr6.sin6_len = sizeof(struct sockaddr_in6); + addr6.sin6_len = sizeof(struct sockaddr_in6); #endif - addr6.sin6_addr.s6_addr[0] = 0xFF; - addr6.sin6_addr.s6_addr[1] = 0x02; - addr6.sin6_addr.s6_addr[15] = 0xFB; - addr6.sin6_port = htons((unsigned short)5353); - saddr = (struct sockaddr*)&addr6; - saddrlen = sizeof(struct sockaddr_in6); - } - else { - memset(&addr, 0, sizeof(struct sockaddr_in)); - addr.sin_family = AF_INET; + addr6.sin6_addr.s6_addr[0] = 0xFF; + addr6.sin6_addr.s6_addr[1] = 0x02; + addr6.sin6_addr.s6_addr[15] = 0xFB; + addr6.sin6_port = htons((unsigned short)5353); + saddr = (struct sockaddr*)&addr6; + saddrlen = sizeof(struct sockaddr_in6); + } else { + memset(&addr, 0, sizeof(struct sockaddr_in)); + addr.sin_family = AF_INET; #ifdef __APPLE__ - addr.sin_len = sizeof(struct sockaddr_in); + addr.sin_len = sizeof(struct sockaddr_in); #endif - addr.sin_addr.s_addr = htonl((((uint32_t)224U) << 24U) | ((uint32_t)251U)); - addr.sin_port = htons((unsigned short)5353); - saddr = (struct sockaddr*)&addr; - saddrlen = sizeof(struct sockaddr_in); - } - - if (sendto(sock, buffer, (char*)data - (char*)buffer, 0, - saddr, saddrlen) < 0) - return -1; - return 0; + addr.sin_addr.s_addr = htonl((((uint32_t)224U) << 24U) | ((uint32_t)251U)); + addr.sin_port = htons((unsigned short)5353); + saddr = (struct sockaddr*)&addr; + saddrlen = sizeof(struct sockaddr_in); + } + + if (sendto(sock, buffer, (char*)data - (char*)buffer, 0, saddr, saddrlen) < 0) + return -1; + return 0; } -static size_t -mdns_query_recv(int sock, void* buffer, size_t capacity, - mdns_record_callback_fn callback, void* user_data, - uint8_t one_shot) { - struct sockaddr_in6 addr; - struct sockaddr* saddr = (struct sockaddr*)&addr; - memset(&addr, 0, sizeof(addr)); - saddr->sa_family = AF_INET; +static size_t mdns_query_recv(int sock, void* buffer, size_t capacity, + mdns_record_callback_fn callback, void* user_data, + uint8_t one_shot) { + struct sockaddr_in6 addr; + struct sockaddr* saddr = (struct sockaddr*)&addr; + memset(&addr, 0, sizeof(addr)); + saddr->sa_family = AF_INET; #ifdef __APPLE__ - saddr->sa_len = sizeof(addr); + saddr->sa_len = sizeof(addr); #endif - socklen_t addrlen = sizeof(addr); - int ret = recvfrom(sock, buffer, capacity, 0, - saddr, &addrlen); - if (ret <= 0) - return 0; - - size_t data_size = (size_t)ret; - uint16_t* data = (uint16_t*)buffer; - - uint16_t transaction_id = ntohs(*data++); - ++data;// uint16_t flags = ntohs(*data++); - uint16_t questions = ntohs(*data++); - uint16_t answer_rrs = ntohs(*data++); - uint16_t authority_rrs = ntohs(*data++); - uint16_t additional_rrs = ntohs(*data++); - - if (one_shot && transaction_id != mdns_transaction_id)// || (flags != 0x8400)) - return 0; //Not a reply to our last question - - if (questions > 1) - return 0; - - //Skip questions part - int i; - for (i = 0; i < questions; ++i) { - size_t ofs = (size_t)((char*)data - (char*)buffer); - if (!mdns_string_skip(buffer, data_size, &ofs)) - return 0; - data = (void*)((char*)buffer + ofs); - ++data; - ++data; - } - - size_t records = 0; - size_t offset = (size_t)((char*)data - (char*)buffer); - records += mdns_records_parse(saddr, buffer, data_size, &offset, - MDNS_ENTRYTYPE_ANSWER, answer_rrs, - callback, user_data); - records += mdns_records_parse(saddr, buffer, data_size, &offset, - MDNS_ENTRYTYPE_AUTHORITY, authority_rrs, - callback, user_data); - records += mdns_records_parse(saddr, buffer, data_size, &offset, - MDNS_ENTRYTYPE_ADDITIONAL, additional_rrs, - callback, user_data); - return records; + socklen_t addrlen = sizeof(addr); + int ret = recvfrom(sock, buffer, capacity, 0, saddr, &addrlen); + if (ret <= 0) return 0; + + size_t data_size = (size_t)ret; + uint16_t* data = (uint16_t*)buffer; + + uint16_t transaction_id = ntohs(*data++); + ++data; // uint16_t flags = ntohs(*data++); + uint16_t questions = ntohs(*data++); + uint16_t answer_rrs = ntohs(*data++); + uint16_t authority_rrs = ntohs(*data++); + uint16_t additional_rrs = ntohs(*data++); + + if (one_shot && + transaction_id != mdns_transaction_id) // || (flags != 0x8400)) + return 0; // Not a reply to our last question + + if (questions > 1) return 0; + + // Skip questions part + int i; + for (i = 0; i < questions; ++i) { + size_t ofs = (size_t)((char*)data - (char*)buffer); + if (!mdns_string_skip(buffer, data_size, &ofs)) return 0; + data = (void*)((char*)buffer + ofs); + ++data; + ++data; + } + + size_t records = 0; + size_t offset = (size_t)((char*)data - (char*)buffer); + records += mdns_records_parse(saddr, buffer, data_size, &offset, + MDNS_ENTRYTYPE_ANSWER, answer_rrs, callback, + user_data); + records += mdns_records_parse(saddr, buffer, data_size, &offset, + MDNS_ENTRYTYPE_AUTHORITY, authority_rrs, + callback, user_data); + records += mdns_records_parse(saddr, buffer, data_size, &offset, + MDNS_ENTRYTYPE_ADDITIONAL, additional_rrs, + callback, user_data); + return records; } -static mdns_string_t -mdns_record_parse_ptr(const void* buffer, size_t size, size_t offset, size_t length, - char* strbuffer, size_t capacity) { - //PTR record is just a string - if ((size >= offset + length) && (length >= 2)) - return mdns_string_extract(buffer, size, &offset, strbuffer, capacity); - mdns_string_t empty = {0, 0}; - return empty; +static mdns_string_t mdns_record_parse_ptr(const void* buffer, size_t size, + size_t offset, size_t length, + char* strbuffer, size_t capacity) { + // PTR record is just a string + if ((size >= offset + length) && (length >= 2)) + return mdns_string_extract(buffer, size, &offset, strbuffer, capacity); + mdns_string_t empty = {0, 0}; + return empty; } -static mdns_record_srv_t -mdns_record_parse_srv(const void* buffer, size_t size, size_t offset, size_t length, - char* strbuffer, size_t capacity) { - mdns_record_srv_t srv; - memset(&srv, 0, sizeof(mdns_record_srv_t)); - // Read the priority, weight, port number and the discovery name - // SRV record format (http://www.ietf.org/rfc/rfc2782.txt): - // 2 bytes network-order unsigned priority - // 2 bytes network-order unsigned weight - // 2 bytes network-order unsigned port - // string: discovery (domain) name, minimum 2 bytes when compressed - if ((size >= offset + length) && (length >= 8)) { - const uint16_t* recorddata = (const uint16_t*)((const char*)buffer + offset); - srv.priority = ntohs(*recorddata++); - srv.weight = ntohs(*recorddata++); - srv.port = ntohs(*recorddata++); - offset += 6; - srv.name = mdns_string_extract(buffer, size, &offset, strbuffer, capacity); - } - return srv; +static mdns_record_srv_t mdns_record_parse_srv(const void* buffer, size_t size, + size_t offset, size_t length, + char* strbuffer, + size_t capacity) { + mdns_record_srv_t srv; + memset(&srv, 0, sizeof(mdns_record_srv_t)); + // Read the priority, weight, port number and the discovery name + // SRV record format (http://www.ietf.org/rfc/rfc2782.txt): + // 2 bytes network-order unsigned priority + // 2 bytes network-order unsigned weight + // 2 bytes network-order unsigned port + // string: discovery (domain) name, minimum 2 bytes when compressed + if ((size >= offset + length) && (length >= 8)) { + const uint16_t* recorddata = + (const uint16_t*)((const char*)buffer + offset); + srv.priority = ntohs(*recorddata++); + srv.weight = ntohs(*recorddata++); + srv.port = ntohs(*recorddata++); + offset += 6; + srv.name = mdns_string_extract(buffer, size, &offset, strbuffer, capacity); + } + return srv; } -static struct sockaddr_in* -mdns_record_parse_a(const void* buffer, size_t size, size_t offset, size_t length, - struct sockaddr_in* addr) { - memset(addr, 0, sizeof(struct sockaddr_in)); - addr->sin_family = AF_INET; +static struct sockaddr_in* mdns_record_parse_a(const void* buffer, size_t size, + size_t offset, size_t length, + struct sockaddr_in* addr) { + memset(addr, 0, sizeof(struct sockaddr_in)); + addr->sin_family = AF_INET; #ifdef __APPLE__ - addr->sin_len = sizeof(struct sockaddr_in); + addr->sin_len = sizeof(struct sockaddr_in); #endif - if ((size >= offset + length) && (length == 4)) - addr->sin_addr.s_addr = *(const uint32_t*)((const char*)buffer + offset); - return addr; + if ((size >= offset + length) && (length == 4)) + addr->sin_addr.s_addr = *(const uint32_t*)((const char*)buffer + offset); + return addr; } -static struct sockaddr_in6* -mdns_record_parse_aaaa(const void* buffer, size_t size, size_t offset, size_t length, - struct sockaddr_in6* addr) { - memset(addr, 0, sizeof(struct sockaddr_in6)); - addr->sin6_family = AF_INET6; +static struct sockaddr_in6* mdns_record_parse_aaaa(const void* buffer, + size_t size, size_t offset, + size_t length, + struct sockaddr_in6* addr) { + memset(addr, 0, sizeof(struct sockaddr_in6)); + addr->sin6_family = AF_INET6; #ifdef __APPLE__ - addr->sin6_len = sizeof(struct sockaddr_in6); + addr->sin6_len = sizeof(struct sockaddr_in6); #endif - if ((size >= offset + length) && (length == 16)) - addr->sin6_addr = *(const struct in6_addr*)((const char*)buffer + offset); - return addr; + if ((size >= offset + length) && (length == 16)) + addr->sin6_addr = *(const struct in6_addr*)((const char*)buffer + offset); + return addr; } -static size_t -mdns_record_parse_txt(const void* buffer, size_t size, size_t offset, size_t length, - mdns_record_txt_t* records, size_t capacity) { - size_t parsed = 0; - const char* strdata; - size_t separator, sublength; - size_t end = offset + length; - - if (size < end) - end = size; - - while ((offset < end) && (parsed < capacity)) { - strdata = (const char*)buffer + offset; - sublength = *(const unsigned char*)strdata; - - ++strdata; - offset += sublength + 1; - - separator = 0; - for (size_t c = 0; c < sublength; ++c) { - //DNS-SD TXT record keys MUST be printable US-ASCII, [0x20, 0x7E] - if ((strdata[c] < 0x20) || (strdata[c] > 0x7E)) - break; - if (strdata[c] == '=') { - separator = c; - break; - } - } - - if (!separator) - continue; - - if (separator < sublength) { - records[parsed].key.str = strdata; - records[parsed].key.length = separator; - records[parsed].value.str = strdata + separator + 1; - records[parsed].value.length = sublength - (separator + 1); - } - else { - records[parsed].key.str = strdata; - records[parsed].key.length = sublength; - } - - ++parsed; - } - - return parsed; +static size_t mdns_record_parse_txt(const void* buffer, size_t size, + size_t offset, size_t length, + mdns_record_txt_t* records, + size_t capacity) { + size_t parsed = 0; + const char* strdata; + size_t separator, sublength; + size_t end = offset + length; + + if (size < end) end = size; + + while ((offset < end) && (parsed < capacity)) { + strdata = (const char*)buffer + offset; + sublength = *(const unsigned char*)strdata; + + ++strdata; + offset += sublength + 1; + + separator = 0; + for (size_t c = 0; c < sublength; ++c) { + // DNS-SD TXT record keys MUST be printable US-ASCII, [0x20, 0x7E] + if ((strdata[c] < 0x20) || (strdata[c] > 0x7E)) break; + if (strdata[c] == '=') { + separator = c; + break; + } + } + + if (!separator) continue; + + if (separator < sublength) { + records[parsed].key.str = strdata; + records[parsed].key.length = separator; + records[parsed].value.str = strdata + separator + 1; + records[parsed].value.length = sublength - (separator + 1); + } else { + records[parsed].key.str = strdata; + records[parsed].key.length = sublength; + } + + ++parsed; + } + + return parsed; } #ifdef _WIN32 diff --git a/ctrl/facemgr/src/interfaces/dummy/CMakeLists.txt b/ctrl/facemgr/src/interfaces/dummy/CMakeLists.txt index 05276bc5a..c68c39273 100644 --- a/ctrl/facemgr/src/interfaces/dummy/CMakeLists.txt +++ b/ctrl/facemgr/src/interfaces/dummy/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021 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: diff --git a/ctrl/facemgr/src/interfaces/dummy/dummy.c b/ctrl/facemgr/src/interfaces/dummy/dummy.c index 69c336e57..df63eef17 100644 --- a/ctrl/facemgr/src/interfaces/dummy/dummy.c +++ b/ctrl/facemgr/src/interfaces/dummy/dummy.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -19,7 +19,7 @@ */ #include <stdlib.h> -#include <unistd.h> // close +#include <unistd.h> // close #include <hicn/facemgr.h> @@ -36,34 +36,32 @@ * Internal data */ typedef struct { - /* The configuration data will likely be allocated on the stack (or should - * be freed) by the caller, we recommend to make a copy of this data. - * This copy can further be altered with default values. - */ - dummy_cfg_t cfg; + /* The configuration data will likely be allocated on the stack (or should + * be freed) by the caller, we recommend to make a copy of this data. + * This copy can further be altered with default values. + */ + dummy_cfg_t cfg; - /* ... */ + /* ... */ - int fd; /* Sample internal data: file descriptor */ + int fd; /* Sample internal data: file descriptor */ } dummy_data_t; -int dummy_initialize(interface_t * interface, void * cfg) -{ - dummy_data_t * data = malloc(sizeof(dummy_data_t)); - if (!data) - goto ERR_MALLOC; - interface->data = data; - - /* Use default values for unspecified configuration parameters */ - if (cfg) { - data->cfg = *(dummy_cfg_t *)cfg; - } else { - memset(&data->cfg, 0, sizeof(data->cfg)); - } +int dummy_initialize(interface_t *interface, void *cfg) { + dummy_data_t *data = malloc(sizeof(dummy_data_t)); + if (!data) goto ERR_MALLOC; + interface->data = data; + + /* Use default values for unspecified configuration parameters */ + if (cfg) { + data->cfg = *(dummy_cfg_t *)cfg; + } else { + memset(&data->cfg, 0, sizeof(data->cfg)); + } - /* ... */ + /* ... */ - data->fd = 0; + data->fd = 0; #if 0 if (interface_register_fd(interface, data->fd, NULL) < 0) { ERROR("[dummy_initialize] Error registering fd"); @@ -71,49 +69,45 @@ int dummy_initialize(interface_t * interface, void * cfg) } #endif - /* ... */ + /* ... */ - /* - * We should return a negative value in case of error, and a positive value - * otherwise: - * - a file descriptor (>0) will be added to the event loop; or - * - 0 if we don't use any file descriptor - */ - return 0; + /* + * We should return a negative value in case of error, and a positive value + * otherwise: + * - a file descriptor (>0) will be added to the event loop; or + * - 0 if we don't use any file descriptor + */ + return 0; ERR_FD: ERR_MALLOC: - return -1; + return -1; } -int dummy_finalize(interface_t * interface) -{ - dummy_data_t * data = (dummy_data_t*)interface->data; +int dummy_finalize(interface_t *interface) { + dummy_data_t *data = (dummy_data_t *)interface->data; - if (data->fd > 0) - close(data->fd); + if (data->fd > 0) close(data->fd); - return 0; + return 0; } -int dummy_callback(interface_t * interface) -{ - dummy_data_t * data = (dummy_data_t*)interface->data; - UNUSED(data); +int dummy_callback(interface_t *interface) { + dummy_data_t *data = (dummy_data_t *)interface->data; + UNUSED(data); - /* ... */ + /* ... */ - return 0; + return 0; } -int dummy_on_event(interface_t * interface, facelet_t * facelet) -{ - dummy_data_t * data = (dummy_data_t*)interface->data; - UNUSED(data); +int dummy_on_event(interface_t *interface, facelet_t *facelet) { + dummy_data_t *data = (dummy_data_t *)interface->data; + UNUSED(data); - /* ... */ + /* ... */ - return 0; + return 0; } interface_ops_t dummy_ops = { diff --git a/ctrl/facemgr/src/interfaces/dummy/dummy.h b/ctrl/facemgr/src/interfaces/dummy/dummy.h index 22fe5d1a6..f930ead58 100644 --- a/ctrl/facemgr/src/interfaces/dummy/dummy.h +++ b/ctrl/facemgr/src/interfaces/dummy/dummy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -28,7 +28,7 @@ * Configuration data */ typedef struct { - /* ... */ + /* ... */ } dummy_cfg_t; #endif /* FACEMGR_INTERFACE_DUMMY_H */ diff --git a/ctrl/facemgr/src/interfaces/hicn_light/CMakeLists.txt b/ctrl/facemgr/src/interfaces/hicn_light/CMakeLists.txt index ef839a69c..a0fb3e351 100644 --- a/ctrl/facemgr/src/interfaces/hicn_light/CMakeLists.txt +++ b/ctrl/facemgr/src/interfaces/hicn_light/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021-2022 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: @@ -11,20 +11,23 @@ # See the License for the specific language governing permissions and # limitations under the License. + +############################################################## +# Sources +############################################################## list(APPEND HEADER_FILES ) list(APPEND SOURCE_FILES - ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light.c + ${CMAKE_CURRENT_SOURCE_DIR}/hicn_light.c ) list(APPEND LIBRARIES - ${HICNCTRL_LIBRARIES} + ${LIBHICNCTRL_LIBRARIES} ) - list(APPEND INCLUDE_DIRS - ${HICNCTRL_INCLUDE_DIR} + ${LIBHICNCTRL_INCLUDE_DIR} ) set(SOURCE_FILES ${SOURCE_FILES} PARENT_SCOPE) diff --git a/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c b/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c index b6e0e605a..b396782f5 100644 --- a/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c +++ b/ctrl/facemgr/src/interfaces/hicn_light/hicn_light.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -19,8 +19,8 @@ */ #include <assert.h> #include <stdbool.h> -#include <stdio.h> // snprintf -#include <time.h> // time +#include <stdio.h> // snprintf +#include <time.h> // time #include <hicn/ctrl.h> #include <hicn/facemgr.h> @@ -38,578 +38,636 @@ #define WITH_POLL typedef enum { - HL_STATE_UNDEFINED, - HL_STATE_IDLE, - HL_STATE_ROUTES_SENT, - HL_STATE_ROUTES_RECEIVED, - HL_STATE_FACES_SENT, - HL_STATE_FACES_RECEIVED, - HL_STATE_N + HL_STATE_UNDEFINED, + HL_STATE_IDLE, + HL_STATE_ROUTES_SENT, + HL_STATE_ROUTES_RECEIVED, + HL_STATE_FACES_SENT, + HL_STATE_FACES_RECEIVED, + HL_STATE_N } hl_state_t; typedef struct { - hc_sock_t * s; /* NULL means no active socket */ - hl_state_t state; + hc_sock_t *s; /* NULL means no active socket */ - /* Timer used for forwarder reconnection */ - int reconnect_timer_fd; /* 0 means no active timer */ + /* Socket for polling, dependent on s */ + hc_sock_t *sp; /* NULL means no active socket */ - /* Timer used to periodically poll the forwarder face and routing tables */ - int poll_timer_fd; - hc_data_t * polled_routes; -} hl_data_t; + hl_state_t state; + + /* Timer used for forwarder reconnection */ + int reconnect_timer_fd; /* 0 means no active timer */ -/* Forward declarations */ -int hl_timeout(interface_t * interface, int fd, void * unused); + /* Timer used to periodically poll the forwarder face and routing tables */ + int poll_timer_fd; + hc_data_t *polled_routes; +} hl_data_t; #ifdef WITH_POLL -int hl_process_state(interface_t * interface, int fd, void * unused) +int hl_process_state(interface_t *interface, int fd, void *unused); #else -int hl_process_state(interface_t * interface) +int hl_process_state(interface_t *interface); #endif -{ - hl_data_t * data = (hl_data_t *)interface->data; - - /* - * Every tick we need to probe the forwarder for the list of faces and - * associated routes. - * - * This is used to guess manually added faces and routes - * - * TODO ensure we are idle at tick time - */ - - switch(data->state) - { - case HL_STATE_IDLE: - assert(!data->polled_routes); - - //DEBUG("[hl_process_state] Querying route list"); - if (hc_route_list_async(data->s) < 0) { - DEBUG("[hl_process_state] Error querying route list"); - return -1; - } - data->state = HL_STATE_ROUTES_SENT; - break; +void start_poll_timer(interface_t *interface) { + hl_data_t *data = (hl_data_t *)interface->data; - case HL_STATE_ROUTES_RECEIVED: - //DEBUG("[hl_process_state] Querying face list"); - if (hc_face_list_async(data->s) < 0) { - DEBUG("[hl_process_state] Error querying face list"); - return -1; - } - data->state = HL_STATE_FACES_SENT; - break; - - case HL_STATE_FACES_RECEIVED: - data->state = HL_STATE_IDLE; - break; - - case HL_STATE_ROUTES_SENT: - case HL_STATE_FACES_SENT: - INFO("[hl_process_state] Out of sync... resetting state"); - if (data->polled_routes) { - hc_data_free(data->polled_routes); - data->polled_routes = NULL; - } - data->state = HL_STATE_IDLE; - break; + data->poll_timer_fd = interface_register_timer(interface, INTERVAL_MS, + hl_process_state, interface); + if (data->poll_timer_fd < 0) { + ERROR("[start_poll_timer) Could not start polling timer"); + } +} - case HL_STATE_UNDEFINED: - case HL_STATE_N: - ERROR("[hl_process_state] Unexpected state"); - return -1; - } +void stop_poll_timer(interface_t *interface) { + hl_data_t *data = (hl_data_t *)interface->data; - return 0; + if (data->poll_timer_fd > 0) + if (interface_unregister_timer(interface, data->poll_timer_fd) < 0) { + ERROR("[stop_poll_timer] Could not stop polling timer"); + } } - -int -hl_after_connect(interface_t * interface) +#ifdef WITH_POLL +int hl_process_state(interface_t *interface, int fd, void *unused) +#else +int hl_process_state(interface_t *interface) +#endif { - hl_data_t * data = interface->data; + hl_data_t *data = (hl_data_t *)interface->data; + + /* + * Every tick we need to probe the forwarder for the list of faces and + * associated routes. + * + * This is used to guess manually added faces and routes + * + * TODO ensure we are idle at tick time + */ + + switch (data->state) { + case HL_STATE_IDLE: + assert(!data->polled_routes); + stop_poll_timer(interface); + + // DEBUG("[hl_process_state] Querying route list"); + if (hc_route_list_async(data->sp) < 0) { + DEBUG("[hl_process_state] Error querying route list"); + return -1; + } + data->state = HL_STATE_ROUTES_SENT; + break; + + case HL_STATE_ROUTES_RECEIVED: + // DEBUG("[hl_process_state] Querying face list"); + if (hc_face_list_async(data->sp) < 0) { + DEBUG("[hl_process_state] Error querying face list"); + return -1; + } + data->state = HL_STATE_FACES_SENT; + break; + + case HL_STATE_FACES_RECEIVED: + data->state = HL_STATE_IDLE; + start_poll_timer(interface); + break; + + case HL_STATE_ROUTES_SENT: + case HL_STATE_FACES_SENT: + WARN("[hl_process_state] Out of sync... resetting state"); + if (data->polled_routes) { + hc_data_free(data->polled_routes); + data->polled_routes = NULL; + } + data->state = HL_STATE_IDLE; + start_poll_timer(interface); + break; + + case HL_STATE_UNDEFINED: + case HL_STATE_N: + ERROR("[hl_process_state] Unexpected state"); + return -1; + } + + return 0; +} - /* File descriptor for control socket operations */ - if (interface_register_fd(interface, hc_sock_get_fd(data->s), NULL) < 0) { - ERROR("[hc_connect] Error registering fd"); - goto ERR_FD; - } +/* + * Called whenever a connection to both sockets succeeds. + * Polling will be useful to detect when connection to the forwarder is lost, + * and will allow to try reconnect both sockets (the control socket being UDP / + * in blocking mode will not detect such loss of connection). Operations on the + * control socket that will fail will be reattempted by higher layers. + */ +int hl_after_connect(interface_t *interface) { + hl_data_t *data = interface->data; - /* We always restart from the idle phase */ - data->state = HL_STATE_IDLE; + /* File descriptor for polling socket operations */ + if (interface_register_fd(interface, hc_sock_get_fd(data->sp), NULL) < 0) { + ERROR("[hc_connect] Error registering fd"); + goto ERR_FD; + } + /* We always restart from the idle phase */ + data->state = HL_STATE_IDLE; /* poll will replace the original get, ideally we would get notifications */ #ifdef WITH_POLL - data->poll_timer_fd = interface_register_timer(interface, INTERVAL_MS, - hl_process_state, interface); - if (data->poll_timer_fd < 0) { - ERROR("[hc_connect] Could not initialize polling timer"); - return -1; - } + start_poll_timer(interface); #else - hl_process_state(interface); + hl_process_state(interface); #endif - return 0; + return 0; - //interface_unregister_fd(interface, hc_sock_get_fd(data->s)); + // interface_unregister_fd(interface, hc_sock_get_fd(data->sp)); ERR_FD: - return -1; + return -1; } -int _hl_connect(interface_t * interface); +int _hl_connect(interface_t *interface); -int -hl_connect_timeout(interface_t * interface, int fd, void * unused) -{ - hl_data_t * data = interface->data; - assert(fd == data->reconnect_timer_fd); - _unused(data); +int hl_connect_timeout(interface_t *interface, int fd, void *unused) { + hl_data_t *data = interface->data; + assert(fd == data->reconnect_timer_fd); + _unused(data); - int rc = _hl_connect(interface); - if (rc < 0) { - DEBUG("[hl_initialize] Error during connection reattempt; next attempt in %ds", INTERVAL_MS / 1000); - return -1; - } + int rc = _hl_connect(interface); + if (rc < 0) { + DEBUG( + "[hl_initialize] Error during connection reattempt; next attempt in " + "%ds", + INTERVAL_MS / 1000); + return -1; + } - if (interface_unregister_timer(interface, fd) < 0) { - ERROR("[hl_connect_timeout] Could not cancel timer after successful connect"); - } + if (interface_unregister_timer(interface, fd) < 0) { + ERROR( + "[hl_connect_timeout] Could not cancel timer after successful connect"); + } - /* Connect success */ - return hl_after_connect(interface); + /* Connect success */ + return hl_after_connect(interface); } - -int -_hl_connect(interface_t * interface) -{ - hl_data_t * data = interface->data; - assert(!data->s); - - data->s = hc_sock_create(); - if (data->s <= 0) { - ERROR("[hc_connect] Could not create control socket"); - goto ERR_SOCK; - } - - if (hc_sock_connect(data->s) < 0) { - DEBUG("[hc_connect] Could not connect control socket"); - goto ERR_CONNECT; - } - - return 0; - +/* + * Connection without reattempt. Both control and polling sockets should be + * connected to succeed. + */ +int _hl_connect(interface_t *interface) { + hl_data_t *data = interface->data; + assert(!data->s); + assert(!data->sp); + + data->s = hc_sock_create(); + if (data->s <= 0) { + ERROR("[hc_connect] Could not create control socket"); + goto ERR_SOCK; + } + + if (hc_sock_connect(data->s) < 0) { + DEBUG("[hc_connect] Could not connect control socket"); + goto ERR_CONNECT; + } + + data->sp = hc_sock_create(); + if (data->sp <= 0) { + ERROR("[hc_connect] Could not create polling socket"); + goto ERR_SOCK_POLL; + } + + if (hc_sock_connect(data->sp) < 0) { + DEBUG("[hc_connect] Could not connect polling socket"); + goto ERR_CONNECT_POLL; + } + + return 0; + +ERR_CONNECT_POLL: + hc_sock_free(data->sp); + data->sp = NULL; +ERR_SOCK_POLL: ERR_CONNECT: - hc_sock_free(data->s); - data->s = NULL; + hc_sock_free(data->s); + data->s = NULL; ERR_SOCK: - return -1; - + return -1; } -int hl_disconnect(interface_t * interface) -{ - hl_data_t * data = (hl_data_t *) interface->data; - if (data->reconnect_timer_fd > 0) - interface_unregister_timer(interface, data->reconnect_timer_fd); +int hl_disconnect(interface_t *interface) { + hl_data_t *data = (hl_data_t *)interface->data; + if (data->reconnect_timer_fd > 0) + interface_unregister_timer(interface, data->reconnect_timer_fd); - if (data->poll_timer_fd > 0) - interface_unregister_timer(interface, data->poll_timer_fd); + stop_poll_timer(interface); - if (data->polled_routes) - hc_data_free(data->polled_routes); + if (data->polled_routes) hc_data_free(data->polled_routes); - if (data->s) { - interface_unregister_fd(interface, hc_sock_get_fd(data->s)); - hc_sock_free(data->s); - } + if (data->s) { + hc_sock_free(data->s); + data->s = NULL; + } - return 0; + if (data->sp) { + interface_unregister_fd(interface, hc_sock_get_fd(data->sp)); + hc_sock_free(data->sp); + data->sp = NULL; + } + + return 0; } -int -hl_connect(interface_t * interface) -{ - hl_data_t * data = interface->data; +/* Connection with reattempts */ +int hl_connect(interface_t *interface) { + hl_data_t *data = interface->data; - if (_hl_connect(interface) >= 0) - return hl_after_connect(interface); + if (_hl_connect(interface) >= 0) return hl_after_connect(interface); - /* Timer for managing the connection to the forwarder */ - DEBUG("Connection to forwarder failed... next retry in %ds", INTERVAL_MS / 1000); - data->reconnect_timer_fd = interface_register_timer(interface, INTERVAL_MS, hl_connect_timeout, NULL); - if (data->reconnect_timer_fd < 0) { - ERROR("[hc_connect] Could not initialize reattempt timer"); - return -1; - } + /* Timer for managing the connection to the forwarder */ + DEBUG("Connection to forwarder failed... next retry in %ds", + INTERVAL_MS / 1000); + data->reconnect_timer_fd = interface_register_timer(interface, INTERVAL_MS, + hl_connect_timeout, NULL); + if (data->reconnect_timer_fd < 0) { + ERROR("[hc_connect] Could not initialize reattempt timer"); + return -1; + } - return 0; + return 0; } -int -hl_initialize(interface_t * interface, void * cfg) -{ - hl_data_t * data = malloc(sizeof(hl_data_t)); - if (!data) { - ERROR("[hicn_light] Out of memory!"); - goto ERR_MALLOC; - } - - data->s = NULL; - data->reconnect_timer_fd = 0; - data->poll_timer_fd = 0; +int hl_initialize(interface_t *interface, void *cfg) { + hl_data_t *data = malloc(sizeof(hl_data_t)); + if (!data) { + ERROR("[hicn_light] Out of memory!"); + goto ERR_MALLOC; + } - interface->data = data; + data->s = NULL; + data->sp = NULL; + data->reconnect_timer_fd = 0; + data->poll_timer_fd = 0; + data->polled_routes = NULL; + data->state = HL_STATE_UNDEFINED; - if (hl_connect(interface) < 0) { - ERROR("[hl_initialize] Error during connection to forwarder"); - goto ERR_CONNECT; - } + interface->data = data; - data->polled_routes = NULL; + /* Connect both control and polling sockets */ + if (hl_connect(interface) < 0) { + ERROR("[hl_initialize] Error during connection to forwarder"); + goto ERR_CONNECT; + } - return 0; + return 0; ERR_CONNECT: - free(data); + free(data); ERR_MALLOC: - return -1; + return -1; } -int hl_finalize(interface_t * interface) -{ - hl_data_t * data = (hl_data_t *) interface->data; +int hl_finalize(interface_t *interface) { + hl_data_t *data = (hl_data_t *)interface->data; - hl_disconnect(interface); + hl_disconnect(interface); - if (data->polled_routes) - hc_data_free(data->polled_routes); + if (data->polled_routes) hc_data_free(data->polled_routes); - free(data); + free(data); - return 0; + return 0; } -int hl_on_event(interface_t * interface, facelet_t * facelet) -{ - hc_face_t hc_face; - hc_route_t route; - int rc; - int ret = 0; - hl_data_t * data = (hl_data_t *)interface->data; - face_t * face = NULL; - - hc_face.id = 0; - memset(hc_face.name, 0, sizeof(hc_face.name)); - - - /* NOTE - * - One example where this fails (and it is normal) is when we delete a - * face that was not completely created, because for instance bonjour did - * not give any data - */ - if (facelet_get_face(facelet, &face) < 0) { - ERROR("Could not retrieve face from facelet"); - ret = -FACELET_ERROR_REASON_INTERNAL_ERROR; - goto ERR_FACE; +int hl_on_event(interface_t *interface, facelet_t *facelet) { + hc_face_t hc_face; + hc_route_t route; + int rc; + int ret = 0; + hl_data_t *data = (hl_data_t *)interface->data; + face_t *face = NULL; + + hc_face.id = 0; + memset(hc_face.name, 0, sizeof(hc_face.name)); + + /* NOTE + * - One example where this fails (and it is normal) is when we delete a + * face that was not completely created, because for instance bonjour did + * not give any data + */ + if (facelet_get_face(facelet, &face) < 0) { + ERROR("Could not retrieve face from facelet"); + ret = -FACELET_ERROR_REASON_INTERNAL_ERROR; + goto ERR_FACE; + } + + if (!data->s) { + /* We are not connected to the forwarder */ + ret = -FACELET_ERROR_REASON_FORWARDER_OFFLINE; + goto ERR; + } + + switch (facelet_get_event(facelet)) { + case FACELET_EVENT_CREATE: { + /* Create face */ + char buf[MAXSZ_FACELET]; + facelet_snprintf(buf, MAXSZ_FACELET, facelet); + DEBUG("Create facelet %s", buf); + + hc_face.face = *face; + rc = hc_face_create(data->s, &hc_face); + if (rc < 0) { + ERROR("Failed to create face\n"); + ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; + goto ERR; + } + INFO("Created face id=%d - %s", hc_face.id, buf); } - if (!data->s) { - /* We are not connected to the forwarder */ - ret = -FACELET_ERROR_REASON_FORWARDER_OFFLINE; + hicn_route_t **route_array; + int n = facelet_get_route_array(facelet, &route_array); + if (n < 0) { + ERROR("Failed to create default hICN/IPv4 route"); + ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; goto ERR; - } + } + if (n == 0) { + /* Adding default routes */ + route = (hc_route_t){ + .face_id = hc_face.id, + .family = AF_INET, + .remote_addr = IPV4_ANY, + .len = 0, + .cost = DEFAULT_ROUTE_COST, + + }; + if (hc_route_create(data->s, &route) < 0) { + ERROR("Failed to create default hICN/IPv4 route"); + ret = -1; + } - switch(facelet_get_event(facelet)) { - - case FACELET_EVENT_CREATE: - { - /* Create face */ - char buf[MAXSZ_FACELET]; - facelet_snprintf(buf, MAXSZ_FACELET, facelet); - DEBUG("Create facelet %s", buf); - - hc_face.face = *face; - rc = hc_face_create(data->s, &hc_face); - if (rc < 0) { - ERROR("Failed to create face\n"); - ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; - goto ERR; - } - INFO("Created face id=%d - %s", hc_face.id, buf); - } + route = (hc_route_t){ + .face_id = hc_face.id, + .family = AF_INET6, + .remote_addr = IPV6_ANY, + .len = 0, + .cost = DEFAULT_ROUTE_COST, + }; + if (hc_route_create(data->s, &route) < 0) { + ERROR("Failed to create default hICN/IPv6 route"); + ret = -1; + } - hicn_route_t ** route_array; - int n = facelet_get_route_array(facelet, &route_array); - if (n < 0) { - ERROR("Failed to create default hICN/IPv4 route"); - ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; - goto ERR; - } - if (n == 0) { - /* Adding default routes */ - route = (hc_route_t) { - .face_id = hc_face.id, - .family = AF_INET, - .remote_addr = IPV4_ANY, - .len = 0, - .cost = DEFAULT_ROUTE_COST, - - }; - if (hc_route_create(data->s, &route) < 0) { - ERROR("Failed to create default hICN/IPv4 route"); - ret = -1; - } - - route = (hc_route_t) { - .face_id = hc_face.id, - .family = AF_INET6, - .remote_addr = IPV6_ANY, - .len = 0, - .cost = DEFAULT_ROUTE_COST, - }; - if (hc_route_create(data->s, &route) < 0) { - ERROR("Failed to create default hICN/IPv6 route"); - ret = -1; - } - - INFO("Successfully created default route(s)."); - } else { - for (unsigned i = 0; i < n; i++) { - hicn_route_t * hicn_route = route_array[i]; - ip_prefix_t prefix; - int cost; - if (hicn_route_get_prefix(hicn_route, &prefix) < 0) { - ERROR("Failed to get route prefix"); - ret = -1; - continue; - } - if (hicn_route_get_cost(hicn_route, &cost) < 0) { - ERROR("Failed to get route cost"); - ret = -1; - continue; - } - route = (hc_route_t) { - .face_id = hc_face.id, - .family = prefix.family, - .remote_addr = prefix.address, - .len = prefix.len, - .cost = cost, - }; - if (hc_route_create(data->s, &route) < 0) { - ERROR("Failed to create static route route"); - ret = -1; - continue; - } - } - } - free(route_array); - - break; - - case FACELET_EVENT_DELETE: - /* Removing a face should also remove associated routes */ - hc_face.face = *face; - rc = hc_face_delete(data->s, &hc_face); - if (rc < 0) { - ERROR("Failed to delete face\n"); - ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; - goto ERR; - } + INFO("Successfully created default route(s)."); + } else { + for (unsigned i = 0; i < n; i++) { + hicn_route_t *hicn_route = route_array[i]; + ip_prefix_t prefix; + int cost; + if (hicn_route_get_prefix(hicn_route, &prefix) < 0) { + ERROR("Failed to get route prefix"); + ret = -1; + continue; + } + if (hicn_route_get_cost(hicn_route, &cost) < 0) { + ERROR("Failed to get route cost"); + ret = -1; + continue; + } + route = (hc_route_t){ + .face_id = hc_face.id, + .name = "", /* take face_id into account */ + .family = prefix.family, + .remote_addr = prefix.address, + .len = prefix.len, + .cost = cost, + }; + if (hc_route_create(data->s, &route) < 0) { + ERROR("Failed to create static route route"); + ret = -1; + continue; + } + } + } + free(route_array); + + break; + + case FACELET_EVENT_DELETE: + /* Removing a face should also remove associated routes */ + hc_face.face = *face; + rc = hc_face_delete(data->s, &hc_face, 1); + if (rc < 0) { + ERROR("Failed to delete face\n"); + ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; + goto ERR; + } + + char buf[MAXSZ_FACELET]; + facelet_snprintf(buf, MAXSZ_FACELET, facelet); + INFO("Deleted face id=%d", hc_face.id); + + break; + + case FACELET_EVENT_UPDATE: + /* Currently, only admin_state & priority are supported */ + if (facelet_get_admin_state_status(facelet) == + FACELET_ATTR_STATUS_DIRTY) { + hc_face.face = *face; + hc_face_t *face_found; + + rc = hc_face_get(data->s, &hc_face, &face_found); + if (rc < 0) { + ERROR("Failed to find face\n"); + ret = -FACELET_ERROR_REASON_INTERNAL_ERROR; + goto ERR; + } + if (!face_found) { + ERROR("Face to update has not been found"); + ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; + goto ERR; + } + char conn_id_or_name[SYMBOLIC_NAME_LEN]; + snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", face_found->id); + free(face_found); + + face_state_t admin_state; + if (facelet_get_admin_state(facelet, &admin_state) < 0) { + ERROR("Failed to retrieve facelet admin state"); + ret = -FACELET_ERROR_REASON_INTERNAL_ERROR; + goto ERR; + } - char buf[MAXSZ_FACELET]; - facelet_snprintf(buf, MAXSZ_FACELET, facelet); - INFO("Deleted face id=%d", hc_face.id); - - break; - - case FACELET_EVENT_UPDATE: - /* Currently, only admin_state & priority are supported */ - if (facelet_get_admin_state_status(facelet) == FACELET_ATTR_STATUS_DIRTY) { - hc_face.face = *face; - hc_face_t * face_found; - - rc = hc_face_get(data->s, &hc_face, &face_found); - if (rc < 0) { - ERROR("Failed to find face\n"); - ret = -FACELET_ERROR_REASON_INTERNAL_ERROR; - goto ERR; - } - if (!face_found) { - ERROR("Face to update has not been found"); - ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; - goto ERR; - } - char conn_id_or_name[SYMBOLIC_NAME_LEN]; - snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", face_found->id); - free(face_found); - - face_state_t admin_state; - if (facelet_get_admin_state(facelet, &admin_state) < 0) { - ERROR("Failed to retrieve facelet admin state"); - ret = -FACELET_ERROR_REASON_INTERNAL_ERROR; - goto ERR; - } - - if (hc_connection_set_admin_state(data->s, conn_id_or_name, admin_state) < 0) { - ERROR("Failed to update admin state"); - ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; - goto ERR; - } - facelet_set_admin_state_status(facelet, FACELET_ATTR_STATUS_CLEAN); - INFO("Updated face id=%d - admin_state=%s", hc_face.id, - face_state_str[admin_state]); - } + if (hc_connection_set_admin_state(data->s, conn_id_or_name, + admin_state) < 0) { + ERROR("Failed to update admin state"); + ret = -FACELET_ERROR_REASON_UNSPECIFIED_ERROR; + goto ERR; + } + facelet_set_admin_state_status(facelet, FACELET_ATTR_STATUS_CLEAN); + INFO("Updated face id=%d - admin_state=%s", hc_face.id, + face_state_str(admin_state)); + } #ifdef WITH_POLICY - if (facelet_get_netdevice_type_status(facelet) == FACELET_ATTR_STATUS_DIRTY) { - hc_face.face = *face; - hc_face_t * face_found; - - rc = hc_face_get(data->s, &hc_face, &face_found); - if (rc < 0) { - ERROR("Failed to find face\n"); - goto ERR; - } - if (!face_found) { - ERROR("Face to update has not been found"); - goto ERR; - } - char conn_id_or_name[SYMBOLIC_NAME_LEN]; - snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", face_found->id); - free(face_found); - - netdevice_type_t netdevice_type; - if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) { - ERROR("Failed to retrieve facelet netdevice_type"); - goto ERR; - } - - /* Encode netdevice type into tags */ - policy_tags_t tags = POLICY_TAGS_EMPTY; - if (facelet_has_netdevice_type(facelet)) { - netdevice_type_t netdevice_type; - if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) { - ERROR("error getting netdevice_type"); - goto ERR; - } - - - switch(netdevice_type) { - case NETDEVICE_TYPE_UNDEFINED: - case NETDEVICE_TYPE_LOOPBACK: - break; - case NETDEVICE_TYPE_WIRED: - policy_tags_add(&tags, POLICY_TAG_WIRED); - break; - case NETDEVICE_TYPE_WIFI: - policy_tags_add(&tags, POLICY_TAG_WIFI); - break; - case NETDEVICE_TYPE_CELLULAR: - policy_tags_add(&tags, POLICY_TAG_CELLULAR); - break; - default: - goto ERR; - } - } - //face->tags = tags; - - if (hc_connection_set_tags(data->s, conn_id_or_name, tags) < 0) { - ERROR("Failed to update tags"); - goto ERR; - } - facelet_set_netdevice_type_status(facelet, FACELET_ATTR_STATUS_CLEAN); - INFO("Updated face id=%d - netdevice_type=%s", hc_face.id, - netdevice_type_str[netdevice_type]); - } - if (facelet_get_priority_status(facelet) == FACELET_ATTR_STATUS_DIRTY) { - INFO("Updating priority..."); - hc_face.face = *face; - hc_face_t * face_found; - - rc = hc_face_get(data->s, &hc_face, &face_found); - if (rc < 0) { - ERROR("Failed to find face\n"); - goto ERR; - } - if (!face_found) { - ERROR("Face to update has not been found"); - goto ERR; - } - char conn_id_or_name[SYMBOLIC_NAME_LEN]; - snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", face_found->id); - free(face_found); - - uint32_t priority; - if (facelet_get_priority(facelet, &priority) < 0) { - ERROR("Failed to retrieve facelet priority"); - goto ERR; - } - - INFO("Changing connection %s priority to %d", conn_id_or_name, priority); - if (hc_connection_set_priority(data->s, conn_id_or_name, priority) < 0) { - ERROR("Failed to update priority"); - goto ERR; - } - facelet_set_priority_status(facelet, FACELET_ATTR_STATUS_CLEAN); - - INFO("Updated face id=%d - priority=%d", hc_face.id, priority); - } -#endif /* WITH_POLICY */ - break; + if (facelet_get_netdevice_type_status(facelet) == + FACELET_ATTR_STATUS_DIRTY) { + hc_face.face = *face; + hc_face_t *face_found; + + rc = hc_face_get(data->s, &hc_face, &face_found); + if (rc < 0) { + ERROR("Failed to find face\n"); + goto ERR; + } + if (!face_found) { + ERROR("Face to update has not been found"); + goto ERR; + } + char conn_id_or_name[SYMBOLIC_NAME_LEN]; + snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", face_found->id); + free(face_found); + + netdevice_type_t netdevice_type; + if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) { + ERROR("Failed to retrieve facelet netdevice_type"); + goto ERR; + } - default: - ERROR("Unknown event %s\n", facelet_event_str[facelet_get_event(facelet)]); - /* Unsupported events */ - ret = -FACELET_ERROR_REASON_INTERNAL_ERROR; + /* Encode netdevice type into tags */ + policy_tags_t tags = POLICY_TAGS_EMPTY; + if (facelet_has_netdevice_type(facelet)) { + netdevice_type_t netdevice_type; + if (facelet_get_netdevice_type(facelet, &netdevice_type) < 0) { + ERROR("error getting netdevice_type"); goto ERR; - } + } + + switch (netdevice_type) { + case NETDEVICE_TYPE_UNDEFINED: + case NETDEVICE_TYPE_LOOPBACK: + break; + case NETDEVICE_TYPE_WIRED: + policy_tags_add(&tags, POLICY_TAG_WIRED); + break; + case NETDEVICE_TYPE_WIFI: + policy_tags_add(&tags, POLICY_TAG_WIFI); + break; + case NETDEVICE_TYPE_CELLULAR: + policy_tags_add(&tags, POLICY_TAG_CELLULAR); + break; + default: + goto ERR; + } + } + // face->tags = tags; + + if (hc_connection_set_tags(data->s, conn_id_or_name, tags) < 0) { + ERROR("Failed to update tags"); + goto ERR; + } + facelet_set_netdevice_type_status(facelet, FACELET_ATTR_STATUS_CLEAN); + INFO("Updated face id=%d - netdevice_type=%s", hc_face.id, + netdevice_type_str(netdevice_type)); + } + if (facelet_get_priority_status(facelet) == FACELET_ATTR_STATUS_DIRTY) { + INFO("Updating priority..."); + hc_face.face = *face; + hc_face_t *face_found; + + rc = hc_face_get(data->s, &hc_face, &face_found); + if (rc < 0) { + ERROR("Failed to find face\n"); + goto ERR; + } + if (!face_found) { + ERROR("Face to update has not been found"); + goto ERR; + } + char conn_id_or_name[SYMBOLIC_NAME_LEN]; + snprintf(conn_id_or_name, SYMBOLIC_NAME_LEN, "%d", face_found->id); + free(face_found); + + uint32_t priority; + if (facelet_get_priority(facelet, &priority) < 0) { + ERROR("Failed to retrieve facelet priority"); + goto ERR; + } + + INFO("Changing connection %s priority to %d", conn_id_or_name, + priority); + if (hc_connection_set_priority(data->s, conn_id_or_name, priority) < + 0) { + ERROR("Failed to update priority"); + goto ERR; + } + facelet_set_priority_status(facelet, FACELET_ATTR_STATUS_CLEAN); + + INFO("Updated face id=%d - priority=%d", hc_face.id, priority); + } +#endif /* WITH_POLICY */ + break; + + default: + ERROR("Unknown event %s\n", + facelet_event_str[facelet_get_event(facelet)]); + /* Unsupported events */ + ret = -FACELET_ERROR_REASON_INTERNAL_ERROR; + goto ERR; + } ERR: - face_free(face); + face_free(face); ERR_FACE: - return ret; + return ret; } -int hl_callback(interface_t * interface, int fd, void * unused) -{ - hl_data_t * data = (hl_data_t*)interface->data; - hc_data_t * results; - int ret = 0; - - /* In case of error, reconnect to forwarder */ - if (hc_sock_callback(data->s, &results) < 0) { - DEBUG("Closing socket... reconnecting..."); - if (interface_unregister_fd(interface, hc_sock_get_fd(data->s)) < 0) { - ERROR("[hl_callback] Error unregistering fd"); - } - - /* Stopping poll timer */ - if (interface_unregister_timer(interface, data->poll_timer_fd) < 0) { - ERROR("[hl_callback] Could not cancel polling timer after forwarder disconnect"); - } - if (data->polled_routes) - hc_data_free(data->polled_routes); +/* + * This should only receive data from the polling socket which is asynchronous, + * while all face creation, etc. operations are done synchronously in this + * version. + */ +int hl_callback(interface_t *interface, int fd, void *unused) { + hl_data_t *data = (hl_data_t *)interface->data; + hc_data_t *results; + int ret = 0; + + /* Workaround: sometimes this is called with data = NULL */ + if (!data) { + INFO("[hl_callback] no data"); + return 0; + } - hc_sock_free(data->s); - data->s = NULL; - hl_connect(interface); - return ret; + /* In case of error, reconnect to forwarder */ + if (hc_sock_callback(data->sp, &results) < 0) { + INFO("Closing socket... reconnecting..."); + if (interface_unregister_fd(interface, hc_sock_get_fd(data->sp)) < 0) { + ERROR("[hl_callback] Error unregistering fd"); } - /* Shall we wait for more data ? */ - if (!results->complete) - return ret; + /* Stopping poll timer */ + stop_poll_timer(interface); + if (data->polled_routes) hc_data_free(data->polled_routes); - /* Process returned data */ - switch(data->state) { + hc_sock_free(data->s); + data->s = NULL; + hc_sock_free(data->sp); + data->sp = NULL; - case HL_STATE_ROUTES_SENT: - //DEBUG("[hl_callback] Processing routes"); - data->polled_routes = results; + hl_connect(interface); + return ret; + } + + /* Shall we wait for more data ? */ + if (!results->complete) { + INFO("[hl_callback] results incomplete"); + return ret; + } + + /* Process returned data */ + // DEBUG("Processing data"); + switch (data->state) { + case HL_STATE_ROUTES_SENT: + // DEBUG("[hl_callback] Processing routes"); + data->polled_routes = results; #if 0 foreach_route(r, results) { @@ -622,19 +680,17 @@ int hl_callback(interface_t * interface, int fd, void * unused) DEBUG("Route: %s", buf); } #endif - data->state = HL_STATE_ROUTES_RECEIVED; - if (hl_process_state(interface, fd, unused) < 0) { - ERROR("[hl_callback] Error processing state after routes received"); - ret = -1; - } - break; - - - case HL_STATE_FACES_SENT: - //DEBUG("[hl_callback] Processing faces"); - assert(data->polled_routes); - foreach_face(f, results) { - + data->state = HL_STATE_ROUTES_RECEIVED; + if (hl_process_state(interface, fd, unused) < 0) { + ERROR("[hl_callback] Error processing state after routes received"); + ret = -1; + } + break; + + case HL_STATE_FACES_SENT: + // DEBUG("[hl_callback] Processing faces"); + assert(data->polled_routes); + foreach_face(f, results) { #if 0 char buf[MAXSZ_FACE]; int rc = hc_face_snprintf(buf, MAXSZ_FACE, f); @@ -646,17 +702,16 @@ int hl_callback(interface_t * interface, int fd, void * unused) DEBUG("Face: %s", buf); #endif - /* We can ignore faces on localhost */ + /* We can ignore faces on localhost */ - facelet_t * facelet = facelet_create_from_face(&f->face); - if (!facelet) { - ERROR("[hl_callback] Could not create facelet... skipping"); - continue; - } + facelet_t *facelet = facelet_create_from_face(&f->face); + if (!facelet) { + ERROR("[hl_callback] Could not create facelet... skipping"); + continue; + } - foreach_route(r, data->polled_routes) { - if (r->face_id != f->id) - continue; + foreach_route(r, data->polled_routes) { + if (r->face_id != f->id) continue; #if 0 char route_s[MAXSZ_HC_ROUTE]; @@ -668,41 +723,40 @@ int hl_callback(interface_t * interface, int fd, void * unused) DEBUG("Associated route: %s", route_s); #endif - if (r->len == 0) - continue; - - ip_prefix_t prefix = { - .family = r->family, - .address = r->remote_addr, - .len = r->len, - }; - hicn_route_t * route = hicn_route_create(&prefix, r->face_id, r->cost); - facelet_add_route(facelet, route); - } + if (r->len == 0) continue; - facelet_set_event(facelet, FACELET_EVENT_GET); - interface_raise_event(interface, facelet); - } - hc_data_free(results); - hc_data_free(data->polled_routes); - data->polled_routes = NULL; - data->state = HL_STATE_FACES_RECEIVED; - if (hl_process_state(interface, fd, unused) < 0) { - ERROR("[hl_callback] Error processing state after faces received"); - ret = -1; - } - break; - - case HL_STATE_IDLE: - case HL_STATE_FACES_RECEIVED: - case HL_STATE_ROUTES_RECEIVED: - case HL_STATE_UNDEFINED: - case HL_STATE_N: - ERROR("[hl_callback] Unexpected state"); - ret = -1; - } + ip_prefix_t prefix = { + .family = r->family, + .address = r->remote_addr, + .len = r->len, + }; + hicn_route_t *route = hicn_route_create(&prefix, r->face_id, r->cost); + facelet_add_route(facelet, route); + } - return ret; + facelet_set_event(facelet, FACELET_EVENT_GET); + interface_raise_event(interface, facelet); + } + hc_data_free(results); + hc_data_free(data->polled_routes); + data->polled_routes = NULL; + data->state = HL_STATE_FACES_RECEIVED; + if (hl_process_state(interface, fd, unused) < 0) { + ERROR("[hl_callback] Error processing state after faces received"); + ret = -1; + } + break; + + case HL_STATE_IDLE: + case HL_STATE_FACES_RECEIVED: + case HL_STATE_ROUTES_RECEIVED: + case HL_STATE_UNDEFINED: + case HL_STATE_N: + ERROR("[hl_callback] Unexpected state"); + ret = -1; + } + + return ret; } const interface_ops_t hicn_light_ops = { diff --git a/ctrl/facemgr/src/interfaces/netlink/CMakeLists.txt b/ctrl/facemgr/src/interfaces/netlink/CMakeLists.txt index 7f44d87fe..5d46cb8b6 100644 --- a/ctrl/facemgr/src/interfaces/netlink/CMakeLists.txt +++ b/ctrl/facemgr/src/interfaces/netlink/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021 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: diff --git a/ctrl/facemgr/src/interfaces/netlink/netlink.c b/ctrl/facemgr/src/interfaces/netlink/netlink.c index a1affd719..11738d7ac 100644 --- a/ctrl/facemgr/src/interfaces/netlink/netlink.c +++ b/ctrl/facemgr/src/interfaces/netlink/netlink.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -20,9 +20,9 @@ #include <assert.h> #include <linux/rtnetlink.h> -#include <net/if_arp.h> // ARPHRD_LOOPBACK -#include <sys/types.h> // getpid -#include <unistd.h> // getpid +#include <net/if_arp.h> // ARPHRD_LOOPBACK +#include <sys/types.h> // getpid +#include <unistd.h> // getpid #include <hicn/facemgr.h> #include <hicn/util/ip_address.h> @@ -32,202 +32,188 @@ #include "../../interface.h" typedef enum { - NL_STATE_UNDEFINED, - NL_STATE_LINK_SENT, - NL_STATE_ADDR_SENT, - NL_STATE_DONE, + NL_STATE_UNDEFINED, + NL_STATE_LINK_SENT, + NL_STATE_ADDR_SENT, + NL_STATE_DONE, } nl_state_t; /* Internal data storage */ typedef struct { - int fd; - nl_state_t state; + int fd; + nl_state_t state; } nl_data_t; -static inline void parse_rtattr(struct rtattr *tb[], int max, struct rtattr *rta, int len, - unsigned short flags) -{ - unsigned short type; - - memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); - while (RTA_OK(rta, len)) { - type = rta->rta_type & ~flags; - if (type <= max) - tb[type] = rta; - rta = RTA_NEXT(rta, len); - } +static inline void parse_rtattr(struct rtattr *tb[], int max, + struct rtattr *rta, int len, + unsigned short flags) { + unsigned short type; + + memset(tb, 0, sizeof(struct rtattr *) * (max + 1)); + while (RTA_OK(rta, len)) { + type = rta->rta_type & ~flags; + if (type <= max) tb[type] = rta; + rta = RTA_NEXT(rta, len); + } } -int nl_process_state(interface_t * interface) -{ - nl_data_t * data = (nl_data_t*)interface->data; - int rc; - - switch(data->state) { - case NL_STATE_UNDEFINED: - { - DEBUG("[nl_process_state] UNDEFINED->LINK_SENT"); - struct { - struct nlmsghdr header; - struct rtgenmsg payload; - } msg2 = { - .header = { - .nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)), - .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP, - .nlmsg_type = RTM_GETLINK, - .nlmsg_pid = getpid(), - .nlmsg_seq = 3, - }, +int nl_process_state(interface_t *interface) { + nl_data_t *data = (nl_data_t *)interface->data; + int rc; + + switch (data->state) { + case NL_STATE_UNDEFINED: { + DEBUG("[nl_process_state] UNDEFINED->LINK_SENT"); + struct { + struct nlmsghdr header; + struct rtgenmsg payload; + } msg2 = {.header = + { + .nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)), + .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP, + .nlmsg_type = RTM_GETLINK, + .nlmsg_pid = getpid(), + .nlmsg_seq = 3, + }, .payload = { .rtgen_family = AF_PACKET, - } - }; - - rc = send(data->fd, &msg2, msg2.header.nlmsg_len, 0); - if (rc < 0) - printf("E: Error sending netlink query\n"); + }}; - data->state = NL_STATE_LINK_SENT; - break; - } - - case NL_STATE_LINK_SENT: - { - DEBUG("[nl_process_state] LINK_SENT->ADDR_SENT"); - /* Issue a first query to receive static state */ - struct { - struct nlmsghdr header; - struct ifaddrmsg payload; - } msg = { - .header = { - .nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)), - .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP, - .nlmsg_type = RTM_GETADDR, - .nlmsg_pid = getpid(), - .nlmsg_seq = 7, - }, - .payload = { - .ifa_family = AF_INET, - } - }; + rc = send(data->fd, &msg2, msg2.header.nlmsg_len, 0); + if (rc < 0) printf("E: Error sending netlink query\n"); - rc = send(data->fd, &msg, msg.header.nlmsg_len, 0); - if (rc < 0) - printf("E: Error sending netlink query\n"); - - data->state = NL_STATE_ADDR_SENT; - break; - } + data->state = NL_STATE_LINK_SENT; + break; + } - case NL_STATE_ADDR_SENT: - { - DEBUG("[nl_process_state] ADDR_SENT->DONE"); - data->state = NL_STATE_DONE; - break; - } + case NL_STATE_LINK_SENT: { + DEBUG("[nl_process_state] LINK_SENT->ADDR_SENT"); + /* Issue a first query to receive static state */ + struct { + struct nlmsghdr header; + struct ifaddrmsg payload; + } msg = {.header = + { + .nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg)), + .nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP, + .nlmsg_type = RTM_GETADDR, + .nlmsg_pid = getpid(), + .nlmsg_seq = 7, + }, + .payload = { + .ifa_family = AF_INET, + }}; + + rc = send(data->fd, &msg, msg.header.nlmsg_len, 0); + if (rc < 0) printf("E: Error sending netlink query\n"); + + data->state = NL_STATE_ADDR_SENT; + break; + } - default: /* NL_STATE_DONE never called */ - break; + case NL_STATE_ADDR_SENT: { + DEBUG("[nl_process_state] ADDR_SENT->DONE"); + data->state = NL_STATE_DONE; + break; } - return 0; + default: /* NL_STATE_DONE never called */ + break; + } + + return 0; } -int nl_initialize(interface_t * interface, void * cfg) -{ - nl_data_t * data = malloc(sizeof(nl_data_t)); - if (!data) - goto ERR_MALLOC; +int nl_initialize(interface_t *interface, void *cfg) { + nl_data_t *data = malloc(sizeof(nl_data_t)); + if (!data) goto ERR_MALLOC; - data->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); - if (data->fd < 0) { - ERROR("[nl_initialize] Failed to create netlink socket: %s", (char*)strerror(errno)); - goto ERR_SOCKET; - } + data->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); + if (data->fd < 0) { + ERROR("[nl_initialize] Failed to create netlink socket: %s", + (char *)strerror(errno)); + goto ERR_SOCKET; + } - data->state = NL_STATE_UNDEFINED; + data->state = NL_STATE_UNDEFINED; - struct sockaddr_nl local; // local addr struct - memset(&local, 0, sizeof(local)); - local.nl_family = AF_NETLINK; // set protocol family - // NOTE: RTNLGRP_LINK replaces obsolete RTMGRP_LINK, etc - local.nl_groups = 0 - | RTMGRP_LINK - | RTMGRP_IPV4_IFADDR - | RTMGRP_IPV6_IFADDR + struct sockaddr_nl local; // local addr struct + memset(&local, 0, sizeof(local)); + local.nl_family = AF_NETLINK; // set protocol family + // NOTE: RTNLGRP_LINK replaces obsolete RTMGRP_LINK, etc + local.nl_groups = 0 | RTMGRP_LINK | RTMGRP_IPV4_IFADDR | RTMGRP_IPV6_IFADDR #if 0 | RTMGRP_IPV4_ROUTE; | RTMGRP_IPV6_ROUTE; #endif - ; - local.nl_pid = getpid(); // set out id using current process id + ; + local.nl_pid = getpid(); // set out id using current process id - if (bind(data->fd, (struct sockaddr*)&local, sizeof(local)) < 0) { // bind socket - ERROR("[nl_initialize] Failed to bind netlink socket: %s", (char*)strerror(errno)); - goto ERR_BIND; - } + if (bind(data->fd, (struct sockaddr *)&local, sizeof(local)) < + 0) { // bind socket + ERROR("[nl_initialize] Failed to bind netlink socket: %s", + (char *)strerror(errno)); + goto ERR_BIND; + } - interface->data = data; + interface->data = data; - if (interface_register_fd(interface, data->fd, NULL) < 0) { - ERROR("[nl_initialize] Error registering fd"); - goto ERR_FD; - } + if (interface_register_fd(interface, data->fd, NULL) < 0) { + ERROR("[nl_initialize] Error registering fd"); + goto ERR_FD; + } #if 1 - nl_process_state(interface); + nl_process_state(interface); #endif - return 0; + return 0; ERR_FD: ERR_BIND: - close(data->fd); + close(data->fd); ERR_SOCKET: - free(data); + free(data); ERR_MALLOC: - return -1; + return -1; } -int parse_link(struct nlmsghdr * h, facelet_t ** facelet, - char * interface_name, size_t interface_name_size, - bool * up, bool * running) -{ - struct ifinfomsg *ifi; // structure for network interface info - struct rtattr *tb[IFLA_MAX + 1]; +int parse_link(struct nlmsghdr *h, facelet_t **facelet, char *interface_name, + size_t interface_name_size, bool *up, bool *running) { + struct ifinfomsg *ifi; // structure for network interface info + struct rtattr *tb[IFLA_MAX + 1]; - assert(facelet); + assert(facelet); - ifi = (struct ifinfomsg*) NLMSG_DATA(h); // get information about changed network interface - parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(h), 1<<15); + ifi = (struct ifinfomsg *)NLMSG_DATA( + h); // get information about changed network interface + parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), IFLA_PAYLOAD(h), 1 << 15); - if (interface_name) { - assert(tb[IFLA_IFNAME]); - snprintf(interface_name, interface_name_size, "%s", (char*)RTA_DATA(tb[IFLA_IFNAME])); - } + if (interface_name) { + assert(tb[IFLA_IFNAME]); + snprintf(interface_name, interface_name_size, "%s", + (char *)RTA_DATA(tb[IFLA_IFNAME])); + } - if (up) - *up = ifi->ifi_flags & IFF_UP; - if (running) - *running = ifi->ifi_flags & IFF_RUNNING; + if (up) *up = ifi->ifi_flags & IFF_UP; + if (running) *running = ifi->ifi_flags & IFF_RUNNING; + netdevice_t *netdevice = netdevice_create_from_name(interface_name); + if (!netdevice) { + ERROR("[netlink.parse_link] error creating netdevice '%s'", interface_name); + goto ERR_ND; + } - netdevice_t * netdevice = netdevice_create_from_name(interface_name); - if (!netdevice) { - ERROR("[netlink.parse_link] error creating netdevice '%s'", interface_name); - goto ERR_ND; - } + *facelet = facelet_create(); + if (!*facelet) { + ERROR("[netlink.parse_link] error creating facelet"); + goto ERR_FACELET; + } - *facelet = facelet_create(); - if (!*facelet) { - ERROR("[netlink.parse_link] error creating facelet"); - goto ERR_FACELET; - } - - if (facelet_set_netdevice(*facelet, *netdevice) < 0) { - ERROR("[netlink.parse_link] error setting netdevice"); - goto ERR; - } + if (facelet_set_netdevice(*facelet, *netdevice) < 0) { + ERROR("[netlink.parse_link] error setting netdevice"); + goto ERR; + } // FIXME Tags #if 0 @@ -252,160 +238,162 @@ int parse_link(struct nlmsghdr * h, facelet_t ** facelet, #endif - // TODO - // - ifi_change - // - IFLA_PROTINFO + // TODO + // - ifi_change + // - IFLA_PROTINFO - netdevice_free(netdevice); - return 0; + netdevice_free(netdevice); + return 0; ERR: - facelet_free(*facelet); - *facelet = NULL; + facelet_free(*facelet); + *facelet = NULL; ERR_FACELET: - netdevice_free(netdevice); + netdevice_free(netdevice); ERR_ND: - return -1; + return -1; } -int parse_addr(struct nlmsghdr * h, facelet_t ** facelet, - char * interface_name, size_t interface_name_size, - char * interface_address, size_t interface_address_size) -{ - ip_address_t local_addr = IP_ADDRESS_EMPTY; - struct ifaddrmsg *ifa; // structure for network interface data - struct rtattr *tba[IFA_MAX+1]; - - assert(facelet); - - ifa = (struct ifaddrmsg*)NLMSG_DATA(h); // get data from the network interface - - parse_rtattr(tba, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(h), 0); - - /* FIXME - * - * IFA_LOCAL ok for v4, not there for v6 - * - * IFA_ADDRESS seems to work for both but with the following precaution - * - * IFA_ADDRESS is prefix address, rather than local interface address. - * It makes no difference for normally configured broadcast interfaces, - * but for point-to-point IFA_ADDRESS is DESTINATION address, - * local address is supplied in IFA_LOCAL attribute. - */ - if (!tba[IFA_ADDRESS]) { - ERROR("[netlink.parse_addr] No local address"); - return -1; - } - - switch(ifa->ifa_family) { - case AF_INET: - local_addr.v4.as_inaddr = *(struct in_addr*)RTA_DATA(tba[IFA_ADDRESS]); - break; - case AF_INET6: - local_addr.v6.as_in6addr = *(struct in6_addr*)RTA_DATA(tba[IFA_ADDRESS]); - break; - default: - return 0; - } - - /* See comment in parse_link */ - if (interface_address) { - assert(tba[IFA_ADDRESS]); - ip_address_snprintf(interface_address, interface_address_size, &local_addr, ifa->ifa_family); - } - - netdevice_t * netdevice = netdevice_create_from_index(ifa->ifa_index); - if (!netdevice) { - ERROR("[netlink.parse_addr] error creating netdevice from index '%d'", ifa->ifa_index); - goto ERR_ND; - } - - if (interface_name) { - snprintf(interface_name, interface_name_size, "%s", netdevice->name); - } - - *facelet = facelet_create(); - if (!*facelet) { - ERROR("[netlink.parse_addr] error creating facelet"); - goto ERR_FACELET; - } - if (facelet_set_netdevice(*facelet, *netdevice) < 0) { - ERROR("[netlink.parse_addr] error setting netdevice"); - goto ERR; - } - if (facelet_set_family(*facelet, ifa->ifa_family) < 0) { - ERROR("[netlink.parse_addr] error setting family"); - goto ERR; - } - if (facelet_set_local_addr(*facelet, local_addr) < 0) { - ERROR("[netlink.parse_addr] error setting local address"); - goto ERR; - } - - netdevice_free(netdevice); - return 0; +int parse_addr(struct nlmsghdr *h, facelet_t **facelet, char *interface_name, + size_t interface_name_size, char *interface_address, + size_t interface_address_size) { + ip_address_t local_addr = IP_ADDRESS_EMPTY; + struct ifaddrmsg *ifa; // structure for network interface data + struct rtattr *tba[IFA_MAX + 1]; + + assert(facelet); + + ifa = + (struct ifaddrmsg *)NLMSG_DATA(h); // get data from the network interface + + parse_rtattr(tba, IFA_MAX, IFA_RTA(ifa), IFA_PAYLOAD(h), 0); + + /* FIXME + * + * IFA_LOCAL ok for v4, not there for v6 + * + * IFA_ADDRESS seems to work for both but with the following precaution + * + * IFA_ADDRESS is prefix address, rather than local interface address. + * It makes no difference for normally configured broadcast interfaces, + * but for point-to-point IFA_ADDRESS is DESTINATION address, + * local address is supplied in IFA_LOCAL attribute. + */ + if (!tba[IFA_ADDRESS]) { + ERROR("[netlink.parse_addr] No local address"); + return -1; + } + + switch (ifa->ifa_family) { + case AF_INET: + local_addr.v4.as_inaddr = *(struct in_addr *)RTA_DATA(tba[IFA_ADDRESS]); + break; + case AF_INET6: + local_addr.v6.as_in6addr = *(struct in6_addr *)RTA_DATA(tba[IFA_ADDRESS]); + break; + default: + return 0; + } + + /* See comment in parse_link */ + if (interface_address) { + assert(tba[IFA_ADDRESS]); + ip_address_snprintf(interface_address, interface_address_size, &local_addr, + ifa->ifa_family); + } + + netdevice_t *netdevice = netdevice_create_from_index(ifa->ifa_index); + if (!netdevice) { + ERROR("[netlink.parse_addr] error creating netdevice from index '%d'", + ifa->ifa_index); + goto ERR_ND; + } + + if (interface_name) { + snprintf(interface_name, interface_name_size, "%s", netdevice->name); + } + + *facelet = facelet_create(); + if (!*facelet) { + ERROR("[netlink.parse_addr] error creating facelet"); + goto ERR_FACELET; + } + if (facelet_set_netdevice(*facelet, *netdevice) < 0) { + ERROR("[netlink.parse_addr] error setting netdevice"); + goto ERR; + } + if (facelet_set_family(*facelet, ifa->ifa_family) < 0) { + ERROR("[netlink.parse_addr] error setting family"); + goto ERR; + } + if (facelet_set_local_addr(*facelet, local_addr) < 0) { + ERROR("[netlink.parse_addr] error setting local address"); + goto ERR; + } + + netdevice_free(netdevice); + return 0; ERR: - facelet_free(*facelet); - *facelet = NULL; + facelet_free(*facelet); + *facelet = NULL; ERR_FACELET: - netdevice_free(netdevice); + netdevice_free(netdevice); ERR_ND: - return -1; + return -1; } -int nl_callback(interface_t * interface, int fd, void * unused) -{ - nl_data_t * data = (nl_data_t*)interface->data; +int nl_callback(interface_t *interface, int fd, void *unused) { + nl_data_t *data = (nl_data_t *)interface->data; - struct sockaddr_nl local; // local addr struct - memset(&local, 0, sizeof(local)); + struct sockaddr_nl local; // local addr struct + memset(&local, 0, sizeof(local)); - char buf[8192]; // message buffer - struct iovec iov; // message structure - iov.iov_base = buf; // set message buffer as io - iov.iov_len = sizeof(buf); // set size + char buf[8192]; // message buffer + struct iovec iov; // message structure + iov.iov_base = buf; // set message buffer as io + iov.iov_len = sizeof(buf); // set size - // initialize protocol message header - struct msghdr msg = { - .msg_name = &local, // local address - .msg_namelen = sizeof(local), // address size - .msg_iov = &iov, // io vector - .msg_iovlen = 1, // io size - }; + // initialize protocol message header + struct msghdr msg = { + .msg_name = &local, // local address + .msg_namelen = sizeof(local), // address size + .msg_iov = &iov, // io vector + .msg_iovlen = 1, // io size + }; - ssize_t status = recvmsg(data->fd, &msg, 0); + ssize_t status = recvmsg(data->fd, &msg, 0); - // check status - if (status < 0) { -/* - if (errno == EINTR || errno == EAGAIN) - continue; -*/ + // check status + if (status < 0) { + /* + if (errno == EINTR || errno == EAGAIN) + continue; + */ - printf("Failed to read netlink: %s", (char*)strerror(errno)); - return -1; - } + printf("Failed to read netlink: %s", (char *)strerror(errno)); + return -1; + } - if (msg.msg_namelen != sizeof(local)) { // check message length, just in case - printf("Invalid length of the sender address struct\n"); - return -1; - } + if (msg.msg_namelen != sizeof(local)) { // check message length, just in case + printf("Invalid length of the sender address struct\n"); + return -1; + } - // message parser - struct nlmsghdr *h; + // message parser + struct nlmsghdr *h; - for (h = (struct nlmsghdr*)buf; status >= (ssize_t)sizeof(*h); ) { // read all messagess headers - int len = h->nlmsg_len; - int l = len - sizeof(*h); + for (h = (struct nlmsghdr *)buf; + status >= (ssize_t)sizeof(*h);) { // read all messagess headers + int len = h->nlmsg_len; + int l = len - sizeof(*h); - if ((l < 0) || (len > status)) { - printf("Invalid message length: %i\n", len); - continue; - } + if ((l < 0) || (len > status)) { + printf("Invalid message length: %i\n", len); + continue; + } - switch(h->nlmsg_type) { + switch (h->nlmsg_type) { #if 0 case RTM_NEWROUTE: case RTM_DELROUTE: @@ -413,147 +401,123 @@ int nl_callback(interface_t * interface, int fd, void * unused) break; #endif - case RTM_DELADDR: - { - facelet_t * facelet = NULL; - char interface_name[IFNAMSIZ]; - char interface_address[MAXSZ_IP_ADDRESS] = {0}; - - if (parse_addr(h, &facelet, interface_name, IFNAMSIZ, - interface_address, MAXSZ_IP_ADDRESS) < 0) { - ERROR("Error parsing address message"); - break; - } - - DEBUG("[NETLINK] Interface %s: address was removed", interface_name); - if (facelet) { - facelet_set_event(facelet, FACELET_EVENT_SET_DOWN); - facelet_set_attr_clean(facelet); - interface_raise_event(interface, facelet); - } - break; - } - - case RTM_NEWADDR: - { - facelet_t * facelet = NULL; - char interface_name[IFNAMSIZ]; - char interface_address[MAXSZ_IP_ADDRESS] = {0}; - - if (parse_addr(h, &facelet, interface_name, IFNAMSIZ, - interface_address, MAXSZ_IP_ADDRESS) < 0) { - ERROR("Error parsing address message"); - break; - } - - DEBUG("[NETLINK] Interface %s: new address was assigned: %s", interface_name, interface_address); - - if (facelet) { - facelet_set_event(facelet, FACELET_EVENT_UPDATE); - facelet_set_attr_clean(facelet); - interface_raise_event(interface, facelet); - } - break; - } + case RTM_DELADDR: { + facelet_t *facelet = NULL; + char interface_name[IFNAMSIZ]; + char interface_address[MAXSZ_IP_ADDRESS] = {0}; - case RTM_DELLINK: - { - /* This does not always seem to be called, hence we rely on - * down, not running */ - facelet_t * facelet = NULL; - char interface_name[IFNAMSIZ]; - if (parse_link(h, &facelet, interface_name, IFNAMSIZ, - NULL, NULL) < 0) { - ERROR("Error parsing link message"); - break; - } + if (parse_addr(h, &facelet, interface_name, IFNAMSIZ, interface_address, + MAXSZ_IP_ADDRESS) < 0) { + ERROR("Error parsing address message"); + break; + } - DEBUG("[NETLINK] Network interface %s was removed", interface_name); + DEBUG("[NETLINK] Interface %s: address was removed", interface_name); + if (facelet) { + facelet_set_event(facelet, FACELET_EVENT_SET_DOWN); + facelet_set_attr_clean(facelet); + interface_raise_event(interface, facelet); + } + break; + } + + case RTM_NEWADDR: { + facelet_t *facelet = NULL; + char interface_name[IFNAMSIZ]; + char interface_address[MAXSZ_IP_ADDRESS] = {0}; + + if (parse_addr(h, &facelet, interface_name, IFNAMSIZ, interface_address, + MAXSZ_IP_ADDRESS) < 0) { + ERROR("Error parsing address message"); + break; + } - if (!facelet) - break; + DEBUG("[NETLINK] Interface %s: new address was assigned: %s", + interface_name, interface_address); - facelet_set_event(facelet, FACELET_EVENT_DELETE); - facelet_set_attr_clean(facelet); - interface_raise_event(interface, facelet); + if (facelet) { + facelet_set_event(facelet, FACELET_EVENT_UPDATE); + facelet_set_attr_clean(facelet); + interface_raise_event(interface, facelet); + } + break; + } + + case RTM_DELLINK: { + /* This does not always seem to be called, hence we rely on + * down, not running */ + facelet_t *facelet = NULL; + char interface_name[IFNAMSIZ]; + if (parse_link(h, &facelet, interface_name, IFNAMSIZ, NULL, NULL) < 0) { + ERROR("Error parsing link message"); + break; + } - break; - } - - case RTM_NEWLINK: - { - facelet_t * facelet = NULL; - char interface_name[IFNAMSIZ]; - bool up, running; - - if (parse_link(h, &facelet, interface_name, IFNAMSIZ, &up, &running) < 0) { - ERROR("Error parsing link message"); - break; - } - - // UP RUNNING - // UP NOT RUNNING - // DOWN NOT RUNNING -#if 1 - DEBUG("[NETLINK] New network interface %s, state: %s %s", interface_name, - up ? "UP" : "DOWN", - running ? "RUNNING" : "NOT_RUNNING"); -#endif + DEBUG("[NETLINK] Network interface %s was removed", interface_name); - if (!facelet) - break; - if (up && running) { - facelet_set_event(facelet, FACELET_EVENT_CREATE); - //facelet_set_family(facelet, AF_INET); - facelet_set_attr_clean(facelet); - interface_raise_event(interface, facelet); + if (!facelet) break; -#if 0 - facelet_t * facelet6 = facelet_dup(facelet); - if (!facelet6) { - ERROR("Could not duplicate face for v6"); - break; - } - facelet_set_family(facelet6, AF_INET6); - interface_raise_event(interface, facelet6); -#endif -// } else { -//#if 1 -// facelet_set_event(facelet, FACELET_EVENT_SET_DOWN); -// facelet_set_attr_clean(facelet); -// interface_raise_event(interface, facelet); -//#else -// facelet_free(facelet); -//#endif - } - break; - } + facelet_set_event(facelet, FACELET_EVENT_DELETE); + facelet_set_attr_clean(facelet); + interface_raise_event(interface, facelet); - case NLMSG_ERROR: - break; - case NLMSG_DONE: - nl_process_state(interface); - break; - default: - break; + break; + } + + case RTM_NEWLINK: { + facelet_t *facelet = NULL; + char interface_name[IFNAMSIZ]; + bool up, running; + if (parse_link(h, &facelet, interface_name, IFNAMSIZ, &up, &running) < + 0) { + ERROR("Error parsing link message"); + break; } - status -= NLMSG_ALIGN(len); // align offsets by the message length, this is important + // UP RUNNING + // UP NOT RUNNING + // DOWN NOT RUNNING +#if 1 + DEBUG("[NETLINK] New network interface %s, state: %s %s", + interface_name, up ? "UP" : "DOWN", + running ? "RUNNING" : "NOT_RUNNING"); +#endif - h = (struct nlmsghdr*)((char*)h + NLMSG_ALIGN(len)); // get next message + if (!facelet) break; + if (up && running) { + facelet_set_event(facelet, FACELET_EVENT_CREATE); + facelet_set_attr_clean(facelet); + interface_raise_event(interface, facelet); + } else { + facelet_free(facelet); + } + break; + } + + case NLMSG_ERROR: + break; + case NLMSG_DONE: + nl_process_state(interface); + break; + default: + break; } - return 0; -} + status -= NLMSG_ALIGN( + len); // align offsets by the message length, this is important -int nl_finalize(interface_t * interface) -{ - nl_data_t * data = (nl_data_t*)interface->data; - close(data->fd); - free(interface->data); - return 0; + h = (struct nlmsghdr *)((char *)h + NLMSG_ALIGN(len)); // get next message + } + + return 0; +} +int nl_finalize(interface_t *interface) { + nl_data_t *data = (nl_data_t *)interface->data; + close(data->fd); + free(interface->data); + return 0; } const interface_ops_t netlink_ops = { diff --git a/ctrl/facemgr/src/interfaces/network_framework/CMakeLists.txt b/ctrl/facemgr/src/interfaces/network_framework/CMakeLists.txt index e8b0144b1..db96e390f 100644 --- a/ctrl/facemgr/src/interfaces/network_framework/CMakeLists.txt +++ b/ctrl/facemgr/src/interfaces/network_framework/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021 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: diff --git a/ctrl/facemgr/src/interfaces/network_framework/network_framework.c b/ctrl/facemgr/src/interfaces/network_framework/network_framework.c index 2c4bff513..3adba0969 100644 --- a/ctrl/facemgr/src/interfaces/network_framework/network_framework.c +++ b/ctrl/facemgr/src/interfaces/network_framework/network_framework.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -32,7 +32,7 @@ #include <hicn/util/map.h> #include "../../common.h" -#include <hicn/ctrl/face.h> +#include <hicn/face.h> #include "../../interface.h" #include "network_framework.h" @@ -41,7 +41,6 @@ #error "Network frameork requires MacOSX 10.14+" #endif /* !defined(MAC_OS_X_VERSION_10_14) */ - /* * Bonjour service discovery for hICN forwarder * @@ -70,144 +69,147 @@ /* Generated variables */ #define BONJOUR_SERVICE_TYPE "_hicn._" STRINGIZE(BONJOUR_PROTOCOL) #define BONJOUR_PROTOCOL_NAME STRINGIZE(BONJOUR_PROTOCOL) -#define nw_parameters_create_fn PPCAT(nw_parameters_create_secure_, BONJOUR_PROTOCOL) +#define nw_parameters_create_fn \ + PPCAT(nw_parameters_create_secure_, BONJOUR_PROTOCOL) #define DEFAULT_PORT 9695 typedef enum { - INTERFACE_TYPE_OTHER, - INTERFACE_TYPE_WIFI, - INTERFACE_TYPE_CELLULAR, - INTERFACE_TYPE_WIRED, - INTERFACE_TYPE_LOOPBACK, + INTERFACE_TYPE_OTHER, + INTERFACE_TYPE_WIFI, + INTERFACE_TYPE_CELLULAR, + INTERFACE_TYPE_WIRED, + INTERFACE_TYPE_LOOPBACK, } _nw_interface_type_t; -const char * interface_type_str[] = { +const char *interface_type_str[] = { "OTHER", "WIFI", "CELLULAR", "WIRED", "LOOPBACK", }; #if 1 typedef enum { - PATH_STATUS_INVALID, - PATH_STATUS_SATISTIED, - PATH_STATUS_UNSATISFIED, - PATH_STATUS_SATISFIABLE, + PATH_STATUS_INVALID, + PATH_STATUS_SATISTIED, + PATH_STATUS_UNSATISFIED, + PATH_STATUS_SATISFIABLE, } _nw_path_status_t; #endif -const char * path_status_str[] = { - "INVALID", "SATISFIED", "UNSATISFIED", "SATISFIABLE", +const char *path_status_str[] = { + "INVALID", + "SATISFIED", + "UNSATISFIED", + "SATISFIABLE", }; -const char * endpoint_type_str[] = { - "INVALID", "ADDRESS", "HOST", "BONJOUR", +const char *endpoint_type_str[] = { + "INVALID", + "ADDRESS", + "HOST", + "BONJOUR", }; -const char * connection_state_str[] = { +const char *connection_state_str[] = { "INVALID", "WAITING", "PREPARING", "READY", "FAILED", "CANCELLED", }; -int -cmp_iface(const nw_interface_t iface1, const nw_interface_t iface2) -{ - return INT_CMP(nw_interface_get_index(iface1), nw_interface_get_index(iface2)); +int cmp_iface(const nw_interface_t iface1, const nw_interface_t iface2) { + return INT_CMP(nw_interface_get_index(iface1), + nw_interface_get_index(iface2)); } -//TYPEDEF_MAP(map_cnx, nw_interface_t, nw_connection_t, cmp_iface); +// TYPEDEF_MAP(map_cnx, nw_interface_t, nw_connection_t, cmp_iface); typedef struct { - network_framework_cfg_t cfg; - nw_path_monitor_t pm; /**< Main path monitor */ -// map_cnx_t map_cnx; /**< Map: interface -> connection for face status */ + network_framework_cfg_t cfg; + nw_path_monitor_t pm; /**< Main path monitor */ + // map_cnx_t map_cnx; /**< Map: interface -> connection for face status + // */ } nf_data_t; -void -dump_interface(nw_interface_t interface, int indent) -{ - uint32_t index = nw_interface_get_index(interface); - const char * name = nw_interface_get_name(interface); - nw_interface_type_t type = nw_interface_get_type(interface); +void dump_interface(nw_interface_t interface, int indent) { + uint32_t index = nw_interface_get_index(interface); + const char *name = nw_interface_get_name(interface); + nw_interface_type_t type = nw_interface_get_type(interface); - printfi(indent+1, "%d: %s [%s]\n", index, name, interface_type_str[type]); + printfi(indent + 1, "%d: %s [%s]\n", index, name, interface_type_str[type]); } -void -dump_endpoint(nw_endpoint_t endpoint, int indent) -{ - if (!endpoint) { - printfi(indent, "N/A\n"); - return; - } - - nw_endpoint_type_t endpoint_type = nw_endpoint_get_type(endpoint); - const char * hostname = nw_endpoint_get_hostname(endpoint); - short port = nw_endpoint_get_port(endpoint); - const struct sockaddr * address = nw_endpoint_get_address(endpoint); - - printfi(indent, "Type: %s\n", endpoint_type_str[endpoint_type]); - printfi(indent, "Hostname: %s\n", hostname); - printfi(indent, "Port: %d\n", port); - - if (address) { - char *s = NULL; - switch(address->sa_family) { - case AF_INET: { - struct sockaddr_in *addr_in = (struct sockaddr_in *)address; - s = malloc(INET_ADDRSTRLEN); - inet_ntop(AF_INET, &(addr_in->sin_addr), s, INET_ADDRSTRLEN); - break; - } - case AF_INET6: { - struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)address; - s = malloc(INET6_ADDRSTRLEN); - inet_ntop(AF_INET6, &(addr_in6->sin6_addr), s, INET6_ADDRSTRLEN); - break; - } - default: - break; - } +void dump_endpoint(nw_endpoint_t endpoint, int indent) { + if (!endpoint) { + printfi(indent, "N/A\n"); + return; + } + + nw_endpoint_type_t endpoint_type = nw_endpoint_get_type(endpoint); + const char *hostname = nw_endpoint_get_hostname(endpoint); + short port = nw_endpoint_get_port(endpoint); + const struct sockaddr *address = nw_endpoint_get_address(endpoint); + + printfi(indent, "Type: %s\n", endpoint_type_str[endpoint_type]); + printfi(indent, "Hostname: %s\n", hostname); + printfi(indent, "Port: %d\n", port); + + if (address) { + char *s = NULL; + switch (address->sa_family) { + case AF_INET: { + struct sockaddr_in *addr_in = (struct sockaddr_in *)address; + s = malloc(INET_ADDRSTRLEN); + inet_ntop(AF_INET, &(addr_in->sin_addr), s, INET_ADDRSTRLEN); + break; + } + case AF_INET6: { + struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)address; + s = malloc(INET6_ADDRSTRLEN); + inet_ntop(AF_INET6, &(addr_in6->sin6_addr), s, INET6_ADDRSTRLEN); + break; + default: + break; + } printfi(indent, "IP address: %s\n", s); free(s); } -} + } -void -dump_path(nw_path_t path, int indent) -{ + void dump_path(nw_path_t path, int indent) { /* nw_path_enumerate_interfaces : not interesting */ nw_path_status_t path_status = nw_path_get_status(path); printfi(indent, "Status: %s\n", path_status_str[path_status]); - printfi(indent, "Expensive: %s\n", nw_path_is_expensive(path) ? "true" : "false"); - printfi(indent, "IPv4 enabled: %s\n", nw_path_has_ipv4(path) ? "true" : "false"); - printfi(indent, "IPv6 enabled: %s\n", nw_path_has_ipv6(path) ? "true" : "false"); + printfi(indent, "Expensive: %s\n", + nw_path_is_expensive(path) ? "true" : "false"); + printfi(indent, "IPv4 enabled: %s\n", + nw_path_has_ipv4(path) ? "true" : "false"); + printfi(indent, "IPv6 enabled: %s\n", + nw_path_has_ipv6(path) ? "true" : "false"); printfi(indent, "DNS: %s\n", nw_path_has_dns(path) ? "true" : "false"); printfi(indent, "Interfaces:\n"); - nw_path_enumerate_interfaces(path, (nw_path_enumerate_interfaces_block_t)^(nw_interface_t interface) { - dump_interface(interface, indent+1); - return true; - }); + nw_path_enumerate_interfaces( + path, + (nw_path_enumerate_interfaces_block_t) ^ (nw_interface_t interface) { + dump_interface(interface, indent + 1); + return true; + }); nw_endpoint_t local = nw_path_copy_effective_local_endpoint(path); printfi(indent, "Effective local endpoint:\n"); - dump_endpoint(local, indent+1); + dump_endpoint(local, indent + 1); nw_release(local); nw_endpoint_t remote = nw_path_copy_effective_remote_endpoint(path); printfi(indent, "Effective remote endpoint:\n"); - dump_endpoint(remote, indent+1); + dump_endpoint(remote, indent + 1); nw_release(remote); -} + } -void -dump_connection(nw_connection_t connection, int indent) -{ + void dump_connection(nw_connection_t connection, int indent) { nw_endpoint_t remote = nw_connection_copy_endpoint(connection); nw_path_t path = nw_connection_copy_current_path(connection); printfi(indent, "Remote endpoint:\n"); - dump_endpoint(remote, indent+1); + dump_endpoint(remote, indent + 1); printfi(indent, "Path:\n"); - dump_path(path, indent+1); + dump_path(path, indent + 1); /* nw_connection_copy_protocol_metadata(); @@ -216,34 +218,34 @@ dump_connection(nw_connection_t connection, int indent) nw_release(remote); nw_release(path); -} + } #if defined(MAC_OS_X_VERSION_10_15) -void -dump_browse_result(nw_browse_result_t result, int indent) -{ + void dump_browse_result(nw_browse_result_t result, int indent) { /* Endpoint */ nw_endpoint_t browse_endpoint = nw_browse_result_copy_endpoint(result); if (!browse_endpoint) { - ERROR("[network_framework.dump_result] Failed to retrieve endpoint from Bonjour browse result"); - return; + ERROR( + "[network_framework.dump_result] Failed to retrieve endpoint from " + "Bonjour browse result"); + return; } printfi(indent + 1, "Endpoint:"); dump_endpoint(browse_endpoint, indent + 2); /* Interfaces */ printfi(indent + 1, "Interfaces:"); - nw_browse_result_enumerate_interfaces(result, (nw_browse_result_enumerate_interface_t) ^(nw_interface_t interface) { - dump_interface(interface, indent + 2); - return true; - }); -} + nw_browse_result_enumerate_interfaces( + result, + (nw_browse_result_enumerate_interface_t) ^ (nw_interface_t interface) { + dump_interface(interface, indent + 2); + return true; + }); + } #endif /* defined(MAC_OS_X_VERSION_10_15) */ -facelet_t * -facelet_create_from_connection(nw_connection_t connection) -{ - facelet_t * facelet; + facelet_t *facelet_create_from_connection(nw_connection_t connection) { + facelet_t *facelet; ip_address_t local_addr, remote_addr; uint16_t remote_port; @@ -252,34 +254,36 @@ facelet_create_from_connection(nw_connection_t connection) nw_endpoint_t remote = nw_path_copy_effective_remote_endpoint(path); __block nw_interface_t interface; - const struct sockaddr * local_sa = nw_endpoint_get_address(local); - const struct sockaddr * remote_sa = nw_endpoint_get_address(remote); - - assert (local_sa->sa_family == remote_sa->sa_family); - switch(local_sa->sa_family) { - case AF_INET: - local_addr.v4.as_inaddr = ((struct sockaddr_in *)local_sa)->sin_addr; - remote_addr.v4.as_inaddr = ((struct sockaddr_in *)remote_sa)->sin_addr; - remote_port = ((struct sockaddr_in *)remote_sa)->sin_port; - break; - case AF_INET6: - local_addr.v6.as_in6addr = ((struct sockaddr_in6 *)local_sa)->sin6_addr; - remote_addr.v6.as_in6addr = ((struct sockaddr_in6 *)remote_sa)->sin6_addr; - remote_port = ((struct sockaddr_in6 *)remote_sa)->sin6_port; - break; - default: - ERROR("Unsupported address family: %d\n", local_sa->sa_family); - return NULL; + const struct sockaddr *local_sa = nw_endpoint_get_address(local); + const struct sockaddr *remote_sa = nw_endpoint_get_address(remote); + + assert(local_sa->sa_family == remote_sa->sa_family); + switch (local_sa->sa_family) { + case AF_INET: + local_addr.v4.as_inaddr = ((struct sockaddr_in *)local_sa)->sin_addr; + remote_addr.v4.as_inaddr = ((struct sockaddr_in *)remote_sa)->sin_addr; + remote_port = ((struct sockaddr_in *)remote_sa)->sin_port; + break; + case AF_INET6: + local_addr.v6.as_in6addr = ((struct sockaddr_in6 *)local_sa)->sin6_addr; + remote_addr.v6.as_in6addr = + ((struct sockaddr_in6 *)remote_sa)->sin6_addr; + remote_port = ((struct sockaddr_in6 *)remote_sa)->sin6_port; + break; + default: + ERROR("Unsupported address family: %d\n", local_sa->sa_family); + return NULL; } - /* Retrieving path interface type (a single one expected */ - nw_path_enumerate_interfaces(path, (nw_path_enumerate_interfaces_block_t)^(nw_interface_t path_interface) { - interface = path_interface; - return false; - }); - - const char * name = nw_interface_get_name(interface); + nw_path_enumerate_interfaces( + path, (nw_path_enumerate_interfaces_block_t) ^ + (nw_interface_t path_interface) { + interface = path_interface; + return false; + }); + + const char *name = nw_interface_get_name(interface); netdevice_t netdevice; snprintf(netdevice.name, IFNAMSIZ, "%s", name); netdevice_update_index(&netdevice); @@ -287,25 +291,24 @@ facelet_create_from_connection(nw_connection_t connection) netdevice_type_t netdevice_type; nw_interface_type_t type = nw_interface_get_type(interface); - switch(type) { - case INTERFACE_TYPE_OTHER: - netdevice_type = NETDEVICE_TYPE_UNDEFINED; - break; - case INTERFACE_TYPE_WIFI: - netdevice_type = NETDEVICE_TYPE_WIFI; - break; - case INTERFACE_TYPE_CELLULAR: - netdevice_type = NETDEVICE_TYPE_CELLULAR; - break; - case INTERFACE_TYPE_WIRED: - netdevice_type = NETDEVICE_TYPE_WIRED; - break; - case INTERFACE_TYPE_LOOPBACK: - netdevice_type = NETDEVICE_TYPE_LOOPBACK; - break; - default: - break; - + switch (type) { + case INTERFACE_TYPE_OTHER: + netdevice_type = NETDEVICE_TYPE_UNDEFINED; + break; + case INTERFACE_TYPE_WIFI: + netdevice_type = NETDEVICE_TYPE_WIFI; + break; + case INTERFACE_TYPE_CELLULAR: + netdevice_type = NETDEVICE_TYPE_CELLULAR; + break; + case INTERFACE_TYPE_WIRED: + netdevice_type = NETDEVICE_TYPE_WIRED; + break; + case INTERFACE_TYPE_LOOPBACK: + netdevice_type = NETDEVICE_TYPE_LOOPBACK; + break; + default: + break; } nw_release(local); @@ -313,8 +316,7 @@ facelet_create_from_connection(nw_connection_t connection) nw_release(path); facelet = facelet_create(); - if (!facelet) - return NULL; + if (!facelet) return NULL; facelet_set_netdevice(facelet, netdevice); facelet_set_netdevice_type(facelet, netdevice_type); @@ -324,20 +326,21 @@ facelet_create_from_connection(nw_connection_t connection) facelet_set_remote_port(facelet, remote_port); return facelet; -} + } -void -on_connection_state_event(interface_t * interface, nw_interface_t iface, - nw_connection_t cnx, nw_connection_state_t state, nw_error_t error) -{ + void on_connection_state_event( + interface_t * interface, nw_interface_t iface, nw_connection_t cnx, + nw_connection_state_t state, nw_error_t error) { #if 1 DEBUG("Connection [new state = %s]:\n", connection_state_str[state]); nw_path_t path = nw_connection_copy_current_path(cnx); - nw_path_enumerate_interfaces(path, (nw_path_enumerate_interfaces_block_t)^(nw_interface_t interface) { - const char * name = nw_interface_get_name(interface); - printf("NAME=%s\n", name); - return true; - }); + nw_path_enumerate_interfaces( + path, + (nw_path_enumerate_interfaces_block_t) ^ (nw_interface_t interface) { + const char *name = nw_interface_get_name(interface); + printf("NAME=%s\n", name); + return true; + }); #endif /* We should get enough information to create the face and set if up @@ -346,84 +349,71 @@ on_connection_state_event(interface_t * interface, nw_interface_t iface, nw_endpoint_t remote = nw_connection_copy_endpoint(cnx); errno = error ? nw_error_get_error_code(error) : 0; - switch(state) { - case nw_connection_state_waiting: - warn("connect to %s port %u (%s) failed, is waiting", - nw_endpoint_get_hostname(remote), - nw_endpoint_get_port(remote), - BONJOUR_PROTOCOL_NAME); - break; - - case nw_connection_state_preparing: - break; - - case nw_connection_state_ready: - { - printf("info:\n"); - warn("connection ready"); + switch (state) { + case nw_connection_state_waiting: + warn("connect to %s port %u (%s) failed, is waiting", + nw_endpoint_get_hostname(remote), nw_endpoint_get_port(remote), + BONJOUR_PROTOCOL_NAME); + break; + + case nw_connection_state_preparing: + break; + + case nw_connection_state_ready: { + printf("info:\n"); + warn("connection ready"); #if 1 - WITH_DEBUG({ - dump_connection(cnx, 1); - }); + WITH_DEBUG({ dump_connection(cnx, 1); }); #endif - facelet_t * facelet = facelet_create_from_connection(cnx); - if (!facelet) - return; - facelet_set_event(facelet, FACELET_EVENT_CREATE); - interface_raise_event(interface, facelet); - break; - } - case nw_connection_state_failed: - /* Can we fail with bonjour, or are we always waiting ? */ - warn("connect to %s port %u (%s) failed", - nw_endpoint_get_hostname(remote), - nw_endpoint_get_port(remote), - BONJOUR_PROTOCOL_NAME); - break; - - case nw_connection_state_cancelled: - // Release the primary reference on the connection - // that was taken at creation time - nw_release(cnx); - break; - - default: /* nw_connection_state_invalid */ - /* Should never be called */ - break; - + facelet_t *facelet = facelet_create_from_connection(cnx); + if (!facelet) return; + facelet_set_event(facelet, FACELET_EVENT_CREATE); + interface_raise_event(interface, facelet); + break; + } + case nw_connection_state_failed: + /* Can we fail with bonjour, or are we always waiting ? */ + warn("connect to %s port %u (%s) failed", + nw_endpoint_get_hostname(remote), nw_endpoint_get_port(remote), + BONJOUR_PROTOCOL_NAME); + break; + + case nw_connection_state_cancelled: + // Release the primary reference on the connection + // that was taken at creation time + nw_release(cnx); + break; + + default: /* nw_connection_state_invalid */ + /* Should never be called */ + break; } nw_release(remote); + } -} - -void -on_connection_path_event(interface_t * interface, nw_interface_t iface, - nw_connection_t cnx, nw_path_t path) -{ + void on_connection_path_event(interface_t * interface, nw_interface_t iface, + nw_connection_t cnx, nw_path_t path) { #if 1 DEBUG("Connection [path changed]:\n"); - WITH_DEBUG({ - dump_connection(cnx, 1); - }); + WITH_DEBUG({ dump_connection(cnx, 1); }); #endif - /* redundant *//* - DEBUG(1, "Path:\n"); - dump_path(path, 2); - */ -} - -/** - * Enumerate main path interfaces - * - * We need to create specific dummy connections for each newly discovered - * interface - * - * Currently we only use Bonjour/TCP for remote hICN discovery and connection - * path monitoring. - */ -void on_interface_event(interface_t * interface, nw_interface_t iface) -{ + /* redundant */ /* + DEBUG(1, "Path:\n"); + dump_path(path, 2); + */ + } + + /** + * Enumerate main path interfaces + * + * We need to create specific dummy connections for each newly discovered + * interface + * + * Currently we only use Bonjour/TCP for remote hICN discovery and connection + * path monitoring. + */ + void on_interface_event(interface_t * interface, nw_interface_t iface) { /* We can create an hICN face on this interface that will be down until * connected * It is however possible to have two default gateways on the same @@ -452,11 +442,10 @@ void on_interface_event(interface_t * interface, nw_interface_t iface) /* nw_parameters_create_secure_{udp,tcp} */ nw_parameters_t parameters = nw_parameters_create_fn( - NW_PARAMETERS_DISABLE_PROTOCOL, /* no (d)tls */ - NW_PARAMETERS_DEFAULT_CONFIGURATION /* default udp/tcp */); + NW_PARAMETERS_DISABLE_PROTOCOL, /* no (d)tls */ + NW_PARAMETERS_DEFAULT_CONFIGURATION /* default udp/tcp */); - if (!parameters) - goto ERR_PARAMETERS; + if (!parameters) goto ERR_PARAMETERS; nw_parameters_require_interface(parameters, iface); nw_parameters_set_reuse_local_address(parameters, true); @@ -467,49 +456,60 @@ void on_interface_event(interface_t * interface, nw_interface_t iface) * available services on the local network using the parameters specified * before. */ - nw_browse_descriptor_t descriptor = nw_browse_descriptor_create_bonjour_service(BONJOUR_SERVICE_TYPE, BONJOUR_SERVICE_DOMAIN); + nw_browse_descriptor_t descriptor = + nw_browse_descriptor_create_bonjour_service(BONJOUR_SERVICE_TYPE, + BONJOUR_SERVICE_DOMAIN); if (!descriptor) { - ERROR("[network_framework.on_interface_event] Failed to create a bonjour browse descriptor"); - goto ERR_DESCRIPTOR; + ERROR( + "[network_framework.on_interface_event] Failed to create a bonjour " + "browse descriptor"); + goto ERR_DESCRIPTOR; } nw_browser_t browser = nw_browser_create(descriptor, parameters); nw_browser_set_queue(browser, dispatch_get_main_queue()); - nw_browser_set_browse_results_changed_handler(browser, ^(nw_browse_result_t result, nw_browse_result_t result2, bool flag) { - /* Dump result */ - printfi(0, "NEW BROWSE RESULT"); - printfi(1, "Result:"); - dump_browse_result(result, 2); - printfi(1, "Result2:"); - dump_browse_result(result2, 2); - printfi(1, "Flag: %s\n", (flag?"ON":"OFF")); - - /* Changes */ - nw_browse_result_change_t change = nw_browse_result_get_changes(result, result2); - switch(change) { - case nw_browse_result_change_identical: - printfi(2, "The compared services are identical."); - break; - case nw_browse_result_change_result_added: - printfi(2, "A new service was discovered."); - break; - - case nw_browse_result_change_result_removed: - printfi(2, "A previously discovered service was removed."); - break; - - case nw_browse_result_change_txt_record_changed: - printfi(2, "The service's associated TXT record changed."); - break; - - case nw_browse_result_change_interface_added: - printfi(2, "The service was discovered over a new interface."); - break; - - case nw_browse_result_change_interface_removed: - printfi(2, "The service was no longer discovered over a certain interface."); - break; - } + nw_browser_set_browse_results_changed_handler(browser, ^( + nw_browse_result_t result, + nw_browse_result_t + result2, + bool flag) { + /* Dump result */ + printfi(0, "NEW BROWSE RESULT"); + printfi(1, "Result:"); + dump_browse_result(result, 2); + printfi(1, "Result2:"); + dump_browse_result(result2, 2); + printfi(1, "Flag: %s\n", (flag ? "ON" : "OFF")); + + /* Changes */ + nw_browse_result_change_t change = + nw_browse_result_get_changes(result, result2); + switch (change) { + case nw_browse_result_change_identical: + printfi(2, "The compared services are identical."); + break; + case nw_browse_result_change_result_added: + printfi(2, "A new service was discovered."); + break; + + case nw_browse_result_change_result_removed: + printfi(2, "A previously discovered service was removed."); + break; + + case nw_browse_result_change_txt_record_changed: + printfi(2, "The service's associated TXT record changed."); + break; + + case nw_browse_result_change_interface_added: + printfi(2, "The service was discovered over a new interface."); + break; + + case nw_browse_result_change_interface_removed: + printfi( + 2, + "The service was no longer discovered over a certain interface."); + break; + } }); nw_browser_start(browser); @@ -524,20 +524,20 @@ void on_interface_event(interface_t * interface, nw_interface_t iface) nw_endpoint_t endpoint; DEBUG("Creating bonjour service towards NAME=%s TYPE=%s DOMAIN=%s", - BONJOUR_SERVICE_NAME, BONJOUR_SERVICE_TYPE, BONJOUR_SERVICE_DOMAIN); + BONJOUR_SERVICE_NAME, BONJOUR_SERVICE_TYPE, BONJOUR_SERVICE_DOMAIN); endpoint = nw_endpoint_create_bonjour_service( - BONJOUR_SERVICE_NAME, - BONJOUR_SERVICE_TYPE, - BONJOUR_SERVICE_DOMAIN); + BONJOUR_SERVICE_NAME, BONJOUR_SERVICE_TYPE, BONJOUR_SERVICE_DOMAIN); if (!endpoint) { - ERROR("[network_framework.on_interface_event] Failed to create bound Bonjour connection"); - goto ERR_ENDPOINT; + ERROR( + "[network_framework.on_interface_event] Failed to create bound " + "Bonjour " + "connection"); + goto ERR_ENDPOINT; } nw_connection_t connection = nw_connection_create(endpoint, parameters); - if (!connection) - goto ERR_CONNECTION; + if (!connection) goto ERR_CONNECTION; nw_release(endpoint); nw_release(parameters); @@ -547,108 +547,98 @@ void on_interface_event(interface_t * interface, nw_interface_t iface) /* Setup connection handlers */ - nw_connection_set_state_changed_handler(connection, ^(nw_connection_state_t state, nw_error_t error) { - on_connection_state_event(interface, iface, connection, state, error); - }); + nw_connection_set_state_changed_handler( + connection, ^(nw_connection_state_t state, nw_error_t error) { + on_connection_state_event(interface, iface, connection, state, error); + }); nw_connection_set_path_changed_handler(connection, ^(nw_path_t path) { - on_connection_path_event(interface, iface, connection, path); + on_connection_path_event(interface, iface, connection, path); }); nw_connection_set_better_path_available_handler(connection, ^(bool value) { #if 1 - DEBUG("Connection [better path = %s]\n", (value ? "true" : "false")); - WITH_DEBUG({ - dump_connection(connection, 1); - }); + DEBUG("Connection [better path = %s]\n", (value ? "true" : "false")); + WITH_DEBUG({ dump_connection(connection, 1); }); #endif }); nw_connection_set_viability_changed_handler(connection, ^(bool value) { #if 1 - DEBUG("Connection [viable = %s]\n", (value ? "true" : "false")); - WITH_DEBUG({ - //dump_connection(connection, 1); - }); + DEBUG("Connection [viable = %s]\n", (value ? "true" : "false")); + WITH_DEBUG({ + // dump_connection(connection, 1); + }); #endif - /* - * This is the first time we have a connection with address and port - * and thus the full identification of an hICN face - */ - facelet_t * facelet = facelet_create_from_connection(connection); - if (!facelet) - return; - facelet_set_event(facelet, value ? FACELET_EVENT_CREATE : FACELET_EVENT_DELETE); - interface_raise_event(interface, facelet); - + /* + * This is the first time we have a connection with address and port + * and thus the full identification of an hICN face + */ + facelet_t *facelet = facelet_create_from_connection(connection); + if (!facelet) return; + facelet_set_event(facelet, + value ? FACELET_EVENT_CREATE : FACELET_EVENT_DELETE); + interface_raise_event(interface, facelet); }); nw_connection_start(connection); nw_connection_set_queue(connection, dispatch_get_main_queue()); - nw_retain(connection); // Hold a reference until cancelled + nw_retain(connection); // Hold a reference until cancelled #if 1 DEBUG("Created Bonjour cnx on interface:"); - WITH_DEBUG({ - dump_interface(iface, 1); - }); + WITH_DEBUG({ dump_interface(iface, 1); }); #endif return; - nw_release(connection); -ERR_CONNECTION: + nw_release(connection); + ERR_CONNECTION: nw_release(endpoint); -ERR_ENDPOINT: + ERR_ENDPOINT: #if defined(MAC_OS_X_VERSION_10_15) nw_release(descriptor); -ERR_DESCRIPTOR: + ERR_DESCRIPTOR: #endif /* defined(MAC_OS_X_VERSION_10_15) */ nw_release(parameters); -ERR_PARAMETERS: + ERR_PARAMETERS: return; -} + } -void on_path_event(interface_t * interface, nw_path_t path) -{ + void on_path_event(interface_t * interface, nw_path_t path) { /* Simplification: we handle path event only once. * Ideally, test whether we discover new interfaces or not */ #if 1 DEBUG("Path [event]:\n"); - WITH_DEBUG({ - dump_path(path, 1); - }); + WITH_DEBUG({ dump_path(path, 1); }); #endif - nw_path_enumerate_interfaces(path, (nw_path_enumerate_interfaces_block_t)^(nw_interface_t iface) { - on_interface_event(interface, iface); - return true; - }); - -} + nw_path_enumerate_interfaces( + path, (nw_path_enumerate_interfaces_block_t) ^ (nw_interface_t iface) { + on_interface_event(interface, iface); + return true; + }); + } -int nf_initialize(interface_t * interface, void * cfg) -{ - nf_data_t * data = malloc(sizeof(nf_data_t)); - if (!data) - goto ERR_MALLOC; + int nf_initialize(interface_t * interface, void *cfg) { + nf_data_t *data = malloc(sizeof(nf_data_t)); + if (!data) goto ERR_MALLOC; - if (cfg) - data->cfg = * (network_framework_cfg_t *)cfg; + if (cfg) data->cfg = *(network_framework_cfg_t *)cfg; data->pm = nw_path_monitor_create(); - if (!data->pm) - goto ERR_PM; + if (!data->pm) goto ERR_PM; nw_path_monitor_set_queue(data->pm, dispatch_get_main_queue()); - nw_path_monitor_set_cancel_handler(data->pm, ^() { }); + nw_path_monitor_set_cancel_handler(data->pm, ^(){ + }); nw_path_monitor_set_update_handler(data->pm, ^(nw_path_t path) { - on_path_event(interface, path); - }); + on_path_event(interface, path); + }); // XXX NEEDED ? nw_retain(data->pm); @@ -659,25 +649,24 @@ int nf_initialize(interface_t * interface, void * cfg) interface->data = data; return 0; -ERR_PM: + ERR_PM: free(data); -ERR_MALLOC: + ERR_MALLOC: return -1; -} + } -int nf_finalize(interface_t * interface) -{ - nf_data_t * data = (nf_data_t*)interface->data; + int nf_finalize(interface_t * interface) { + nf_data_t *data = (nf_data_t *)interface->data; if (data->pm) { - nw_path_monitor_cancel(data->pm); - data->pm = NULL; + nw_path_monitor_cancel(data->pm); + data->pm = NULL; } return 0; -} - -const interface_ops_t network_framework_ops = { - .type = "network_framework", - .initialize = nf_initialize, - .finalize = nf_finalize, - .on_event = NULL, -}; + } + + const interface_ops_t network_framework_ops = { + .type = "network_framework", + .initialize = nf_initialize, + .finalize = nf_finalize, + .on_event = NULL, + }; diff --git a/ctrl/facemgr/src/interfaces/network_framework/network_framework.h b/ctrl/facemgr/src/interfaces/network_framework/network_framework.h index edb35e904..768edc253 100644 --- a/ctrl/facemgr/src/interfaces/network_framework/network_framework.h +++ b/ctrl/facemgr/src/interfaces/network_framework/network_framework.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -19,4 +19,5 @@ */ typedef struct { + void *_; } network_framework_cfg_t; diff --git a/ctrl/facemgr/src/interfaces/priority_controller/CMakeLists.txt b/ctrl/facemgr/src/interfaces/priority_controller/CMakeLists.txt index 8d18800db..43ba31b0b 100644 --- a/ctrl/facemgr/src/interfaces/priority_controller/CMakeLists.txt +++ b/ctrl/facemgr/src/interfaces/priority_controller/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021 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: diff --git a/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.c b/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.c index 67edc5e39..5d2f695f9 100644 --- a/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.c +++ b/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -34,20 +34,21 @@ #define PC_DEFAULT_PORT 9533 typedef struct { - priority_controller_cfg_t cfg; - int fd; + priority_controller_cfg_t cfg; + int fd; #ifdef PRIORITY_CONTROLLER_INTERNAL - unsigned state; - JNIEnv * env; - jclass cls; - jmethodID mid; + unsigned state; + JNIEnv *env; + jclass cls; + jmethodID mid; #endif /* PRIORITY_CONTROLLER_INTERNAL */ } pc_data_t; #ifdef PRIORITY_CONTROLLER_INTERNAL #include <jni.h> -#define ERR_STR_JAVA "Java VM parameters are required in the interface configuration." +#define ERR_STR_JAVA \ + "Java VM parameters are required in the interface configuration." #define PREFER_CELLULAR 0 #define PREFER_WIFI 1 @@ -55,147 +56,146 @@ typedef struct { #define INTERVAL_MS 500 -const char * prefer_str[] = { "Cellular", "WiFi", "both" }; +const char *prefer_str[] = {"Cellular", "WiFi", "both"}; -jclass find_class_global(JNIEnv* env, const char *name){ - jclass c = (*env)->FindClass(env, name); - jclass c_global = 0; - if (c){ - c_global = (jclass)(*env)->NewGlobalRef(env, c); - (*env)->DeleteLocalRef(env, c); - } - return c_global; +jclass find_class_global(JNIEnv *env, const char *name) { + jclass c = (*env)->FindClass(env, name); + jclass c_global = 0; + if (c) { + c_global = (jclass)(*env)->NewGlobalRef(env, c); + (*env)->DeleteLocalRef(env, c); + } + return c_global; } +int priority_controller_tick(interface_t *interface, int fd, void *unused) { + pc_data_t *data = (pc_data_t *)interface->data; + unsigned new_state = PREFER_BOTH; -int priority_controller_tick(interface_t * interface, int fd, void * unused) -{ - pc_data_t * data = (pc_data_t*)interface->data; - unsigned new_state = PREFER_BOTH; - - jint rssi = (*data->env)->CallStaticIntMethod(data->env, data->cls, data->mid); - DEBUG("[priority_controller_tick] rssi=%d\n", rssi); - if (rssi > -67) { - new_state = PREFER_WIFI; + jint rssi = + (*data->env)->CallStaticIntMethod(data->env, data->cls, data->mid); + DEBUG("[priority_controller_tick] rssi=%d\n", rssi); + if (rssi > -67) { + new_state = PREFER_WIFI; #if 0 } else if ((rssi < -67) && (rssi > -70)) { new_state = PREFER_BOTH; #endif - } else { /* rssi < -70 */ - new_state = PREFER_CELLULAR; - } + } else { /* rssi < -70 */ + new_state = PREFER_CELLULAR; + } - if (new_state == data->state) - return 0; + if (new_state == data->state) return 0; - ERROR("[priority_controller_tick] Setting priority to %s", prefer_str[new_state]); + ERROR("[priority_controller_tick] Setting priority to %s", + prefer_str[new_state]); - /* XXX Factor this */ + /* XXX Factor this */ - facelet_t * facelet_w = facelet_create(); - facelet_t * facelet_c = facelet_create(); - facelet_set_netdevice_type(facelet_w, NETDEVICE_TYPE_WIFI); - facelet_set_netdevice_type(facelet_c, NETDEVICE_TYPE_CELLULAR); - facelet_set_attr_clean(facelet_w); - facelet_set_attr_clean(facelet_c); + facelet_t *facelet_w = facelet_create(); + facelet_t *facelet_c = facelet_create(); + facelet_set_netdevice_type(facelet_w, NETDEVICE_TYPE_WIFI); + facelet_set_netdevice_type(facelet_c, NETDEVICE_TYPE_CELLULAR); + facelet_set_attr_clean(facelet_w); + facelet_set_attr_clean(facelet_c); - switch(new_state) { - case PREFER_CELLULAR: - facelet_set_priority(facelet_w, 0); - facelet_set_priority(facelet_c, 10); - break; - case PREFER_WIFI: - facelet_set_priority(facelet_w, 10); - facelet_set_priority(facelet_c, 0); - break; - case PREFER_BOTH: - facelet_set_priority(facelet_w, 0); - facelet_set_priority(facelet_c, 0); - break; - } + switch (new_state) { + case PREFER_CELLULAR: + facelet_set_priority(facelet_w, 0); + facelet_set_priority(facelet_c, 10); + break; + case PREFER_WIFI: + facelet_set_priority(facelet_w, 10); + facelet_set_priority(facelet_c, 0); + break; + case PREFER_BOTH: + facelet_set_priority(facelet_w, 0); + facelet_set_priority(facelet_c, 0); + break; + } - facelet_set_event(facelet_w, FACELET_EVENT_UPDATE); - facelet_set_event(facelet_c, FACELET_EVENT_UPDATE); + facelet_set_event(facelet_w, FACELET_EVENT_UPDATE); + facelet_set_event(facelet_c, FACELET_EVENT_UPDATE); - interface_raise_event(interface, facelet_w); - interface_raise_event(interface, facelet_c); + interface_raise_event(interface, facelet_w); + interface_raise_event(interface, facelet_c); - data->state = new_state; + data->state = new_state; - return 0; + return 0; } #endif /* PRIORITY_CONTROLLER_INTERNAL */ -int priority_controller_initialize(interface_t * interface, void * cfg) -{ - INFO("Initializing priority controller"); +int priority_controller_initialize(interface_t *interface, void *cfg) { + INFO("Initializing priority controller"); - pc_data_t * data = malloc(sizeof(pc_data_t)); - if (!data) { - INFO("Priority controller data memory allocation error"); - goto ERR_MALLOC; - } + pc_data_t *data = malloc(sizeof(pc_data_t)); + if (!data) { + INFO("Priority controller data memory allocation error"); + goto ERR_MALLOC; + } - interface->data = data; + interface->data = data; - data->cfg = * (priority_controller_cfg_t *) cfg; + data->cfg = *(priority_controller_cfg_t *)cfg; #ifdef PRIORITY_CONTROLLER_INTERNAL - if (!cfg) { - ERROR(ERR_STR_JAVA); - goto ERR_CFG; - } - - /* Retrieve RSSI information from SDK through AndroidUtility class */ - (*data->cfg.jvm)->AttachCurrentThread(data->cfg.jvm, &data->env, NULL); - data->cls = find_class_global(data->env, FACEMGR_ANDROID_UTILITY_CLASS); - if (data->cls == 0) - goto ERR_JAVA; - data->mid = (*data->env)->GetStaticMethodID(data->env, data->cls, "getWifiRSSI", "()I"); - - data->fd = interface_register_timer(interface, INTERVAL_MS, - priority_controller_tick, interface); - if (data->fd < 0) { - ERROR("[priority_controller_initialize] Could not initialize timer"); - goto ERR_FD; - } - data->state = PREFER_BOTH; + if (!cfg) { + ERROR(ERR_STR_JAVA); + goto ERR_CFG; + } + + /* Retrieve RSSI information from SDK through AndroidUtility class */ + (*data->cfg.jvm)->AttachCurrentThread(data->cfg.jvm, &data->env, NULL); + data->cls = find_class_global(data->env, FACEMGR_ANDROID_UTILITY_CLASS); + if (data->cls == 0) goto ERR_JAVA; + data->mid = + (*data->env) + ->GetStaticMethodID(data->env, data->cls, "getWifiRSSI", "()I"); + + data->fd = interface_register_timer(interface, INTERVAL_MS, + priority_controller_tick, interface); + if (data->fd < 0) { + ERROR("[priority_controller_initialize] Could not initialize timer"); + goto ERR_FD; + } + data->state = PREFER_BOTH; #else /* PRIORITY_CONTROLLER_INTERNAL */ - struct sockaddr_in addr; - - data->fd = socket(AF_INET, SOCK_DGRAM, 0); - //data->fd = socket(AF_INET, SOCK_STREAM, 0); - if (data->fd < 0) { - INFO("Priority controller socket error"); - perror("socket error"); - goto ERR_SOCKET; - } - - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_addr.s_addr = inet_addr("127.0.0.1"); - addr.sin_port = htons(PC_DEFAULT_PORT); - - if (bind(data->fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { - INFO("Priority controller socket bind error"); - perror("bind error"); - goto ERR_BIND; - } - - DEBUG("[priority_controller_initialize] register fd"); - if (interface_register_fd(interface, data->fd, NULL) < 0) { - ERROR("[priority_controller_initialize] Error registering fd"); - goto ERR_FD; - } + struct sockaddr_in addr; + + data->fd = socket(AF_INET, SOCK_DGRAM, 0); + // data->fd = socket(AF_INET, SOCK_STREAM, 0); + if (data->fd < 0) { + INFO("Priority controller socket error"); + perror("socket error"); + goto ERR_SOCKET; + } + + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = inet_addr("127.0.0.1"); + addr.sin_port = htons(PC_DEFAULT_PORT); + + if (bind(data->fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + INFO("Priority controller socket bind error"); + perror("bind error"); + goto ERR_BIND; + } + + DEBUG("[priority_controller_initialize] register fd"); + if (interface_register_fd(interface, data->fd, NULL) < 0) { + ERROR("[priority_controller_initialize] Error registering fd"); + goto ERR_FD; + } #endif /* PRIORITY_CONTROLLER_INTERNAL */ - INFO("Priority controller successfully initialized"); - return 0; + INFO("Priority controller successfully initialized"); + return 0; #ifdef PRIORITY_CONTROLLER_INTERNAL ERR_CFG: @@ -204,86 +204,86 @@ ERR_JAVA: ERR_FD: #ifndef PRIORITY_CONTROLLER_INTERNAL ERR_BIND: - close(data->fd); + close(data->fd); ERR_SOCKET: #endif /* ! PRIORITY_CONTROLLER_INTERNAL */ - free(data); + free(data); ERR_MALLOC: - return -1; + return -1; } -int priority_controller_finalize(interface_t * interface) -{ - pc_data_t * data = (pc_data_t*)interface->data; +int priority_controller_finalize(interface_t *interface) { + pc_data_t *data = (pc_data_t *)interface->data; #ifdef PRIORITY_CONTROLLER_INTERNAL - DEBUG("[priority_controller_finalize] unregister timer"); - interface_unregister_timer(interface, data->fd); + DEBUG("[priority_controller_finalize] unregister timer"); + interface_unregister_timer(interface, data->fd); #else - if (data->fd > 0) { - interface_unregister_fd(interface, data->fd); - close(data->fd); - } - free(data); + if (data->fd > 0) { + interface_unregister_fd(interface, data->fd); + close(data->fd); + } + free(data); #endif /* PRIORITY_CONTROLLER_INTERNAL */ - return 0; + return 0; } #ifndef PRIORITY_CONTROLLER_INTERNAL -int priority_controller_callback(interface_t * interface, int fd, void * unused) -{ - pc_data_t * data = (pc_data_t*)interface->data; - char buf[100]; - int rc; - - INFO("Priority controller receiving command"); - - rc = recv(data->fd, buf, 100, 0); - - if (rc < 0) { - INFO("Priority controller read error"); - return -1; - } - - INFO("Priority controller received command: %02X", buf[0]); - - facelet_t * facelet_w = facelet_create(); - facelet_t * facelet_c = facelet_create(); - facelet_set_netdevice_type(facelet_w, NETDEVICE_TYPE_WIFI); - facelet_set_netdevice_type(facelet_c, NETDEVICE_TYPE_CELLULAR); - facelet_set_attr_clean(facelet_w); - facelet_set_attr_clean(facelet_c); - switch(buf[0]) { - case '\0': - facelet_set_priority(facelet_w, 0); - facelet_set_priority(facelet_c, 10); - INFO("Priority controller configuring Cellular preferred"); - break; - case '\1': - facelet_set_priority(facelet_w, 10); - facelet_set_priority(facelet_c, 0); - INFO("Priority controller configuring Wi-Fi preferred"); - break; - case '\2': - facelet_set_priority(facelet_w, 0); - facelet_set_priority(facelet_c, 0); - INFO("Priority controller configuring both Cellular and Wi-Fi preferred"); - break; - default: - INFO("Priority controller invalid data received from updown server. Ignoring..."); - facelet_free(facelet_w); - facelet_free(facelet_c); - return 0; - } - - facelet_set_event(facelet_w, FACELET_EVENT_UPDATE); - facelet_set_event(facelet_c, FACELET_EVENT_UPDATE); - - interface_raise_event(interface, facelet_w); - interface_raise_event(interface, facelet_c); - - return 0; +int priority_controller_callback(interface_t *interface, int fd, void *unused) { + pc_data_t *data = (pc_data_t *)interface->data; + char buf[100]; + int rc; + + INFO("Priority controller receiving command"); + + rc = recv(data->fd, buf, 100, 0); + + if (rc < 0) { + INFO("Priority controller read error"); + return -1; + } + + INFO("Priority controller received command: %02X", buf[0]); + + facelet_t *facelet_w = facelet_create(); + facelet_t *facelet_c = facelet_create(); + facelet_set_netdevice_type(facelet_w, NETDEVICE_TYPE_WIFI); + facelet_set_netdevice_type(facelet_c, NETDEVICE_TYPE_CELLULAR); + facelet_set_attr_clean(facelet_w); + facelet_set_attr_clean(facelet_c); + switch (buf[0]) { + case '\0': + facelet_set_priority(facelet_w, 0); + facelet_set_priority(facelet_c, 10); + INFO("Priority controller configuring Cellular preferred"); + break; + case '\1': + facelet_set_priority(facelet_w, 10); + facelet_set_priority(facelet_c, 0); + INFO("Priority controller configuring Wi-Fi preferred"); + break; + case '\2': + facelet_set_priority(facelet_w, 0); + facelet_set_priority(facelet_c, 0); + INFO("Priority controller configuring both Cellular and Wi-Fi preferred"); + break; + default: + INFO( + "Priority controller invalid data received from updown server. " + "Ignoring..."); + facelet_free(facelet_w); + facelet_free(facelet_c); + return 0; + } + + facelet_set_event(facelet_w, FACELET_EVENT_UPDATE); + facelet_set_event(facelet_c, FACELET_EVENT_UPDATE); + + interface_raise_event(interface, facelet_w); + interface_raise_event(interface, facelet_c); + + return 0; } #endif /* ! PRIORITY_CONTROLLER_INTERNAL */ diff --git a/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.h b/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.h index 247fc3c57..7f257ffcf 100644 --- a/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.h +++ b/ctrl/facemgr/src/interfaces/priority_controller/priority_controller.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -21,7 +21,8 @@ #ifndef FACEMGR_INTERFACE_PRIORITY_CONTROLLER #define FACEMGR_INTERFACE_PRIORITY_CONTROLLER -#define FACEMGR_UTILITY_CLASS "com/cisco/hicn/facemgrlibrary/supportlibrary/FacemgrUtility" +#define FACEMGR_UTILITY_CLASS \ + "com/cisco/hicn/facemgrlibrary/supportlibrary/FacemgrUtility" /* * Uncomment this line to use a Priority controller interface internal to the @@ -36,10 +37,9 @@ typedef struct { #ifdef __ANDROID__ #ifdef PRIORITY_CONTROLLER_INTERNAL - JavaVM * jvm; + JavaVM* jvm; #endif /* PRIORITY_CONTROLLER_INTERNAL */ #endif /* __ANDROID__ */ } priority_controller_cfg_t; - #endif /* FACEMGR_INTERFACE_PRIORITY_CONTROLLER */ diff --git a/ctrl/facemgr/src/interfaces/updown/CMakeLists.txt b/ctrl/facemgr/src/interfaces/updown/CMakeLists.txt index e5fd2167e..4c6c0ea6c 100644 --- a/ctrl/facemgr/src/interfaces/updown/CMakeLists.txt +++ b/ctrl/facemgr/src/interfaces/updown/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2017-2019 Cisco and/or its affiliates. +# Copyright (c) 2021 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: diff --git a/ctrl/facemgr/src/interfaces/updown/updown.c b/ctrl/facemgr/src/interfaces/updown/updown.c index 7d305a5cd..8d31f6cd4 100644 --- a/ctrl/facemgr/src/interfaces/updown/updown.c +++ b/ctrl/facemgr/src/interfaces/updown/updown.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2019 Cisco and/or its affiliates. + * Copyright (c) 2021 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: @@ -26,6 +26,7 @@ #include <unistd.h> #include <hicn/facemgr.h> +#include <hicn/util/sstrncpy.h> #include "../../common.h" #include "../../interface.h" @@ -37,107 +38,101 @@ #define UNIX_PATH "\0updownsrv" typedef struct { - int fd; /* Unix client socket */ + int fd; /* Unix client socket */ } updown_data_t; -int updown_initialize(interface_t * interface, void * cfg) -{ - struct sockaddr_un addr; - char * socket_path = UNIX_PATH; - - updown_data_t * data = malloc(sizeof(updown_data_t)); - if (!data) - goto ERR_MALLOC; - interface->data = data; - - data->fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (data->fd == -1) { - perror("socket error"); - goto ERR_SOCKET; - } - - memset(&addr, 0, sizeof(addr)); - addr.sun_family = AF_UNIX; - if (*socket_path == '\0') { - *addr.sun_path = '\0'; - strncpy(addr.sun_path+1, socket_path+1, sizeof(addr.sun_path)-2); - } else { - strncpy(addr.sun_path, socket_path, sizeof(addr.sun_path)-1); - } - - if (connect(data->fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) { - perror("connect error"); - goto ERR_CONNECT; - } - - if (interface_register_fd(interface, data->fd, NULL) < 0) { - ERROR("[updown_initialize] Error registering fd"); - goto ERR_FD; - } - - return 0; +int updown_initialize(interface_t* interface, void* cfg) { + struct sockaddr_un addr; + char* socket_path = UNIX_PATH; + + updown_data_t* data = malloc(sizeof(updown_data_t)); + if (!data) goto ERR_MALLOC; + interface->data = data; + + data->fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (data->fd == -1) { + perror("socket error"); + goto ERR_SOCKET; + } + + memset(&addr, 0, sizeof(addr)); + addr.sun_family = AF_UNIX; + if (*socket_path == '\0') { + *addr.sun_path = '\0'; + strcpy_s(addr.sun_path + 1, sizeof(addr.sun_path) - 2, socket_path + 1); + } else { + strcpy_s(addr.sun_path, sizeof(addr.sun_path) - 1, socket_path); + } + + if (connect(data->fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) { + perror("connect error"); + goto ERR_CONNECT; + } + + if (interface_register_fd(interface, data->fd, NULL) < 0) { + ERROR("[updown_initialize] Error registering fd"); + goto ERR_FD; + } + + return 0; ERR_FD: ERR_CONNECT: - close(data->fd); + close(data->fd); ERR_SOCKET: - free(data); + free(data); ERR_MALLOC: - return -1; + return -1; } -int updown_finalize(interface_t * interface) -{ - updown_data_t * data = (updown_data_t*)interface->data; +int updown_finalize(interface_t* interface) { + updown_data_t* data = (updown_data_t*)interface->data; - if (data->fd > 0) - close(data->fd); - free(data); + if (data->fd > 0) close(data->fd); + free(data); - return 0; + return 0; } -int updown_callback(interface_t * interface, int fd, void * unused) -{ - updown_data_t * data = (updown_data_t*)interface->data; - char buf[100]; - int rc; - - rc = read(data->fd, buf, sizeof(buf)); - if (rc < 0) - return -1; - - /* - * If the process is paused (eg. in a debugger, we might have more than one - * read. - * XXX how big is the buffer - * XXX shall we drain the queue if it exceeds buffer size ? - */ - //assert(rc == 1); - - /* Raise facelet update event */ - facelet_t * facelet = facelet_create(); - facelet_set_netdevice_type(facelet, NETDEVICE_TYPE_WIFI); //CELLULAR); - facelet_set_attr_clean(facelet); - switch(buf[0]) { - case '\0': - facelet_set_admin_state(facelet, FACE_STATE_DOWN); - break; - case '\1': - facelet_set_admin_state(facelet, FACE_STATE_UP); - break; - break; - default: - ERROR("Invalid data received from updown server. Ignoring..."); - facelet_free(facelet); - return -1; - } - - facelet_set_event(facelet, FACELET_EVENT_UPDATE); - - interface_raise_event(interface, facelet); - - return 0; +int updown_callback(interface_t* interface, int fd, void* unused) { + updown_data_t* data = (updown_data_t*)interface->data; + char buf[100]; + int rc; + + rc = read(data->fd, buf, sizeof(buf)); + if (rc < 0) return -1; + + /* + * If the process is paused (eg. in a debugger, we might have more than one + * read. + * XXX how big is the buffer + * XXX shall we drain the queue if it exceeds buffer size ? + */ + // assert(rc == 1); + + /* Raise facelet update event */ + facelet_t* facelet = facelet_create(); + facelet_set_netdevice_type(facelet, NETDEVICE_TYPE_WIFI); // CELLULAR); + facelet_set_attr_clean(facelet); + switch (buf[0]) { + case '\0': + facelet_set_admin_state(facelet, FACE_STATE_DOWN); + break; + case '\1': + facelet_set_admin_state(facelet, FACE_STATE_UP); + break; + break; + default: + ERROR("Invalid data received from updown server. Ignoring..."); + facelet_free(facelet); + return -1; + } + + facelet_set_event(facelet, FACELET_EVENT_UPDATE); + + interface_raise_event(interface, facelet); + + return 0; } interface_ops_t updown_ops = { |