summaryrefslogtreecommitdiff
path: root/src/core/capsicum.c
diff options
context:
space:
mode:
authorEdward Tomasz Napierala <trasz@FreeBSD.org>2017-07-28 02:21:40 +0100
committerEdward Tomasz Napierala <trasz@FreeBSD.org>2017-07-29 23:52:23 +0100
commit509eca76f0755e94b5981f464f9f9a882499180a (patch)
tree38dc11be859998a3d7850c4fb289d67721a9a2ea /src/core/capsicum.c
parentf4546be7ecb8a0801fb0d30415586c15d721494a (diff)
downloadirssi-509eca76f0755e94b5981f464f9f9a882499180a.zip
Make DNS work in capability mode.
Signed-off-by: Edward Tomasz Napierala <trasz@FreeBSD.org>
Diffstat (limited to 'src/core/capsicum.c')
-rw-r--r--src/core/capsicum.c173
1 files changed, 136 insertions, 37 deletions
diff --git a/src/core/capsicum.c b/src/core/capsicum.c
index a0375077..99f7ff0f 100644
--- a/src/core/capsicum.c
+++ b/src/core/capsicum.c
@@ -31,6 +31,9 @@
#include <sys/socket.h>
#include <string.h>
+#define OPCODE_CONNECT 1
+#define OPCODE_GETHOSTBYNAME 2
+
static int symbiontfds[2];
gboolean capsicum_enabled(void)
@@ -55,6 +58,7 @@ int capsicum_net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip)
/* Send request to the symbiont. */
nvl = nvlist_create(0);
+ nvlist_add_number(nvl, "opcode", OPCODE_CONNECT);
nvlist_add_binary(nvl, "ip", ip, sizeof(*ip));
nvlist_add_number(nvl, "port", port);
if (my_ip != NULL) {
@@ -86,12 +90,139 @@ int capsicum_net_connect_ip(IPADDR *ip, int port, IPADDR *my_ip)
return sock;
}
-static int start_symbiont(void)
+int capsicum_net_gethostbyname(const char *addr, IPADDR *ip4, IPADDR *ip6)
{
- pid_t pid;
nvlist_t *nvl;
+ IPADDR *received_ip4, *received_ip6;
+ int error, ret, saved_errno;
+
+ /* Send request to the symbiont. */
+ nvl = nvlist_create(0);
+ nvlist_add_number(nvl, "opcode", OPCODE_GETHOSTBYNAME);
+ nvlist_add_string(nvl, "addr", addr);
+ error = nvlist_send(symbiontfds[1], nvl);
+ nvlist_destroy(nvl);
+ if (error != 0) {
+ g_warning("nvlist_send: %s", strerror(errno));
+ return -1;
+ }
+
+ /* Receive response. */
+ nvl = nvlist_recv(symbiontfds[1], 0);
+ if (nvl == NULL) {
+ g_warning("nvlist_recv: %s", strerror(errno));
+ return -1;
+ }
+
+ received_ip4 = nvlist_get_binary(nvl, "ip4", NULL);
+ received_ip6 = nvlist_get_binary(nvl, "ip6", NULL);
+ memcpy(ip4, received_ip4, sizeof(*ip4));
+ memcpy(ip6, received_ip6, sizeof(*ip6));
+
+ ret = nvlist_get_number(nvl, "ret");
+ saved_errno = nvlist_get_number(nvl, "errno");
+ nvlist_destroy(nvl);
+ errno = saved_errno;
+
+ return ret;
+}
+
+nvlist_t *symbiont_connect(const nvlist_t *request)
+{
+ nvlist_t *response;
IPADDR *ip, *my_ip;
- int childfd, error, port, saved_errno, sock;
+ int port, saved_errno, sock;
+
+ ip = nvlist_get_binary(request, "ip", NULL);
+ port = (int)nvlist_get_number(request, "port");
+ if (nvlist_exists(request, "my_ip"))
+ my_ip = nvlist_get_binary(request, "my_ip", NULL);
+ else
+ my_ip = NULL;
+
+ /* Connect. */
+ sock = net_connect_ip_handle(ip, port, my_ip);
+ saved_errno = errno;
+
+ /* Send back the socket fd. */
+ response = nvlist_create(0);
+
+ if (sock != -1)
+ nvlist_move_descriptor(response, "sock", sock);
+ nvlist_add_number(response, "errno", saved_errno);
+
+ return (response);
+}
+
+nvlist_t *symbiont_gethostbyname(const nvlist_t *request)
+{
+ nvlist_t *response;
+ IPADDR ip4, ip6;
+ const char *addr;
+ int ret, saved_errno;
+
+ addr = nvlist_get_string(request, "addr");
+
+ /* Connect. */
+ ret = net_gethostbyname(addr, &ip4, &ip6);
+ saved_errno = errno;
+
+ /* Send back the IPs. */
+ response = nvlist_create(0);
+
+ nvlist_add_number(response, "ret", ret);
+ nvlist_add_number(response, "errno", saved_errno);
+ nvlist_add_binary(response, "ip4", &ip4, sizeof(ip4));
+ nvlist_add_binary(response, "ip6", &ip6, sizeof(ip6));
+
+ return (response);
+}
+
+/*
+ * Child process, running outside the Capsicum sandbox.
+ */
+_Noreturn static void symbiont(void)
+{
+ nvlist_t *request, *response;
+ int error, opcode;
+
+ setproctitle("capsicum symbiont");
+ close(symbiontfds[1]);
+ close(0);
+ close(1);
+ close(2);
+
+ for (;;) {
+ /* Receive parameters from the main irssi process. */
+ request = nvlist_recv(symbiontfds[0], 0);
+ if (request == NULL)
+ exit(1);
+
+ opcode = nvlist_get_number(request, "opcode");
+ switch (opcode) {
+ case OPCODE_CONNECT:
+ response = symbiont_connect(request);
+ break;
+ case OPCODE_GETHOSTBYNAME:
+ response = symbiont_gethostbyname(request);
+ break;
+ default:
+ exit(1);
+ }
+
+ /* Send back the response. */
+ error = nvlist_send(symbiontfds[0], response);
+ if (error != 0)
+ exit(1);
+ nvlist_destroy(request);
+ nvlist_destroy(response);
+ }
+}
+
+static int start_symbiont(void)
+{
+ int childfd, error;
+ pid_t pid;
error = socketpair(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, symbiontfds);
if (error != 0) {
@@ -110,40 +241,8 @@ static int start_symbiont(void)
return 0;
}
- /* We're the child, running outside the Capsicum sandbox. */
- setproctitle("capsicum symbiont");
- close(symbiontfds[1]);
- close(0);
- close(1);
- close(2);
- for (;;) {
- /* Receive parameters from the main irssi process. */
- nvl = nvlist_recv(symbiontfds[0], 0);
- if (nvl == NULL)
- exit(1);
- ip = nvlist_get_binary(nvl, "ip", NULL);
- port = (int)nvlist_get_number(nvl, "port");
- if (nvlist_exists(nvl, "my_ip"))
- my_ip = nvlist_get_binary(nvl, "my_ip", NULL);
- else
- my_ip = NULL;
-
- /* Connect. */
- sock = net_connect_ip_handle(ip, port, my_ip);
- saved_errno = errno;
-
- /* Send back the socket fd. */
- nvlist_destroy(nvl);
- nvl = nvlist_create(0);
-
- if (sock != -1)
- nvlist_move_descriptor(nvl, "sock", sock);
- nvlist_add_number(nvl, "errno", saved_errno);
- error = nvlist_send(symbiontfds[0], nvl);
- if (error != 0)
- exit(1);
- nvlist_destroy(nvl);
- }
+ symbiont();
+ /* NOTREACHED */
}
static void cmd_capsicum(const char *data, SERVER_REC *server, void *item)