From c01a4c47d2ac21f54ad86a618eec30921f2bc73d Mon Sep 17 00:00:00 2001 From: Sander Vrijders Date: Wed, 27 Apr 2016 21:36:26 +0200 Subject: ipcpd: Add registration to DNS server This adds support for adding the application name to a BIND DNS server through the nsupdate utility. --- include/ouroboros/config.h.in | 1 + src/ipcpd/shim-udp/CMakeLists.txt | 36 ++++++++----- src/ipcpd/shim-udp/main.c | 103 +++++++++++++++++++++++++++++++++++--- 3 files changed, 121 insertions(+), 19 deletions(-) diff --git a/include/ouroboros/config.h.in b/include/ouroboros/config.h.in index 6abce97a..380c1065 100644 --- a/include/ouroboros/config.h.in +++ b/include/ouroboros/config.h.in @@ -30,5 +30,6 @@ #define _POSIX_C_SOURCE 199506L #define IPCP_SHIM_UDP_EXEC "@IPCP_SHIM_UDP_TARGET@" #define IPCP_NORMAL_EXEC "@IPCP_NORMAL_TARGET@" +#define NSUPDATE_EXEC "@NSUPDATE_EXECUTABLE@" #endif diff --git a/src/ipcpd/shim-udp/CMakeLists.txt b/src/ipcpd/shim-udp/CMakeLists.txt index f730fa3a..c71fa00b 100644 --- a/src/ipcpd/shim-udp/CMakeLists.txt +++ b/src/ipcpd/shim-udp/CMakeLists.txt @@ -14,30 +14,40 @@ include_directories(${CMAKE_BINARY_DIR}/include) include(CheckFunctionExists) CHECK_FUNCTION_EXISTS("gethostbyname" CMAKE_HAVE_GETHOSTBYNAME) IF(NOT CMAKE_HAVE_GETHOSTBYNAME) - CHECK_LIBRARY_EXISTS("nsl" "gethostbyname" "" CMAKE_LIB_NSL_HAS_GETHOSTBYNAME) - IF (CMAKE_LIB_NSL_HAS_GETHOSTBYNAME) - SET (X11_X_EXTRA_LIBS ${X11_X_EXTRA_LIBS} -lnsl) - ELSE (CMAKE_LIB_NSL_HAS_GETHOSTBYNAME) - CHECK_LIBRARY_EXISTS("bsd" "gethostbyname" "" CMAKE_LIB_BSD_HAS_GETHOSTBYNAME) - IF (CMAKE_LIB_BSD_HAS_GETHOSTBYNAME) - SET (X11_X_EXTRA_LIBS ${X11_X_EXTRA_LIBS} -lbsd) - ENDIF (CMAKE_LIB_BSD_HAS_GETHOSTBYNAME) - ENDIF (CMAKE_LIB_NSL_HAS_GETHOSTBYNAME) + CHECK_LIBRARY_EXISTS("nsl" "gethostbyname" "" CMAKE_LIB_NSL_HAS_GETHOSTBYNAME) + IF (CMAKE_LIB_NSL_HAS_GETHOSTBYNAME) + SET (X11_X_EXTRA_LIBS ${X11_X_EXTRA_LIBS} -lnsl) + ELSE (CMAKE_LIB_NSL_HAS_GETHOSTBYNAME) + CHECK_LIBRARY_EXISTS("bsd" "gethostbyname" "" CMAKE_LIB_BSD_HAS_GETHOSTBYNAME) + IF (CMAKE_LIB_BSD_HAS_GETHOSTBYNAME) + SET (X11_X_EXTRA_LIBS ${X11_X_EXTRA_LIBS} -lbsd) + ENDIF (CMAKE_LIB_BSD_HAS_GETHOSTBYNAME) + ENDIF (CMAKE_LIB_NSL_HAS_GETHOSTBYNAME) ENDIF(NOT CMAKE_HAVE_GETHOSTBYNAME) +# Find the nsupdate executable +find_program(NSUPDATE_EXECUTABLE + NAMES nsupdate + DOC "The nsupdate tool that enables DDNS") + +if (${NSUPDATE_EXECUTABLE} STREQUAL "NSUPDATE_EXECUTABLE-NOTFOUND") + message(FATAL_ERROR "Could not find nsupdate, which is needed for DDNS") +else() + message("-- Found nsupdate: ${NSUPDATE_EXECUTABLE}") +endif() + SET(IPCP_SHIM_UDP_TARGET ipcpd-shim-udp CACHE STRING "IPCP_SHIM_UDP_TARGET") set(SHIM_UDP_SOURCES - # Add source files here - ${CMAKE_CURRENT_SOURCE_DIR}/main.c -) + # Add source files here + ${CMAKE_CURRENT_SOURCE_DIR}/main.c) add_executable (ipcpd-shim-udp ${SHIM_UDP_SOURCES} ${IPCP_SOURCES}) target_link_libraries (ipcpd-shim-udp LINK_PUBLIC ouroboros) include(MacroAddCompileFlags) if (CMAKE_BUILD_TYPE MATCHES Debug) - MACRO_ADD_COMPILE_FLAGS(ipcpd-shim-udp -DCONFIG_OUROBOROS_DEBUG) + MACRO_ADD_COMPILE_FLAGS(ipcpd-shim-udp -DCONFIG_OUROBOROS_DEBUG) endif (CMAKE_BUILD_TYPE MATCHES Debug) install(TARGETS ipcpd-shim-udp RUNTIME DESTINATION bin) diff --git a/src/ipcpd/shim-udp/main.c b/src/ipcpd/shim-udp/main.c index 71c414ef..460fe9e3 100644 --- a/src/ipcpd/shim-udp/main.c +++ b/src/ipcpd/shim-udp/main.c @@ -44,11 +44,13 @@ #include #include #include +#include #define THIS_TYPE IPCP_SHIM_UDP #define LISTEN_PORT htons(0x0D1F) #define SHIM_UDP_BUF_SIZE 256 #define SHIM_UDP_MAX_SDU_SIZE 8980 +#define DNS_TTL 86400 #define shim_data(type) ((struct ipcp_udp_data *) type->data) @@ -340,35 +342,124 @@ int ipcp_udp_bootstrap(struct dif_config * conf) return 0; } +/* FIXME: Dependency on nsupdate to be removed in the end */ +static int ddns_send(char * cmd) +{ + pid_t pid = 0; + int wstatus; + int pipe_fd[2]; + char * argv[] = {NSUPDATE_EXEC, 0}; + char * envp[] = {0}; + + if (pipe(pipe_fd)) { + LOG_ERR("Failed to create pipe."); + return -1; + } + + pid = fork(); + if (pid == -1) { + LOG_ERR("Failed to fork."); + return -1; + } + + if (pid == 0) { + close(pipe_fd[1]); + dup2(pipe_fd[0], 0); + execve(argv[0], &argv[0], envp); + } + + close(pipe_fd[0]); + + if (write(pipe_fd[1], cmd, strlen(cmd)) == -1) { + LOG_ERR("Failed to register with DNS server."); + close(pipe_fd[1]); + return -1; + } + + waitpid(pid, &wstatus, 0); + if (WIFEXITED(wstatus) == true && + WEXITSTATUS(wstatus) == 0) + LOG_DBGF("Succesfully communicated with DNS server."); + else + LOG_ERR("Failed to register with DNS server."); + + close(pipe_fd[1]); + return 0; +} + int ipcp_udp_name_reg(char * name) { + char ipstr[INET_ADDRSTRLEN]; + char dnsstr[INET_ADDRSTRLEN]; + /* max DNS name length + max IP length + command length */ + char cmd[100]; + uint32_t dns_addr; + uint32_t ip_addr; + if (_ipcp->state != IPCP_ENROLLED) { LOG_DBGF("Won't register with non-enrolled IPCP."); return -1; } + if (strlen(name) > 24) { + LOG_ERR("DNS names cannot be longer than 24 chars."); + return -1; + } + if (ipcp_data_add_reg_entry(_ipcp->data, name)) { LOG_ERR("Failed to add %s to local registry.", name); return -1; } - LOG_DBG("Registered %s", name); + /* register application with DNS server */ + + dns_addr = shim_data(_ipcp)->dns_addr; + if (dns_addr != 0) { + ip_addr = shim_data(_ipcp)->ip_addr; - /* FIXME: register application with DNS server */ - LOG_MISSING; + inet_ntop(AF_INET, &ip_addr, ipstr, INET_ADDRSTRLEN); + inet_ntop(AF_INET, &dns_addr, dnsstr, INET_ADDRSTRLEN); + sprintf(cmd, "server %s\nupdate add %s %d A %s\nsend\nquit\n", + dnsstr, name, DNS_TTL, ipstr); + + if (ddns_send(cmd)) { + ipcp_data_del_reg_entry(_ipcp->data, name); + return -1; + } + } + + LOG_DBG("Registered %s.", name); return 0; } int ipcp_udp_name_unreg(char * name) { + char dnsstr[INET_ADDRSTRLEN]; + /* max DNS name length + max IP length + max command length */ + char cmd[100]; + uint32_t dns_addr; + + if (strlen(name) > 24) { + LOG_ERR("DNS names cannot be longer than 24 chars."); + return -1; + } + + /* unregister application with DNS server */ + + dns_addr = shim_data(_ipcp)->dns_addr; + if (dns_addr != 0) { + inet_ntop(AF_INET, &dns_addr, dnsstr, INET_ADDRSTRLEN); + sprintf(cmd, "server %s\nupdate delete %s A\nsend\nquit\n", + dnsstr, name); + + ddns_send(cmd); + } + ipcp_data_del_reg_entry(_ipcp->data, name); LOG_DBG("Unregistered %s.", name); - /* FIXME: unregister application from DNS server */ - LOG_MISSING; - return 0; } -- cgit v1.2.3