1a664ade9SLutz Donnerhacke /*-
224ea1dbfSLutz Donnerhacke * SPDX-License-Identifier: BSD-3-Clause
324ea1dbfSLutz Donnerhacke *
424ea1dbfSLutz Donnerhacke * Copyright 2021 Lutz Donnerhacke
524ea1dbfSLutz Donnerhacke *
624ea1dbfSLutz Donnerhacke * Redistribution and use in source and binary forms, with or without
724ea1dbfSLutz Donnerhacke * modification, are permitted provided that the following conditions
824ea1dbfSLutz Donnerhacke * are met:
924ea1dbfSLutz Donnerhacke *
1024ea1dbfSLutz Donnerhacke * 1. Redistributions of source code must retain the above copyright
1124ea1dbfSLutz Donnerhacke * notice, this list of conditions and the following disclaimer.
1224ea1dbfSLutz Donnerhacke * 2. Redistributions in binary form must reproduce the above
1324ea1dbfSLutz Donnerhacke * copyright notice, this list of conditions and the following
1424ea1dbfSLutz Donnerhacke * disclaimer in the documentation and/or other materials provided
1524ea1dbfSLutz Donnerhacke * with the distribution.
1624ea1dbfSLutz Donnerhacke * 3. Neither the name of the copyright holder nor the names of its
1724ea1dbfSLutz Donnerhacke * contributors may be used to endorse or promote products derived
1824ea1dbfSLutz Donnerhacke * from this software without specific prior written permission.
1924ea1dbfSLutz Donnerhacke *
2024ea1dbfSLutz Donnerhacke * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
2124ea1dbfSLutz Donnerhacke * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
2224ea1dbfSLutz Donnerhacke * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
2324ea1dbfSLutz Donnerhacke * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2424ea1dbfSLutz Donnerhacke * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
2524ea1dbfSLutz Donnerhacke * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
2624ea1dbfSLutz Donnerhacke * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
2724ea1dbfSLutz Donnerhacke * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2824ea1dbfSLutz Donnerhacke * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
2924ea1dbfSLutz Donnerhacke * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
3024ea1dbfSLutz Donnerhacke * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
3124ea1dbfSLutz Donnerhacke * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3224ea1dbfSLutz Donnerhacke * SUCH DAMAGE.
3324ea1dbfSLutz Donnerhacke */
3424ea1dbfSLutz Donnerhacke #include <atf-c.h>
3524ea1dbfSLutz Donnerhacke #include <errno.h>
3624ea1dbfSLutz Donnerhacke #include <stdlib.h>
3724ea1dbfSLutz Donnerhacke #include <string.h>
3824ea1dbfSLutz Donnerhacke
3924ea1dbfSLutz Donnerhacke #include <sys/select.h>
4024ea1dbfSLutz Donnerhacke #include <sys/queue.h>
4124ea1dbfSLutz Donnerhacke
4224ea1dbfSLutz Donnerhacke #include "util.h"
4324ea1dbfSLutz Donnerhacke
4424ea1dbfSLutz Donnerhacke
4524ea1dbfSLutz Donnerhacke static int cs = -1, ds = -1;
4624ea1dbfSLutz Donnerhacke static ng_error_t error_handling = FAIL;
4724ea1dbfSLutz Donnerhacke
4824ea1dbfSLutz Donnerhacke #define CHECK(r, x) do { \
499021c466SLutz Donnerhacke if (!(x)) { \
509021c466SLutz Donnerhacke if (error_handling == PASS) \
5124ea1dbfSLutz Donnerhacke return r; \
529021c466SLutz Donnerhacke atf_tc_fail_requirement(file, line, "%s (%s)", \
539021c466SLutz Donnerhacke #x " not met", strerror(errno));\
549021c466SLutz Donnerhacke } \
5524ea1dbfSLutz Donnerhacke } while(0)
5624ea1dbfSLutz Donnerhacke
57a664ade9SLutz Donnerhacke struct data_handler
58a664ade9SLutz Donnerhacke {
5924ea1dbfSLutz Donnerhacke char const *hook;
6024ea1dbfSLutz Donnerhacke ng_data_handler_t handler;
6124ea1dbfSLutz Donnerhacke SLIST_ENTRY(data_handler) next;
6224ea1dbfSLutz Donnerhacke };
6324ea1dbfSLutz Donnerhacke static SLIST_HEAD(, data_handler) data_head = SLIST_HEAD_INITIALIZER(data_head);
6409307dbfSLutz Donnerhacke static ng_msg_handler_t msg_handler = NULL;
6524ea1dbfSLutz Donnerhacke
6624ea1dbfSLutz Donnerhacke static void handle_data(void *ctx);
6709307dbfSLutz Donnerhacke static void handle_msg(void *ctx);
6824ea1dbfSLutz Donnerhacke
6924ea1dbfSLutz Donnerhacke void
_ng_connect(char const * path1,char const * hook1,char const * path2,char const * hook2,char const * file,size_t line)709021c466SLutz Donnerhacke _ng_connect(char const *path1, char const *hook1,
719021c466SLutz Donnerhacke char const *path2, char const *hook2,
729021c466SLutz Donnerhacke char const *file, size_t line)
7324ea1dbfSLutz Donnerhacke {
7424ea1dbfSLutz Donnerhacke struct ngm_connect c;
7524ea1dbfSLutz Donnerhacke
7624ea1dbfSLutz Donnerhacke strncpy(c.ourhook, hook1, sizeof(c.ourhook));
7724ea1dbfSLutz Donnerhacke strncpy(c.peerhook, hook2, sizeof(c.peerhook));
7824ea1dbfSLutz Donnerhacke strncpy(c.path, path2, sizeof(c.path));
7924ea1dbfSLutz Donnerhacke
8024ea1dbfSLutz Donnerhacke CHECK(, -1 != NgSendMsg(cs, path1,
8124ea1dbfSLutz Donnerhacke NGM_GENERIC_COOKIE, NGM_CONNECT,
8224ea1dbfSLutz Donnerhacke &c, sizeof(c)));
8324ea1dbfSLutz Donnerhacke }
8424ea1dbfSLutz Donnerhacke
8524ea1dbfSLutz Donnerhacke void
_ng_mkpeer(char const * path1,char const * hook1,char const * type,char const * hook2,char const * file,size_t line)869021c466SLutz Donnerhacke _ng_mkpeer(char const *path1, char const *hook1,
879021c466SLutz Donnerhacke char const *type, char const *hook2,
889021c466SLutz Donnerhacke char const *file, size_t line)
8924ea1dbfSLutz Donnerhacke {
9024ea1dbfSLutz Donnerhacke struct ngm_mkpeer p;
9124ea1dbfSLutz Donnerhacke
9224ea1dbfSLutz Donnerhacke strncpy(p.ourhook, hook1, sizeof(p.ourhook));
9324ea1dbfSLutz Donnerhacke strncpy(p.peerhook, hook2, sizeof(p.peerhook));
9424ea1dbfSLutz Donnerhacke strncpy(p.type, type, sizeof(p.type));
9524ea1dbfSLutz Donnerhacke
9624ea1dbfSLutz Donnerhacke CHECK(, -1 != NgSendMsg(cs, path1,
9724ea1dbfSLutz Donnerhacke NGM_GENERIC_COOKIE, NGM_MKPEER,
9824ea1dbfSLutz Donnerhacke &p, sizeof(p)));
9924ea1dbfSLutz Donnerhacke }
10024ea1dbfSLutz Donnerhacke
10124ea1dbfSLutz Donnerhacke void
_ng_rmhook(char const * path,char const * hook,char const * file,size_t line)1029021c466SLutz Donnerhacke _ng_rmhook(char const *path, char const *hook,
1039021c466SLutz Donnerhacke char const *file, size_t line)
10424ea1dbfSLutz Donnerhacke {
10524ea1dbfSLutz Donnerhacke struct ngm_rmhook h;
10624ea1dbfSLutz Donnerhacke
10724ea1dbfSLutz Donnerhacke strncpy(h.ourhook, hook, sizeof(h.ourhook));
10824ea1dbfSLutz Donnerhacke
10924ea1dbfSLutz Donnerhacke CHECK(, -1 != NgSendMsg(cs, path,
11024ea1dbfSLutz Donnerhacke NGM_GENERIC_COOKIE, NGM_RMHOOK,
11124ea1dbfSLutz Donnerhacke &h, sizeof(h)));
11224ea1dbfSLutz Donnerhacke }
11324ea1dbfSLutz Donnerhacke
11424ea1dbfSLutz Donnerhacke void
_ng_name(char const * path,char const * name,char const * file,size_t line)1159021c466SLutz Donnerhacke _ng_name(char const *path, char const *name,
1169021c466SLutz Donnerhacke char const *file, size_t line)
11724ea1dbfSLutz Donnerhacke {
11824ea1dbfSLutz Donnerhacke struct ngm_name n;
11924ea1dbfSLutz Donnerhacke
12024ea1dbfSLutz Donnerhacke strncpy(n.name, name, sizeof(n.name));
12124ea1dbfSLutz Donnerhacke
12224ea1dbfSLutz Donnerhacke CHECK(, -1 != NgSendMsg(cs, path,
12324ea1dbfSLutz Donnerhacke NGM_GENERIC_COOKIE, NGM_NAME,
12424ea1dbfSLutz Donnerhacke &n, sizeof(n)));
12524ea1dbfSLutz Donnerhacke }
12624ea1dbfSLutz Donnerhacke
12724ea1dbfSLutz Donnerhacke void
_ng_shutdown(char const * path,char const * file,size_t line)1289021c466SLutz Donnerhacke _ng_shutdown(char const *path,
1299021c466SLutz Donnerhacke char const *file, size_t line)
13024ea1dbfSLutz Donnerhacke {
13124ea1dbfSLutz Donnerhacke CHECK(, -1 != NgSendMsg(cs, path,
13224ea1dbfSLutz Donnerhacke NGM_GENERIC_COOKIE, NGM_SHUTDOWN,
13324ea1dbfSLutz Donnerhacke NULL, 0));
13424ea1dbfSLutz Donnerhacke }
13524ea1dbfSLutz Donnerhacke
13624ea1dbfSLutz Donnerhacke void
ng_register_data(char const * hook,ng_data_handler_t proc)13724ea1dbfSLutz Donnerhacke ng_register_data(char const *hook, ng_data_handler_t proc)
13824ea1dbfSLutz Donnerhacke {
13924ea1dbfSLutz Donnerhacke struct data_handler *p;
14024ea1dbfSLutz Donnerhacke
14124ea1dbfSLutz Donnerhacke ATF_REQUIRE(NULL != (p = calloc(1, sizeof(struct data_handler))));
14224ea1dbfSLutz Donnerhacke ATF_REQUIRE(NULL != (p->hook = strdup(hook)));
14324ea1dbfSLutz Donnerhacke ATF_REQUIRE(NULL != (p->handler = proc));
14424ea1dbfSLutz Donnerhacke SLIST_INSERT_HEAD(&data_head, p, next);
14524ea1dbfSLutz Donnerhacke }
14624ea1dbfSLutz Donnerhacke
14724ea1dbfSLutz Donnerhacke void
_ng_send_data(char const * hook,void const * data,size_t len,char const * file,size_t line)1489021c466SLutz Donnerhacke _ng_send_data(char const *hook,
1499021c466SLutz Donnerhacke void const *data, size_t len,
1509021c466SLutz Donnerhacke char const *file, size_t line)
15124ea1dbfSLutz Donnerhacke {
15224ea1dbfSLutz Donnerhacke CHECK(, -1 != NgSendData(ds, hook, data, len));
15324ea1dbfSLutz Donnerhacke }
15424ea1dbfSLutz Donnerhacke
15509307dbfSLutz Donnerhacke void
ng_register_msg(ng_msg_handler_t proc)156a664ade9SLutz Donnerhacke ng_register_msg(ng_msg_handler_t proc)
157a664ade9SLutz Donnerhacke {
15809307dbfSLutz Donnerhacke msg_handler = proc;
15909307dbfSLutz Donnerhacke }
16009307dbfSLutz Donnerhacke
16124ea1dbfSLutz Donnerhacke static void
handle_msg(void * ctx)162a664ade9SLutz Donnerhacke handle_msg(void *ctx)
163a664ade9SLutz Donnerhacke {
16424ea1dbfSLutz Donnerhacke struct ng_mesg *m;
16524ea1dbfSLutz Donnerhacke char path[NG_PATHSIZ];
16624ea1dbfSLutz Donnerhacke
16724ea1dbfSLutz Donnerhacke ATF_REQUIRE(-1 != NgAllocRecvMsg(cs, &m, path));
16824ea1dbfSLutz Donnerhacke
16909307dbfSLutz Donnerhacke if (msg_handler != NULL)
17009307dbfSLutz Donnerhacke (*msg_handler) (path, m, ctx);
17109307dbfSLutz Donnerhacke
17224ea1dbfSLutz Donnerhacke free(m);
17324ea1dbfSLutz Donnerhacke }
17424ea1dbfSLutz Donnerhacke
17524ea1dbfSLutz Donnerhacke static void
handle_data(void * ctx)176a664ade9SLutz Donnerhacke handle_data(void *ctx)
177a664ade9SLutz Donnerhacke {
17824ea1dbfSLutz Donnerhacke char hook[NG_HOOKSIZ];
17924ea1dbfSLutz Donnerhacke struct data_handler *hnd;
18024ea1dbfSLutz Donnerhacke u_char *data;
18124ea1dbfSLutz Donnerhacke int len;
18224ea1dbfSLutz Donnerhacke
18324ea1dbfSLutz Donnerhacke ATF_REQUIRE(0 < (len = NgAllocRecvData(ds, &data, hook)));
18424ea1dbfSLutz Donnerhacke SLIST_FOREACH(hnd, &data_head, next)
185a664ade9SLutz Donnerhacke {
18624ea1dbfSLutz Donnerhacke if (0 == strcmp(hnd->hook, hook))
18724ea1dbfSLutz Donnerhacke break;
188a664ade9SLutz Donnerhacke }
18924ea1dbfSLutz Donnerhacke
19024ea1dbfSLutz Donnerhacke if (hnd != NULL)
19124ea1dbfSLutz Donnerhacke (*(hnd->handler)) (data, len, ctx);
19224ea1dbfSLutz Donnerhacke
19324ea1dbfSLutz Donnerhacke free(data);
19424ea1dbfSLutz Donnerhacke }
19524ea1dbfSLutz Donnerhacke
19624ea1dbfSLutz Donnerhacke int
ng_handle_event(unsigned int ms,void * context)19724ea1dbfSLutz Donnerhacke ng_handle_event(unsigned int ms, void *context)
19824ea1dbfSLutz Donnerhacke {
19924ea1dbfSLutz Donnerhacke fd_set fds;
20024ea1dbfSLutz Donnerhacke int maxfd = (ds < cs) ? cs : ds;
20124ea1dbfSLutz Donnerhacke struct timeval timeout = {0, ms * 1000lu};
20224ea1dbfSLutz Donnerhacke
20324ea1dbfSLutz Donnerhacke FD_ZERO(&fds);
20424ea1dbfSLutz Donnerhacke FD_SET(cs, &fds);
20524ea1dbfSLutz Donnerhacke FD_SET(ds, &fds);
20624ea1dbfSLutz Donnerhacke retry:
207a664ade9SLutz Donnerhacke switch (select(maxfd + 1, &fds, NULL, NULL, &timeout))
208a664ade9SLutz Donnerhacke {
20924ea1dbfSLutz Donnerhacke case -1:
21024ea1dbfSLutz Donnerhacke ATF_REQUIRE_ERRNO(EINTR, 1);
21124ea1dbfSLutz Donnerhacke goto retry;
21224ea1dbfSLutz Donnerhacke case 0: /* timeout */
21324ea1dbfSLutz Donnerhacke return 0;
21424ea1dbfSLutz Donnerhacke default: /* something to do */
21524ea1dbfSLutz Donnerhacke if (FD_ISSET(cs, &fds))
21609307dbfSLutz Donnerhacke handle_msg(context);
21724ea1dbfSLutz Donnerhacke if (FD_ISSET(ds, &fds))
21824ea1dbfSLutz Donnerhacke handle_data(context);
21924ea1dbfSLutz Donnerhacke return 1;
22024ea1dbfSLutz Donnerhacke }
22124ea1dbfSLutz Donnerhacke }
22224ea1dbfSLutz Donnerhacke
22324ea1dbfSLutz Donnerhacke void
ng_handle_events(unsigned int ms,void * context)22424ea1dbfSLutz Donnerhacke ng_handle_events(unsigned int ms, void *context)
22524ea1dbfSLutz Donnerhacke {
22624ea1dbfSLutz Donnerhacke while (ng_handle_event(ms, context))
22724ea1dbfSLutz Donnerhacke ;
22824ea1dbfSLutz Donnerhacke }
22924ea1dbfSLutz Donnerhacke
23024ea1dbfSLutz Donnerhacke int
_ng_send_msg(char const * path,char const * msg,char const * file,size_t line)2319021c466SLutz Donnerhacke _ng_send_msg(char const *path, char const *msg,
2329021c466SLutz Donnerhacke char const *file, size_t line)
23324ea1dbfSLutz Donnerhacke {
23424ea1dbfSLutz Donnerhacke int res;
23524ea1dbfSLutz Donnerhacke
23624ea1dbfSLutz Donnerhacke CHECK(-1, -1 != (res = NgSendAsciiMsg(cs, path, "%s", msg)));
23724ea1dbfSLutz Donnerhacke return (res);
23824ea1dbfSLutz Donnerhacke }
23924ea1dbfSLutz Donnerhacke
24024ea1dbfSLutz Donnerhacke ng_error_t
ng_errors(ng_error_t n)24124ea1dbfSLutz Donnerhacke ng_errors(ng_error_t n)
24224ea1dbfSLutz Donnerhacke {
24324ea1dbfSLutz Donnerhacke ng_error_t o = error_handling;
24424ea1dbfSLutz Donnerhacke
24524ea1dbfSLutz Donnerhacke error_handling = n;
24624ea1dbfSLutz Donnerhacke return (o);
24724ea1dbfSLutz Donnerhacke }
24824ea1dbfSLutz Donnerhacke
24924ea1dbfSLutz Donnerhacke void
_ng_init(char const * file,size_t line)250a664ade9SLutz Donnerhacke _ng_init(char const *file, size_t line)
251a664ade9SLutz Donnerhacke {
25224ea1dbfSLutz Donnerhacke if (cs >= 0) /* prevent reinit */
25324ea1dbfSLutz Donnerhacke return;
25424ea1dbfSLutz Donnerhacke
2559021c466SLutz Donnerhacke CHECK(, 0 == NgMkSockNode(NULL, &cs, &ds));
25624ea1dbfSLutz Donnerhacke NgSetDebug(3);
25724ea1dbfSLutz Donnerhacke }
2585554abd9SLutz Donnerhacke
2595554abd9SLutz Donnerhacke #define GD(x) void \
2605554abd9SLutz Donnerhacke get_data##x(void *data, size_t len, void *ctx) {\
2615554abd9SLutz Donnerhacke int *cnt = ctx; \
2625554abd9SLutz Donnerhacke \
2635554abd9SLutz Donnerhacke (void)data; \
2645554abd9SLutz Donnerhacke (void)len; \
2655554abd9SLutz Donnerhacke cnt[x]++; \
2665554abd9SLutz Donnerhacke }
2675554abd9SLutz Donnerhacke
2685554abd9SLutz Donnerhacke GD(0)
2695554abd9SLutz Donnerhacke GD(1)
2705554abd9SLutz Donnerhacke GD(2)
2715554abd9SLutz Donnerhacke GD(3)
2725554abd9SLutz Donnerhacke GD(4)
2735554abd9SLutz Donnerhacke GD(5)
2745554abd9SLutz Donnerhacke GD(6)
2755554abd9SLutz Donnerhacke GD(7)
2765554abd9SLutz Donnerhacke GD(8)
2775554abd9SLutz Donnerhacke GD(9)
278