From dfda83926c50297d7c315f743b4514f687469c9c Mon Sep 17 00:00:00 2001 From: Sander Vrijders Date: Tue, 10 May 2016 16:33:53 +0200 Subject: ipcpd: Allow disabling of DNS This allows someone to disable the use of DNS in the shim UDP. It also adds a config file specific for the shim UDP (which holds the nsupdate location). Certain defines were also moved to the global config file. --- src/ipcpd/shim-udp/main.c | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) (limited to 'src/ipcpd/shim-udp/main.c') diff --git a/src/ipcpd/shim-udp/main.c b/src/ipcpd/shim-udp/main.c index e213f019..b45bee76 100644 --- a/src/ipcpd/shim-udp/main.c +++ b/src/ipcpd/shim-udp/main.c @@ -23,6 +23,7 @@ #include #include "ipcp.h" #include "flow.h" +#include "shim_udp_config.h" #include #include #include @@ -31,6 +32,7 @@ #include #include #include +#include #define OUROBOROS_PREFIX "ipcpd/shim-udp" @@ -74,19 +76,6 @@ struct ipcp * _ipcp; * the info */ -#define UNKNOWN_AP "__UNKNOWN_AP__" -#define UNKNOWN_AE "__UNKNOWN_AE__" - -#define AP_MAX_FLOWS 256 - -#ifndef DU_BUFF_HEADSPACE - #define DU_BUFF_HEADSPACE 128 -#endif - -#ifndef DU_BUFF_TAILSPACE - #define DU_BUFF_TAILSPACE 0 -#endif - /* the shim needs access to these internals */ struct shim_ap_data { instance_name_t * api; @@ -332,8 +321,11 @@ static void * ipcp_udp_listener() } /* echo back the packet */ - while(send(fd, buf, strlen(buf), 0) < 0) - ; + if (send(fd, buf, strlen(buf), 0) < 0) { + LOG_ERR("Failed to echo back the packet."); + close(fd); + continue; + } /* reply to IRM */ @@ -413,12 +405,16 @@ int ipcp_udp_bootstrap(struct dif_config * conf) ipstr, INET_ADDRSTRLEN); - if (conf->dns_addr != 0) + if (conf->dns_addr != 0) { inet_ntop(AF_INET, &conf->dns_addr, dnsstr, INET_ADDRSTRLEN); - else +#ifndef CONFIG_OUROBOROS_ENABLE_DNS + LOG_WARN("DNS address ignored since shim-udp was " + "compiled without DNS support."); +#endif + } else strcpy(dnsstr, "not set"); shim_data(_ipcp)->ip_addr = conf->ip_addr; @@ -480,6 +476,7 @@ int ipcp_udp_bootstrap(struct dif_config * conf) return 0; } +#ifdef CONFIG_OUROBOROS_ENABLE_DNS /* FIXME: Dependency on nsupdate to be removed in the end */ static int ddns_send(char * cmd) { @@ -524,15 +521,18 @@ static int ddns_send(char * cmd) close(pipe_fd[1]); return 0; } +#endif int ipcp_udp_name_reg(char * name) { +#ifdef CONFIG_OUROBOROS_ENABLE_DNS 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; +#endif if (_ipcp->state != IPCP_ENROLLED) { LOG_DBGF("Won't register with non-enrolled IPCP."); @@ -549,6 +549,7 @@ int ipcp_udp_name_reg(char * name) return -1; } +#ifdef CONFIG_OUROBOROS_ENABLE_DNS /* register application with DNS server */ dns_addr = shim_data(_ipcp)->dns_addr; @@ -565,6 +566,7 @@ int ipcp_udp_name_reg(char * name) return -1; } } +#endif LOG_DBG("Registered %s.", name); @@ -573,16 +575,19 @@ int ipcp_udp_name_reg(char * name) int ipcp_udp_name_unreg(char * name) { +#ifdef CONFIG_OUROBOROS_ENABLE_DNS char dnsstr[INET_ADDRSTRLEN]; /* max DNS name length + max IP length + max command length */ char cmd[100]; uint32_t dns_addr; +#endif if (strlen(name) > 24) { LOG_ERR("DNS names cannot be longer than 24 chars."); return -1; } +#ifdef CONFIG_OUROBOROS_ENABLE_DNS /* unregister application with DNS server */ dns_addr = shim_data(_ipcp)->dns_addr; @@ -593,6 +598,7 @@ int ipcp_udp_name_unreg(char * name) ddns_send(cmd); } +#endif ipcp_data_del_reg_entry(_ipcp->data, name); -- cgit v1.2.3 From ba8b2ba46a5b499004272c9acc9049539b600082 Mon Sep 17 00:00:00 2001 From: Sander Vrijders Date: Tue, 10 May 2016 18:42:00 +0200 Subject: ipcpd: Add nslookup to shim UDP This adds nslookup support to the shim UDP, so that a custom DNS server can be queried. --- src/ipcpd/shim-udp/CMakeLists.txt | 12 +++ src/ipcpd/shim-udp/main.c | 168 +++++++++++++++++++++++++++----- src/ipcpd/shim-udp/shim_udp_config.h.in | 1 + 3 files changed, 156 insertions(+), 25 deletions(-) (limited to 'src/ipcpd/shim-udp/main.c') diff --git a/src/ipcpd/shim-udp/CMakeLists.txt b/src/ipcpd/shim-udp/CMakeLists.txt index a50fe8bd..e10a8ca6 100644 --- a/src/ipcpd/shim-udp/CMakeLists.txt +++ b/src/ipcpd/shim-udp/CMakeLists.txt @@ -40,6 +40,18 @@ if (NOT DISABLE_DNS MATCHES True) else() message("-- Found nsupdate: ${NSUPDATE_EXECUTABLE}") endif() + + # Find the nslookup executable + find_program(NSLOOKUP_EXECUTABLE + NAMES nslookup + DOC "The nslookup tool that resolves DNS names") + + if (${NSLOOKUP_EXECUTABLE} STREQUAL "NSLOOKUP_EXECUTABLE-NOTFOUND") + message(FATAL_ERROR + "Could not find nslookup, which is needed for DNS resolution") + else() + message("-- Found nslookup: ${NSLOOKUP_EXECUTABLE}") + endif() endif() configure_file( diff --git a/src/ipcpd/shim-udp/main.c b/src/ipcpd/shim-udp/main.c index b45bee76..bb5c233f 100644 --- a/src/ipcpd/shim-udp/main.c +++ b/src/ipcpd/shim-udp/main.c @@ -400,16 +400,22 @@ int ipcp_udp_bootstrap(struct dif_config * conf) return -1; } - inet_ntop(AF_INET, - &conf->ip_addr, - ipstr, - INET_ADDRSTRLEN); + if (inet_ntop(AF_INET, + &conf->ip_addr, + ipstr, + INET_ADDRSTRLEN) == NULL) { + LOG_ERR("Failed to convert IP address"); + return -1; + } if (conf->dns_addr != 0) { - inet_ntop(AF_INET, - &conf->dns_addr, - dnsstr, - INET_ADDRSTRLEN); + if (inet_ntop(AF_INET, + &conf->dns_addr, + dnsstr, + INET_ADDRSTRLEN) == NULL) { + LOG_ERR("Failed to convert DNS address"); + return -1; + } #ifndef CONFIG_OUROBOROS_ENABLE_DNS LOG_WARN("DNS address ignored since shim-udp was " "compiled without DNS support."); @@ -478,6 +484,7 @@ int ipcp_udp_bootstrap(struct dif_config * conf) #ifdef CONFIG_OUROBOROS_ENABLE_DNS /* FIXME: Dependency on nsupdate to be removed in the end */ +/* NOTE: Disgusted with this crap */ static int ddns_send(char * cmd) { pid_t pid = 0; @@ -506,7 +513,7 @@ static int ddns_send(char * cmd) close(pipe_fd[0]); if (write(pipe_fd[1], cmd, strlen(cmd)) == -1) { - LOG_ERR("Failed to register with DNS server."); + LOG_ERR("Failed to communicate with nsupdate."); close(pipe_fd[1]); return -1; } @@ -521,6 +528,83 @@ static int ddns_send(char * cmd) close(pipe_fd[1]); return 0; } + + +static uint32_t ddns_resolve(char * name, uint32_t dns_addr) +{ + pid_t pid = 0; + int wstatus; + int pipe_fd[2]; + char dnsstr[INET_ADDRSTRLEN]; + char buf[SHIM_UDP_BUF_SIZE]; + ssize_t count = 0; + char * substr; + char * substr2; + char * addr_str = "Address:"; + uint32_t ip_addr = 0; + + if (inet_ntop(AF_INET, &dns_addr, dnsstr, INET_ADDRSTRLEN) == NULL) { + return 0; + } + + + if (pipe(pipe_fd)) { + LOG_ERR("Failed to create pipe."); + return 0; + } + + pid = fork(); + if (pid == -1) { + LOG_ERR("Failed to fork."); + return 0; + } + + if (pid == 0) { + char * argv[] = {NSLOOKUP_EXEC, name, dnsstr, 0}; + char * envp[] = {0}; + + close(pipe_fd[0]); + dup2(pipe_fd[1], 1); + execve(argv[0], &argv[0], envp); + } + + close(pipe_fd[1]); + + count = read(pipe_fd[0], buf, SHIM_UDP_BUF_SIZE); + if (count <= 0) { + LOG_ERR("Failed to communicate with nslookup."); + close(pipe_fd[0]); + return 0; + } + + close(pipe_fd[0]); + + waitpid(pid, &wstatus, 0); + if (WIFEXITED(wstatus) == true && + WEXITSTATUS(wstatus) == 0) + LOG_DBGF("Succesfully communicated with nslookup."); + else + LOG_ERR("Failed to resolve DNS address."); + + buf[count] = '\0'; + substr = strtok(buf, "\n"); + while (substr != NULL) { + substr2 = substr; + substr = strtok(NULL, "\n"); + } + + if (strstr(substr2, addr_str) == NULL) { + LOG_ERR("Failed to resolve DNS address."); + return 0; + } + + if (inet_pton(AF_INET, substr2 + strlen(addr_str) + 1, &ip_addr) != 1) { + LOG_ERR("Failed to resolve DNS address."); + return 0; + } + + return ip_addr; +} #endif int ipcp_udp_name_reg(char * name) @@ -556,8 +640,16 @@ int ipcp_udp_name_reg(char * name) if (dns_addr != 0) { ip_addr = shim_data(_ipcp)->ip_addr; - inet_ntop(AF_INET, &ip_addr, ipstr, INET_ADDRSTRLEN); - inet_ntop(AF_INET, &dns_addr, dnsstr, INET_ADDRSTRLEN); + if (inet_ntop(AF_INET, &ip_addr, + ipstr, INET_ADDRSTRLEN) == NULL) { + return -1; + } + + if (inet_ntop(AF_INET, &dns_addr, + dnsstr, INET_ADDRSTRLEN) == NULL) { + return -1; + } + sprintf(cmd, "server %s\nupdate add %s %d A %s\nsend\nquit\n", dnsstr, name, DNS_TTL, ipstr); @@ -592,7 +684,10 @@ int ipcp_udp_name_unreg(char * name) dns_addr = shim_data(_ipcp)->dns_addr; if (dns_addr != 0) { - inet_ntop(AF_INET, &dns_addr, dnsstr, INET_ADDRSTRLEN); + if (inet_ntop(AF_INET, &dns_addr, dnsstr, INET_ADDRSTRLEN) + == NULL) { + return -1; + } sprintf(cmd, "server %s\nupdate delete %s A\nsend\nquit\n", dnsstr, name); @@ -618,11 +713,13 @@ int ipcp_udp_flow_alloc(int port_id, struct sockaddr_in r_saddr; struct sockaddr_in rf_saddr; int fd; - int n; - - char * recv_buf = NULL; - - struct hostent * h; + int n; + char * recv_buf = NULL; + struct hostent * h; + uint32_t ip_addr = 0; +#ifdef CONFIG_OUROBOROS_ENABLE_DNS + uint32_t dns_addr = 0; +#endif if (dst_name == NULL || src_ap_name == NULL || src_ae_name == NULL) return -1; @@ -650,22 +747,41 @@ int ipcp_udp_flow_alloc(int port_id, return -1; } - h = gethostbyname(dst_name); - if (h == NULL) { - LOG_DBGF("Could not resolve %s.", dst_name); - close(fd); - return -1; +#ifdef CONFIG_OUROBOROS_ENABLE_DNS + dns_addr = shim_data(_ipcp)->dns_addr; + if (dns_addr != 0) { + ip_addr = ddns_resolve(dst_name, dns_addr); + if (ip_addr == 0) { + LOG_DBGF("Could not resolve %s.", dst_name); + close(fd); + return -1; + } + } else { +#endif + h = gethostbyname(dst_name); + if (h == NULL) { + LOG_DBGF("Could not resolve %s.", dst_name); + close(fd); + return -1; + } + + ip_addr = *((uint32_t *) (h->h_addr_list[0])); +#ifdef CONFIG_OUROBOROS_ENABLE_DNS } +#endif memset((char *) &r_saddr, 0, sizeof r_saddr); r_saddr.sin_family = AF_INET; - r_saddr.sin_addr.s_addr = *((uint32_t *) (h->h_addr_list[0])); + r_saddr.sin_addr.s_addr = ip_addr; r_saddr.sin_port = LISTEN_PORT; /* at least try to get the packet on the wire */ - while (sendto(fd, dst_name, strlen(dst_name), 0, + if (sendto(fd, dst_name, strlen(dst_name), 0, (struct sockaddr *) &r_saddr, sizeof r_saddr) < 0) { + LOG_ERR("Failed to send packet"); + close(fd); + return -1; } /* wait for the other shim IPCP to respond */ @@ -683,11 +799,12 @@ int ipcp_udp_flow_alloc(int port_id, (struct sockaddr *) &rf_saddr, sizeof rf_saddr) < 0) { + close(fd); free(recv_buf); return -1; } - if (!strcmp(recv_buf, dst_name)) + if (strcmp(recv_buf, dst_name)) LOG_WARN("Incorrect echo from server"); free(recv_buf); @@ -698,6 +815,7 @@ int ipcp_udp_flow_alloc(int port_id, if (_ap_instance->flows[fd].rb == NULL) { LOG_ERR("Could not open N + 1 ringbuffer."); close(fd); + return -1; } /* tell IRMd that flow allocation "worked" */ diff --git a/src/ipcpd/shim-udp/shim_udp_config.h.in b/src/ipcpd/shim-udp/shim_udp_config.h.in index 00b0b910..71d269d8 100644 --- a/src/ipcpd/shim-udp/shim_udp_config.h.in +++ b/src/ipcpd/shim-udp/shim_udp_config.h.in @@ -24,5 +24,6 @@ #define OUROBOROS_SHIM_UDP_CONFIG #define NSUPDATE_EXEC "@NSUPDATE_EXECUTABLE@" +#define NSLOOKUP_EXEC "@NSLOOKUP_EXECUTABLE@" #endif -- cgit v1.2.3