From ec5025bff45bf0f84317c31555fdf95a9a29ce17 Mon Sep 17 00:00:00 2001 From: Peter Pentchev Date: Fri, 31 Jul 2015 15:37:40 +0000 Subject: [PATCH] Try to teach AICCU about ng_ayiya. TODO: Make it stop, i.e. get ng_ayiya to send a message down the control hook upon receiving a "shutdown" message and get AICCU to hear that message and, well, stop. --- common/aiccu.h | 1 + common/aiccu_freebsd4.c | 8 ++ common/aiccu_kame.c | 25 +++++++ common/aiccu_netgraph.h | 20 +++++ common/ayiya.c | 19 ++++- common/common.c | 60 ++++++++++++--- common/common.h | 2 +- common/tic.c | 2 +- common/tun.c | 190 ++++++++++++++++++++++++++++++++++++++++++++++++ unix-console/Makefile | 5 ++ unix-console/main.c | 5 ++ 11 files changed, 323 insertions(+), 14 deletions(-) create mode 100644 common/aiccu_netgraph.h diff --git common/aiccu.h common/aiccu.h index ef65000..1c0c1f2 100755 --- common/aiccu.h +++ common/aiccu.h @@ -19,6 +19,7 @@ #include "heartbeat.h" #include "ayiya.h" #include "resolver.h" +#include "aiccu_netgraph.h" #ifdef NEWSTUFF_TSP #include "tsp.h" diff --git common/aiccu_freebsd4.c common/aiccu_freebsd4.c index 95a6554..c2e1cc2 100755 --- common/aiccu_freebsd4.c +++ common/aiccu_freebsd4.c @@ -19,6 +19,9 @@ bool aiccu_os_install(void) bool aiccu_os_setup(struct TIC_Tunnel *hTunnel) { +#ifdef AICCU_NETGRAPH + do_log(LOG_ERR, "RDBG aiccu_os_setup(): configure the Netgraph node\n"); exit(42); +#else if (hTunnel->uses_tundev == 0) { /* Create the tunnel device */ @@ -76,6 +79,7 @@ bool aiccu_os_setup(struct TIC_Tunnel *hTunnel) } return true; +#endif /* AICCU_NETGRAPH */ } void aiccu_os_reconfig(struct TIC_Tunnel *hTunnel) @@ -93,6 +97,9 @@ void aiccu_os_reconfig(struct TIC_Tunnel *hTunnel) void aiccu_os_delete(struct TIC_Tunnel *hTunnel) { +#ifdef AICCU_NETGRAPH + dolog(LOG_ERR, "RDBG FIXME: tear down the Netgraph structure\n"); exit(42); +#else hTunnel = hTunnel; /* Mark the interface down */ @@ -107,5 +114,6 @@ void aiccu_os_delete(struct TIC_Tunnel *hTunnel) "ifconfig %s destroy", g_aiccu->ipv6_interface); } +#endif /* AICCU_NETGRAPH */ } diff --git common/aiccu_kame.c common/aiccu_kame.c index c6d1ea3..9d79282 100755 --- common/aiccu_kame.c +++ common/aiccu_kame.c @@ -65,6 +65,24 @@ bool aiccu_os_setup(struct TIC_Tunnel *hTunnel) hTunnel->sIPv6_POP); } +#ifdef AICCU_NETGRAPH + if (NgSendMsg(ng_sock.cs, "c", NGM_AYIYA_COOKIE, NGM_AYIYA_CONFIGURE, + NULL, 0) == -1) + { + dolog(LOG_ERR, "Could not send the 'configure' message to the '%s' Netgraph node: %s (%d)\n", + ng_node_name, strerror(errno), errno); + return false; + } + int32_t resp; + if (!ng_get_msg_response("configure", &resp, sizeof(resp))) + return false; + if (resp != 0) { + dolog(LOG_ERR, "Could not complete the '%s' Netgraph's node configuration: %s (%d)\n", + ng_node_name, strerror(resp), resp); + return false; + } +#endif + return true; } @@ -82,6 +100,7 @@ void aiccu_os_reconfig(struct TIC_Tunnel *hTunnel) void aiccu_os_delete(struct TIC_Tunnel *hTunnel) { +#ifndef AICCU_NETGRAPH hTunnel = hTunnel; aiccu_exec( "ifconfig %s down", @@ -93,5 +112,11 @@ void aiccu_os_delete(struct TIC_Tunnel *hTunnel) "ifconfig %s deletetunnel", g_aiccu->ipv6_interface); } +#else + (void)hTunnel; + if (!tun_ng_connect("stop", true)) + return; + tun_ng_shutdown("stop", true); +#endif } diff --git common/aiccu_netgraph.h common/aiccu_netgraph.h new file mode 100644 index 0000000..3e2291e --- /dev/null +++ common/aiccu_netgraph.h @@ -0,0 +1,20 @@ +#ifndef AICCU_NETGRAPH_H +#define AICCU_NETGRAPH_H + +#include +#include + +#include + +struct ng_connection_sock { + int cs, ds; +}; + +extern struct ng_connection_sock ng_sock; +extern char ng_node_name[NG_NODESIZ]; +extern bool ng_connected; + +bool tun_ng_connect(const char *what, bool disconnect); +bool tun_ng_shutdown(const char *what, bool self); +bool ng_get_msg_response(const char *what, void *buf, size_t size); +#endif diff --git common/ayiya.c common/ayiya.c index f4ed0aa..4068d3e 100755 --- common/ayiya.c +++ common/ayiya.c @@ -155,6 +155,9 @@ DWORD WINAPI ayiya_writer(LPVOID arg); DWORD WINAPI ayiya_writer(LPVOID arg) #endif { +#ifdef AICCU_NETGRAPH + /* Do nothing, really. Everything is handled by the Netgraph node. */ +#else unsigned char buf[2048]; struct pseudo_ayh *s = (struct pseudo_ayh *)buf; struct sockaddr_storage ci; @@ -272,11 +275,15 @@ DWORD WINAPI ayiya_writer(LPVOID arg) #else return 0; #endif +#endif /* AICCU_NETGRAPH */ } /* Construct a beat and send it outwards */ void ayiya_beat(void) { +#ifdef AICCU_NETGRAPH + dolog(LOG_ERR, "RDBG FIXME: send a Netgraph heartbeat\n"); +#else SHA_CTX sha1; sha1_byte hash[SHA1_DIGEST_LENGTH]; struct sockaddr_in target; @@ -340,6 +347,7 @@ void ayiya_beat(void) { ayiya_log(LOG_ERR, beat_name, NULL, 0, "Only %u of %u bytes sent to network: %s (%d)\n", lenout, n, strerror(errno), errno); } +#endif /* AICCU_NETGRAPH */ } bool ayiya(struct TIC_Tunnel *hTunnel) @@ -444,9 +452,18 @@ bool ayiya(struct TIC_Tunnel *hTunnel) SHA1_Init(&sha1); SHA1_Update(&sha1, (const sha1_byte *)hTunnel->sPassword, (unsigned int)strlen(hTunnel->sPassword)); SHA1_Final(ayiya_hash, &sha1); +#ifdef AICCU_NETGRAPH + if (NgSendMsg(ng_sock.cs, "c", NGM_AYIYA_COOKIE, NGM_AYIYA_SECRETHASH, + ayiya_hash, sizeof(ayiya_hash)) == -1) + { + dolog(LOG_ERR, "Could not send the secret hash to the Netgraph node: %s (%d)\n", + strerror(errno), errno); + return false; + } +#endif /* Setup listening socket */ - ayiya_socket = connect_client(hTunnel->sIPv4_POP , AYIYA_PORT, AF_INET, SOCK_DGRAM); + ayiya_socket = connect_client(hTunnel->sIPv4_POP , AYIYA_PORT, AF_INET, SOCK_DGRAM, true); if (!ayiya_socket) { ayiya_log(LOG_ERR, "start", NULL, 0, "Connection error:: could not create connection to AYIYA server\n"); diff --git common/common.c common/common.c index 488c145..d3216b8 100755 --- common/common.c +++ common/common.c @@ -340,13 +340,20 @@ void sock_free(TLSSOCKET sock) } /* Connect this client to a server */ -TLSSOCKET connect_client(const char *hostname, const char *service, int family, int socktype) +TLSSOCKET connect_client(const char *hostname, const char *service, int family, int socktype, bool ng_ayiya) { - TLSSOCKET sock; struct addrinfo hints, *res, *ressave; + TLSSOCKET sock; - sock = sock_alloc(); - if (!sock) return NULL; +#ifndef AICCU_NETGRAPH + ng_ayiya = false; +#endif + + if (!ng_ayiya) + { + sock = sock_alloc(); + if (!sock) return NULL; + } memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = family; @@ -355,28 +362,59 @@ TLSSOCKET connect_client(const char *hostname, const char *service, int family, if (getaddrinfo(hostname, service, &hints, &res) != 0) { dolog(LOG_ERR, "Couldn't resolve host %s, service %s\n", hostname, service); - sock_free(sock); + if (!ng_ayiya) + sock_free(sock); return NULL; } ressave = res; + int s = -1; while (res) { - sock->socket = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - if (sock->socket == -1) continue; - if (connect(sock->socket, res->ai_addr, (unsigned int)res->ai_addrlen) == 0) break; - closesocket(sock->socket); - sock->socket = -1; + if (!ng_ayiya) + { + s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + } else { + struct ngm_mkpeer m = { + .type = "ksocket", + .ourhook = "ayiya", + }; + snprintf(m.peerhook, sizeof(m.peerhook), "%d/%d/%d", + res->ai_family, res->ai_socktype, res->ai_protocol); + s = NgSendMsg(ng_sock.cs, "c", NGM_GENERIC_COOKIE, NGM_MKPEER, + &m, sizeof(m)); + } + if (s == -1) continue; + + int r; + if (!ng_ayiya) + r = connect(s, res->ai_addr, (unsigned int)res->ai_addrlen); + else + r = NgSendMsg(ng_sock.cs, "c.ayiya", NGM_KSOCKET_COOKIE, + NGM_KSOCKET_CONNECT, res->ai_addr, res->ai_addrlen) == -1; + if (r == 0) break; + if (!ng_ayiya) + closesocket(s); + else if (NgSendMsg(ng_sock.cs, "c.ayiya", NGM_GENERIC_COOKIE, + NGM_SHUTDOWN, NULL, 0) == -1) + dolog(LOG_ERR, "Could not shut down the ksocket node: %s (%d)\n", + ng_node_name, strerror(errno), errno); + s = -1; res = res->ai_next; } freeaddrinfo(ressave); - if (sock->socket == -1) + if (ng_ayiya) + return (TLSSOCKET)(s != -1); + + if (s == -1) { sock_free(sock); sock = NULL; + } else { + sock->socket = s; } return sock; diff --git common/common.h common/common.h index 575d854..6982331 100755 --- common/common.h +++ common/common.h @@ -398,7 +398,7 @@ void vsyslog(int priority, const char *format, va_list ap); /* Networking functions */ void sock_printf(TLSSOCKET sock, const char *fmt, ...); int sock_getline(TLSSOCKET sock, char *rbuf, unsigned int rbuflen, unsigned int *filled, char *ubuf, unsigned int ubuflen); -TLSSOCKET connect_client(const char *hostname, const char *service, int family, int socktype); +TLSSOCKET connect_client(const char *hostname, const char *service, int family, int socktype, bool ng_ayiya); TLSSOCKET listen_server(const char *description, const char *hostname, const char *service, int family, int socktype); void sock_free(TLSSOCKET sock); #ifdef AICCU_GNUTLS diff --git common/tic.c common/tic.c index e0d70fe..8292a0a 100755 --- common/tic.c +++ common/tic.c @@ -76,7 +76,7 @@ bool tic_Login(struct TIC_conf *tic, const char *username, const char *password, D(dolog(LOG_DEBUG, "Trying to connect to TIC server %s\n", server)); /* Connect to the TIC server */ - tic->sock = connect_client(server, TIC_PORT, AF_INET, SOCK_STREAM); + tic->sock = connect_client(server, TIC_PORT, AF_INET, SOCK_STREAM, false); if (!tic->sock) { dolog(LOG_ERR, "Couldn't connect to the TIC server %s\n", server); diff --git common/tun.c common/tun.c index c5b6323..b4fa558 100755 --- common/tun.c +++ common/tun.c @@ -48,6 +48,11 @@ struct ether_header #endif +#ifdef AICCU_NETGRAPH +struct ng_connection_sock ng_sock = { .cs = -1, .ds = -1 }; +char ng_node_name[NG_NODESIZ]; +#endif + void tun_log(int level, const char *what, const char *fmt, ...); void tun_log(int level, const char *what, const char *fmt, ...) { @@ -68,8 +73,10 @@ void tun_log(int level, const char *what, const char *fmt, ...) dolog(level, buf); } +#ifndef AICCU_NETGRAPH static const char reader_name[] = "tundev->tun"; static const char writer_name[] = "tun->tundev"; +#endif #ifdef _WIN32 /* Windows doesn't have writev() but does have WSASend */ @@ -148,6 +155,10 @@ DWORD WINAPI tun_reader(LPVOID arg); DWORD WINAPI tun_reader(LPVOID arg) #endif { +#ifdef AICCU_NETGRAPH + /* Nothing to do; the Netgraph node handles everything. */ + (void)arg; +#else unsigned char buf[2048]; /* The function that actually does something with the buffer */ @@ -269,6 +280,7 @@ DWORD WINAPI tun_reader(LPVOID arg) tun->function((char *)&buf[sizeof(struct ether)], (unsigned int)lenin - sizeof(struct ether)); #endif } +#endif /* AICCU_NETGRAPH */ D(dolog(LOG_DEBUG, "TUN Reader stopping\n")); #ifndef _WIN32 @@ -278,6 +290,7 @@ DWORD WINAPI tun_reader(LPVOID arg) #endif } +#ifndef AICCU_NETGRAPH /* Socket -> Tun */ void tun_write(char *buf, unsigned int length) { @@ -357,6 +370,7 @@ void tun_write(char *buf, unsigned int length) } #endif } +#endif #ifdef _WIN32 @@ -687,6 +701,105 @@ bool tun_fixup_adapters(void) #endif +#ifdef AICCU_NETGRAPH +static void +tun_ng_disconnect(void) +{ + close(ng_sock.ds); + ng_sock.ds = -1; + close(ng_sock.cs); + ng_sock.cs = -1; +} + +bool +tun_ng_connect(const char *what, bool disconnect) +{ + if (ng_sock.cs != -1 || ng_sock.ds != -1) + { + if (disconnect) + { + tun_ng_disconnect(); + } else { + tun_log(LOG_ERR, what, "The Netgraph socket seems to be already initialized\n"); + return false; + } + } + if (ng_node_name[0] == '\0') + { + tun_log(LOG_ERR, what, "Internal error: the Netgraph node name has not been initialized\n"); + return false; + } + + char name[NG_NODESIZ]; + snprintf(name, sizeof(name), "%s_%s_%ld", + ng_node_name, what, (long)getpid()); + if (NgMkSockNode(name, &ng_sock.cs, &ng_sock.ds) == -1) + { + tun_log(LOG_ERR, what, "Could not create the Netgraph socket node: %s (%d)\n", + strerror(errno), errno); + return false; + } + return true; +} + +static bool +tun_ng_shutdown_node(const char *what, const char *hook) +{ + char path[NG_PATHSIZ]; + + snprintf(path, sizeof(path), "%s:%s", ng_node_name, hook); + if (NgSendMsg(ng_sock.cs, path, NGM_GENERIC_COOKIE, NGM_SHUTDOWN, + NULL, 0) == -1 && errno != ENOENT) + { + tun_log(LOG_ERR, what, "Could not shut down the %s Netgraph node: %s (%d)\n", + path, strerror(errno), errno); + return false; + } + return true; +} + +bool +tun_ng_shutdown(const char *what, bool self) +{ + if (!tun_ng_shutdown_node(what, "ayiya") || + !tun_ng_shutdown_node(what, "inet6") || + self && !tun_ng_shutdown_node(what, "")) + return false; + + if (self) + tun_ng_disconnect(); + return true; +} + +bool +ng_get_msg_response(const char *what, void *buf, size_t size) +{ + static char ng_path[NG_PATHSIZ]; + static struct { + struct ng_mesg msg; + char data[8192]; + } __attribute__((packed)) ng_buf; + + int len = NgRecvMsg(ng_sock.cs, &ng_buf.msg, sizeof(ng_buf), ng_path); + size_t expected = sizeof(ng_buf.msg) + size; + if (len < 0) + { + dolog(LOG_ERR, "Could not get the %s Netgraph response: %s (%d)\n", + what, strerror(errno), errno); + return false; + } + else if ((size_t)len < expected) + { + dolog(LOG_ERR, "Received a short %s Netgraph response (%d out of %u bytes)\n", + what, len, errno); + return false; + } + len -= sizeof(ng_buf.msg); + memcpy(buf, ng_buf.data, size); + return true; +} +#endif + bool tun_start(struct tun_reader *tun) { #ifndef _WIN32 @@ -716,6 +829,82 @@ bool tun_start(struct tun_reader *tun) } #else /* *BSD/Darwin */ +#ifdef AICCU_NETGRAPH + if (!tun_ng_connect("start", false)) + return false; + + struct ngm_connect c = { + .ourhook = "c", + .peerhook = "control", + }; + snprintf(c.path, sizeof(c.path), "%s:", ng_node_name); + if (NgSendMsg(ng_sock.cs, ".", NGM_GENERIC_COOKIE, NGM_CONNECT, + &c, sizeof(c)) == -1) { + if (errno == ENOENT) { + tun_log(LOG_DEBUG, "start", "About to create the '%s' Netgraph node\n", + ng_node_name); + struct ngm_mkpeer m = { + .type = "ayiya", + .ourhook = "c", + .peerhook = "control", + }; + if (NgSendMsg(ng_sock.cs, ".", NGM_GENERIC_COOKIE, + NGM_MKPEER, &m, sizeof(m)) == -1) + { + tun_log(LOG_ERR, "start", "Could not create a '%s' Netgraph node: %s (%s)\n", + m.type, strerror(errno), errno); + return false; + } + + if (NgNameNode(ng_sock.cs, "c", "%s", ng_node_name) == -1) + { + tun_log(LOG_ERR, "start", "Could not set the Netgraph node's name to '%s': %s (%d)\n", + ng_node_name, strerror(errno), errno); + return false; + } + } else if (errno == EEXIST) { + tun_log(LOG_ERR, "start", "Something is already connected to the '%s' Netgraph node's '%s' hook\n", + ng_node_name, c.peerhook); + return false; + } else { + tun_log(LOG_ERR, "start", "Could not connect to the '%s' hook of the '%s' Netgraph node: %s (%d)\n", + c.peerhook, ng_node_name, strerror(errno), errno); + return false; + } + } else { + tun_log(LOG_DEBUG, "start", "Connected to the %s Netgraph node\n", + ng_node_name); + } + + if (!tun_ng_shutdown("start", false)) + return false; + + struct ngm_mkpeer m = { + .type = "iface", + .ourhook = "inet6", + .peerhook = "inet6", + }; + if (NgSendMsg(ng_sock.cs, "c", NGM_GENERIC_COOKIE, NGM_MKPEER, + &m, sizeof(m)) == -1) + { + tun_log(LOG_ERR, "start", "Could not create a '%s' Netgraph node: %s (%s)\n", + m.type, strerror(errno), errno); + return false; + } + if (NgSendMsg(ng_sock.cs, "c.inet6", NGM_GENERIC_COOKIE, NGM_NODEINFO, + NULL, 0) == -1) + { + tun_log(LOG_ERR, "start", "Could not query the '%s' Netgraph node's name: %s (%d)\n", + m.type, strerror(errno), errno); + return false; + } + struct nodeinfo inf; + if (!ng_get_msg_response("nodeinfo", &inf, sizeof(inf))) + return false; + tun_log(LOG_DEBUG, "start", "Got Netgraph interface node info: name '%s' type '%s' id '%lld' hooks %u\n", inf.name, inf.type, (long long)inf.id, inf.hooks); + if (g_aiccu->ipv6_interface) free(g_aiccu->ipv6_interface); + g_aiccu->ipv6_interface = strdup(inf.name); +#else char buf[128]; unsigned int i; @@ -781,6 +970,7 @@ bool tun_start(struct tun_reader *tun) } #endif +#endif /* AICCU_NETGRAPH */ #endif /* linux */ diff --git unix-console/Makefile unix-console/Makefile index d5e5c07..a661111 100755 --- unix-console/Makefile +++ unix-console/Makefile @@ -34,6 +34,11 @@ ifeq ($(shell echo $(CFLAGS) | grep -c "\-O"),0) CFLAGS += -O3 endif +# Link with the Netgraph library if needed +ifneq ($(shell echo $(CFLAGS) | grep -c "\-DAICCU_NETGRAPH"),0) +LDFLAGS += -lnetgraph +endif + # This is a console client CFLAGS += -D AICCU_CONSOLE diff --git unix-console/main.c unix-console/main.c index 8a4d9a9..527868f 100755 --- unix-console/main.c +++ unix-console/main.c @@ -348,6 +348,11 @@ int main(int argc, char *argv[]) tic_Logout(g_aiccu->tic, NULL); g_aiccu->tic = NULL; +#ifdef AICCU_NETGRAPH + snprintf(ng_node_name, sizeof(ng_node_name), "aiccu_%s", hTunnel->sId); + dolog(LOG_DEBUG, "Using Netgraph node name %s\n", ng_node_name); +#endif + if (g_aiccu->verbose) { printf("Tunnel Information for %s:\n",hTunnel->sId); -- 2.4.6