1a8edc9f1SGleb Smirnoff /*-
2a8edc9f1SGleb Smirnoff * SPDX-License-Identifier: BSD-2-Clause
3a8edc9f1SGleb Smirnoff *
4a8edc9f1SGleb Smirnoff * Copyright (c) 2024 Gleb Smirnoff <glebius@FreeBSD.org>
5a8edc9f1SGleb Smirnoff *
6a8edc9f1SGleb Smirnoff * Redistribution and use in source and binary forms, with or without
7a8edc9f1SGleb Smirnoff * modification, are permitted provided that the following conditions
8a8edc9f1SGleb Smirnoff * are met:
9a8edc9f1SGleb Smirnoff * 1. Redistributions of source code must retain the above copyright
10a8edc9f1SGleb Smirnoff * notice, this list of conditions and the following disclaimer.
11a8edc9f1SGleb Smirnoff * 2. Redistributions in binary form must reproduce the above copyright
12a8edc9f1SGleb Smirnoff * notice, this list of conditions and the following disclaimer in the
13a8edc9f1SGleb Smirnoff * documentation and/or other materials provided with the distribution.
14a8edc9f1SGleb Smirnoff *
15a8edc9f1SGleb Smirnoff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16a8edc9f1SGleb Smirnoff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17a8edc9f1SGleb Smirnoff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18a8edc9f1SGleb Smirnoff * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19a8edc9f1SGleb Smirnoff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20a8edc9f1SGleb Smirnoff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21a8edc9f1SGleb Smirnoff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22a8edc9f1SGleb Smirnoff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23a8edc9f1SGleb Smirnoff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24a8edc9f1SGleb Smirnoff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25a8edc9f1SGleb Smirnoff * SUCH DAMAGE.
26a8edc9f1SGleb Smirnoff */
27a8edc9f1SGleb Smirnoff
28a8edc9f1SGleb Smirnoff #include <sys/socket.h>
29a8edc9f1SGleb Smirnoff #include <netinet/in.h>
30a8edc9f1SGleb Smirnoff #include <netgraph.h>
31a8edc9f1SGleb Smirnoff #include <netgraph/ng_socket.h>
32a8edc9f1SGleb Smirnoff #include <netgraph/ng_ksocket.h>
33a8edc9f1SGleb Smirnoff
34a8edc9f1SGleb Smirnoff #include <errno.h>
35a8edc9f1SGleb Smirnoff
36a8edc9f1SGleb Smirnoff #include <atf-c.h>
37a8edc9f1SGleb Smirnoff
38a8edc9f1SGleb Smirnoff static void
hellocheck(int wr,int rd)39a8edc9f1SGleb Smirnoff hellocheck(int wr, int rd)
40a8edc9f1SGleb Smirnoff {
41a8edc9f1SGleb Smirnoff char sbuf[] = "Hello, peer!", rbuf[sizeof(sbuf)];
42a8edc9f1SGleb Smirnoff
43a8edc9f1SGleb Smirnoff ATF_REQUIRE(send(wr, sbuf, sizeof(sbuf), 0) == sizeof(sbuf));
44a8edc9f1SGleb Smirnoff ATF_REQUIRE(recv(rd, rbuf, sizeof(rbuf), 0) == sizeof(sbuf));
45a8edc9f1SGleb Smirnoff ATF_REQUIRE(strcmp(sbuf, rbuf) == 0);
46a8edc9f1SGleb Smirnoff }
47a8edc9f1SGleb Smirnoff
48a8edc9f1SGleb Smirnoff #define OURHOOK "ks"
49a8edc9f1SGleb Smirnoff
50a8edc9f1SGleb Smirnoff ATF_TC_WITHOUT_HEAD(udp_connect);
ATF_TC_BODY(udp_connect,tc)51a8edc9f1SGleb Smirnoff ATF_TC_BODY(udp_connect, tc)
52a8edc9f1SGleb Smirnoff {
53*d86c5811SSeyed Pouria Mousavizadeh Tehrani struct ngm_mkpeer mkp = {
54*d86c5811SSeyed Pouria Mousavizadeh Tehrani .type = NG_KSOCKET_NODE_TYPE,
55*d86c5811SSeyed Pouria Mousavizadeh Tehrani .ourhook = OURHOOK,
56*d86c5811SSeyed Pouria Mousavizadeh Tehrani .peerhook = "inet/dgram/udp",
57*d86c5811SSeyed Pouria Mousavizadeh Tehrani };
582fcbd5a7SMark Johnston struct sockaddr_in sin = {
592fcbd5a7SMark Johnston .sin_family = AF_INET,
602fcbd5a7SMark Johnston .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
612fcbd5a7SMark Johnston .sin_len = sizeof(sin),
62a8edc9f1SGleb Smirnoff };
632fcbd5a7SMark Johnston socklen_t slen = sizeof(sin);
64*d86c5811SSeyed Pouria Mousavizadeh Tehrani int cs, ds, us;
65a8edc9f1SGleb Smirnoff
66a8edc9f1SGleb Smirnoff ATF_REQUIRE((us = socket(PF_INET, SOCK_DGRAM, 0)) > 0);
672fcbd5a7SMark Johnston ATF_REQUIRE(bind(us, (struct sockaddr *)&sin, sizeof(sin)) == 0);
682fcbd5a7SMark Johnston ATF_REQUIRE(getsockname(us, (struct sockaddr *)&sin, &slen) == 0);
69a8edc9f1SGleb Smirnoff
70a8edc9f1SGleb Smirnoff ATF_REQUIRE(NgMkSockNode(NULL, &cs, &ds) == 0);
71a8edc9f1SGleb Smirnoff ATF_REQUIRE(NgSendMsg(cs, ".", NGM_GENERIC_COOKIE, NGM_MKPEER, &mkp,
72a8edc9f1SGleb Smirnoff sizeof(mkp)) >= 0);
73a8edc9f1SGleb Smirnoff ATF_REQUIRE(NgSendMsg(cs, ".:" OURHOOK, NGM_KSOCKET_COOKIE,
742fcbd5a7SMark Johnston NGM_KSOCKET_CONNECT, &sin, sizeof(sin)) >= 0);
75a8edc9f1SGleb Smirnoff
76a8edc9f1SGleb Smirnoff hellocheck(ds, us);
77a8edc9f1SGleb Smirnoff }
78a8edc9f1SGleb Smirnoff
79a8edc9f1SGleb Smirnoff ATF_TC_WITHOUT_HEAD(udp_bind);
ATF_TC_BODY(udp_bind,tc)80a8edc9f1SGleb Smirnoff ATF_TC_BODY(udp_bind, tc)
81a8edc9f1SGleb Smirnoff {
82*d86c5811SSeyed Pouria Mousavizadeh Tehrani struct ngm_mkpeer mkp = {
83*d86c5811SSeyed Pouria Mousavizadeh Tehrani .type = NG_KSOCKET_NODE_TYPE,
84*d86c5811SSeyed Pouria Mousavizadeh Tehrani .ourhook = OURHOOK,
85*d86c5811SSeyed Pouria Mousavizadeh Tehrani .peerhook = "inet/dgram/udp",
86*d86c5811SSeyed Pouria Mousavizadeh Tehrani };
87a8edc9f1SGleb Smirnoff struct sockaddr_in sin = {
88a8edc9f1SGleb Smirnoff .sin_family = AF_INET,
892fcbd5a7SMark Johnston .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
90a8edc9f1SGleb Smirnoff .sin_len = sizeof(sin),
91a8edc9f1SGleb Smirnoff };
92a8edc9f1SGleb Smirnoff struct ng_mesg *rep;
93*d86c5811SSeyed Pouria Mousavizadeh Tehrani int cs, ds, us;
94a8edc9f1SGleb Smirnoff
95a8edc9f1SGleb Smirnoff ATF_REQUIRE(NgMkSockNode(NULL, &cs, &ds) == 0);
96a8edc9f1SGleb Smirnoff ATF_REQUIRE(NgSendMsg(cs, ".", NGM_GENERIC_COOKIE, NGM_MKPEER, &mkp,
97a8edc9f1SGleb Smirnoff sizeof(mkp)) >= 0);
98a8edc9f1SGleb Smirnoff ATF_REQUIRE(NgSendMsg(cs, ".:" OURHOOK, NGM_KSOCKET_COOKIE,
99a8edc9f1SGleb Smirnoff NGM_KSOCKET_BIND, &sin, sizeof(sin)) >= 0);
100a8edc9f1SGleb Smirnoff ATF_REQUIRE(NgSendMsg(cs, ".:" OURHOOK, NGM_KSOCKET_COOKIE,
101a8edc9f1SGleb Smirnoff NGM_KSOCKET_GETNAME, NULL, 0) >= 0);
102a8edc9f1SGleb Smirnoff ATF_REQUIRE(NgAllocRecvMsg(cs, &rep, NULL) == sizeof(struct ng_mesg) +
103a8edc9f1SGleb Smirnoff sizeof(struct sockaddr_in));
104a8edc9f1SGleb Smirnoff
105a8edc9f1SGleb Smirnoff ATF_REQUIRE((us = socket(PF_INET, SOCK_DGRAM, 0)) > 0);
106a8edc9f1SGleb Smirnoff ATF_REQUIRE(connect(us, (struct sockaddr *)rep->data,
107a8edc9f1SGleb Smirnoff sizeof(struct sockaddr_in)) == 0);
108a8edc9f1SGleb Smirnoff
109a8edc9f1SGleb Smirnoff hellocheck(us, ds);
110a8edc9f1SGleb Smirnoff }
111a8edc9f1SGleb Smirnoff
112*d86c5811SSeyed Pouria Mousavizadeh Tehrani ATF_TC_WITHOUT_HEAD(udp6_connect);
ATF_TC_BODY(udp6_connect,tc)113*d86c5811SSeyed Pouria Mousavizadeh Tehrani ATF_TC_BODY(udp6_connect, tc)
114*d86c5811SSeyed Pouria Mousavizadeh Tehrani {
115*d86c5811SSeyed Pouria Mousavizadeh Tehrani struct ngm_mkpeer mkp = {
116*d86c5811SSeyed Pouria Mousavizadeh Tehrani .type = NG_KSOCKET_NODE_TYPE,
117*d86c5811SSeyed Pouria Mousavizadeh Tehrani .ourhook = OURHOOK,
118*d86c5811SSeyed Pouria Mousavizadeh Tehrani .peerhook = "inet6/dgram/udp6",
119*d86c5811SSeyed Pouria Mousavizadeh Tehrani };
120*d86c5811SSeyed Pouria Mousavizadeh Tehrani struct sockaddr_in6 sin6 = {
121*d86c5811SSeyed Pouria Mousavizadeh Tehrani .sin6_family = AF_INET6,
122*d86c5811SSeyed Pouria Mousavizadeh Tehrani };
123*d86c5811SSeyed Pouria Mousavizadeh Tehrani socklen_t slen = sizeof(sin6);
124*d86c5811SSeyed Pouria Mousavizadeh Tehrani int cs, ds, us;
125*d86c5811SSeyed Pouria Mousavizadeh Tehrani
126*d86c5811SSeyed Pouria Mousavizadeh Tehrani ATF_REQUIRE((us = socket(PF_INET6, SOCK_DGRAM, 0)) > 0);
127*d86c5811SSeyed Pouria Mousavizadeh Tehrani ATF_REQUIRE(bind(us, (struct sockaddr *)&sin6, sizeof(sin6)) == 0);
128*d86c5811SSeyed Pouria Mousavizadeh Tehrani ATF_REQUIRE(getsockname(us, (struct sockaddr *)&sin6, &slen) == 0);
129*d86c5811SSeyed Pouria Mousavizadeh Tehrani
130*d86c5811SSeyed Pouria Mousavizadeh Tehrani ATF_REQUIRE(NgMkSockNode(NULL, &cs, &ds) == 0);
131*d86c5811SSeyed Pouria Mousavizadeh Tehrani ATF_REQUIRE(NgSendMsg(cs, ".", NGM_GENERIC_COOKIE, NGM_MKPEER, &mkp,
132*d86c5811SSeyed Pouria Mousavizadeh Tehrani sizeof(mkp)) >= 0);
133*d86c5811SSeyed Pouria Mousavizadeh Tehrani ATF_REQUIRE(NgSendMsg(cs, ".:" OURHOOK, NGM_KSOCKET_COOKIE,
134*d86c5811SSeyed Pouria Mousavizadeh Tehrani NGM_KSOCKET_CONNECT, &sin6, sizeof(sin6)) >= 0);
135*d86c5811SSeyed Pouria Mousavizadeh Tehrani
136*d86c5811SSeyed Pouria Mousavizadeh Tehrani hellocheck(ds, us);
137*d86c5811SSeyed Pouria Mousavizadeh Tehrani }
138*d86c5811SSeyed Pouria Mousavizadeh Tehrani
139*d86c5811SSeyed Pouria Mousavizadeh Tehrani
140*d86c5811SSeyed Pouria Mousavizadeh Tehrani ATF_TC_WITHOUT_HEAD(udp6_bind);
ATF_TC_BODY(udp6_bind,tc)141*d86c5811SSeyed Pouria Mousavizadeh Tehrani ATF_TC_BODY(udp6_bind, tc)
142*d86c5811SSeyed Pouria Mousavizadeh Tehrani {
143*d86c5811SSeyed Pouria Mousavizadeh Tehrani struct ngm_mkpeer mkp = {
144*d86c5811SSeyed Pouria Mousavizadeh Tehrani .type = NG_KSOCKET_NODE_TYPE,
145*d86c5811SSeyed Pouria Mousavizadeh Tehrani .ourhook = OURHOOK,
146*d86c5811SSeyed Pouria Mousavizadeh Tehrani .peerhook = "inet6/dgram/udp6",
147*d86c5811SSeyed Pouria Mousavizadeh Tehrani };
148*d86c5811SSeyed Pouria Mousavizadeh Tehrani struct sockaddr_in6 sin6 = {
149*d86c5811SSeyed Pouria Mousavizadeh Tehrani .sin6_family = AF_INET6,
150*d86c5811SSeyed Pouria Mousavizadeh Tehrani .sin6_len = sizeof(sin6),
151*d86c5811SSeyed Pouria Mousavizadeh Tehrani };
152*d86c5811SSeyed Pouria Mousavizadeh Tehrani struct ng_mesg *rep;
153*d86c5811SSeyed Pouria Mousavizadeh Tehrani int cs, ds, us;
154*d86c5811SSeyed Pouria Mousavizadeh Tehrani
155*d86c5811SSeyed Pouria Mousavizadeh Tehrani ATF_REQUIRE(NgMkSockNode(NULL, &cs, &ds) == 0);
156*d86c5811SSeyed Pouria Mousavizadeh Tehrani ATF_REQUIRE(NgSendMsg(cs, ".", NGM_GENERIC_COOKIE, NGM_MKPEER, &mkp,
157*d86c5811SSeyed Pouria Mousavizadeh Tehrani sizeof(mkp)) >= 0);
158*d86c5811SSeyed Pouria Mousavizadeh Tehrani ATF_REQUIRE(NgSendMsg(cs, ".:" OURHOOK, NGM_KSOCKET_COOKIE,
159*d86c5811SSeyed Pouria Mousavizadeh Tehrani NGM_KSOCKET_BIND, &sin6, sizeof(sin6)) >= 0);
160*d86c5811SSeyed Pouria Mousavizadeh Tehrani ATF_REQUIRE(NgSendMsg(cs, ".:" OURHOOK, NGM_KSOCKET_COOKIE,
161*d86c5811SSeyed Pouria Mousavizadeh Tehrani NGM_KSOCKET_GETNAME, NULL, 0) >= 0);
162*d86c5811SSeyed Pouria Mousavizadeh Tehrani ATF_REQUIRE(NgAllocRecvMsg(cs, &rep, NULL) == sizeof(struct ng_mesg) +
163*d86c5811SSeyed Pouria Mousavizadeh Tehrani sizeof(struct sockaddr_in6));
164*d86c5811SSeyed Pouria Mousavizadeh Tehrani
165*d86c5811SSeyed Pouria Mousavizadeh Tehrani ATF_REQUIRE((us = socket(PF_INET6, SOCK_DGRAM, 0)) > 0);
166*d86c5811SSeyed Pouria Mousavizadeh Tehrani ATF_REQUIRE(connect(us, (struct sockaddr *)rep->data,
167*d86c5811SSeyed Pouria Mousavizadeh Tehrani sizeof(struct sockaddr_in6)) == 0);
168*d86c5811SSeyed Pouria Mousavizadeh Tehrani
169*d86c5811SSeyed Pouria Mousavizadeh Tehrani hellocheck(us, ds);
170*d86c5811SSeyed Pouria Mousavizadeh Tehrani }
171*d86c5811SSeyed Pouria Mousavizadeh Tehrani
ATF_TP_ADD_TCS(tp)172a8edc9f1SGleb Smirnoff ATF_TP_ADD_TCS(tp)
173a8edc9f1SGleb Smirnoff {
174a8edc9f1SGleb Smirnoff ATF_TP_ADD_TC(tp, udp_connect);
175a8edc9f1SGleb Smirnoff ATF_TP_ADD_TC(tp, udp_bind);
176*d86c5811SSeyed Pouria Mousavizadeh Tehrani ATF_TP_ADD_TC(tp, udp6_connect);
177*d86c5811SSeyed Pouria Mousavizadeh Tehrani ATF_TP_ADD_TC(tp, udp6_bind);
178a8edc9f1SGleb Smirnoff
179a8edc9f1SGleb Smirnoff return (atf_no_error());
180a8edc9f1SGleb Smirnoff }
181