33#include <sys/socket.h>
42#include "mock_bpa_ctr.h"
44static atomic_bool stop_state;
46#define DATA_QUEUE_SIZE 100
49 BUFFER_QUEUE | BUFFER_THREAD_SAFE | BUFFER_PUSH_INIT_POP_MOVE | BUFFER_BLOCKING)
51static data_queue_t over_rx;
52static data_queue_t over_tx;
53static data_queue_t under_rx;
54static data_queue_t under_tx;
55static data_queue_t deliver;
56static data_queue_t forward;
58static pthread_t thr_over_rx, thr_under_rx, thr_deliver, thr_forward;
65static struct sockaddr_in6 over_addr = { .sin6_family = 0 };
66static struct sockaddr_in6 app_addr = { .sin6_family = 0 };
67static struct sockaddr_in6 under_addr = { .sin6_family = 0 };
68static struct sockaddr_in6 router_addr = { .sin6_family = 0 };
69static int tx_notify_r, tx_notify_w;
72static int ingest_netaddr(
struct sockaddr_in6 *addr,
const char *optarg)
74 const char *node = optarg;
75 const char *service =
"4556";
76 char *sep = strchr(optarg,
':');
82 struct addrinfo hints = {
83 .ai_family = AF_INET6,
84 .ai_socktype = SOCK_DGRAM,
85 .ai_protocol = IPPROTO_UDP,
86 .ai_flags = AI_ADDRCONFIG | AI_NUMERICSERV,
88 struct addrinfo *result;
90 BSL_LOG_DEBUG(
"Resolving under address: %s %s", node, service);
91 int res = getaddrinfo(node, service, &hints, &result);
94 BSL_LOG_ERR(
"Failed to resolve router address: %s", optarg);
99 for (
const struct addrinfo *rp = result; rp != NULL; rp = rp->ai_next)
102 if (rp->ai_family == AF_INET6)
104 memcpy(addr, rp->ai_addr, rp->ai_addrlen);
108 freeaddrinfo(result);
113static int bind_udp(
int *sock,
const struct sockaddr_in6 *addr)
115 *sock = socket(addr->sin6_family, SOCK_DGRAM, IPPROTO_UDP);
122 char nodebuf[INET6_ADDRSTRLEN];
123 inet_ntop(addr->sin6_family, &addr->sin6_addr, nodebuf,
sizeof(nodebuf));
124 BSL_LOG_DEBUG(
"Binding UDP socket to [%s]:%d", nodebuf, ntohs(addr->sin6_port));
126 int res = bind(*sock, (
struct sockaddr *)addr,
sizeof(*addr));
130 BSL_LOG_ERR(
"Failed to bind UDP socket, errno %d", errno);
148 bundle_ref.
data = bundle;
149 BSL_LOG_INFO(
"Mock BPA: Calling BSL_API_QuerySecurity");
153 BSL_LOG_ERR(
"Failed to query security: code=%d", returncode);
157 BSL_LOG_INFO(
"Mock BPA: Calling BSL_API_ApplySecurity");
161 BSL_LOG_ERR(
"Failed to apply security: code=%d", returncode);
165 BSL_LOG_INFO(
"Mock BPA: mock_bpa_process SUCCESS (code=0)");
168 free(malloced_action_set);
169 free(malloced_response_set);
173static void sig_stop(
int signum
_U_)
175 atomic_store(&stop_state,
true);
179static void *work_over_rx(
void *arg
_U_)
185 data_queue_pop(&item, over_rx);
191 mock_bpa_decode(&item, bsl);
195 BSL_LOG_ERR(
"work_over_rx failed security processing");
196 mock_bpa_ctr_deinit(&item);
201 data_queue_push(deliver, item);
208static void *work_under_rx(
void *arg
_U_)
214 data_queue_pop(&item, under_rx);
221 if (mock_bpa_decode(&item, bsl))
223 BSL_LOG_ERR(
"work_under_rx failed to decode bundle");
224 mock_bpa_ctr_deinit(&item);
230 BSL_LOG_ERR(
"work_under_rx failed security processing");
231 mock_bpa_ctr_deinit(&item);
236 data_queue_push(forward, item);
243static void *work_deliver(
void *arg
_U_)
249 data_queue_pop(&item, deliver);
258 BSL_LOG_ERR(
"work_deliver failed security processing");
259 mock_bpa_ctr_deinit(&item);
263 mock_bpa_encode(&item);
264 data_queue_push(over_tx, item);
267 int nbytes = write(tx_notify_w, &buf,
sizeof(uint8_t));
279static void *work_forward(
void *arg
_U_)
285 data_queue_pop(&item, forward);
294 BSL_LOG_ERR(
"work_forward failed security processing");
295 mock_bpa_ctr_deinit(&item);
299 mock_bpa_encode(&item);
300 data_queue_push(under_tx, item);
303 int nbytes = write(tx_notify_w, &buf,
sizeof(uint8_t));
315static int bpa_init(
void)
318 struct sigaction stopper = {
319 .sa_handler = sig_stop,
321 sigaction(SIGINT, &stopper, NULL);
322 sigaction(SIGTERM, &stopper, NULL);
325 data_queue_init(over_rx, DATA_QUEUE_SIZE);
326 data_queue_init(over_tx, DATA_QUEUE_SIZE);
327 data_queue_init(under_rx, DATA_QUEUE_SIZE);
328 data_queue_init(under_tx, DATA_QUEUE_SIZE);
329 data_queue_init(deliver, DATA_QUEUE_SIZE);
330 data_queue_init(forward, DATA_QUEUE_SIZE);
339 tx_notify_r = fds[0];
340 tx_notify_w = fds[1];
343 if (pthread_create(&thr_under_rx, NULL, work_under_rx, NULL))
347 if (pthread_create(&thr_over_rx, NULL, work_over_rx, NULL))
351 if (pthread_create(&thr_deliver, NULL, work_deliver, NULL))
355 if (pthread_create(&thr_forward, NULL, work_forward, NULL))
362static int bpa_exec(
void)
366 int over_sock, under_sock;
367 if (bind_udp(&over_sock, &over_addr))
371 if (bind_udp(&under_sock, &under_addr))
376 struct pollfd pfds[] = {
377 { .fd = tx_notify_r, .events = POLLIN },
378 { .fd = under_sock },
381 struct pollfd *
const tx_notify_pfd = pfds;
382 struct pollfd *
const under_pfd = pfds + 1;
383 struct pollfd *
const over_pfd = pfds + 2;
387 while (!atomic_load(&stop_state))
389 under_pfd->events = POLLIN;
390 if (!data_queue_empty_p(under_tx))
392 under_pfd->events |= POLLOUT;
395 over_pfd->events = POLLIN;
396 if (!data_queue_empty_p(over_tx))
398 over_pfd->events |= POLLOUT;
401 int res = poll(pfds,
sizeof(pfds) /
sizeof(
struct pollfd), -1);
408 if (tx_notify_pfd->revents & POLLIN)
412 int nbytes = read(tx_notify_r, &buf,
sizeof(uint8_t));
419 if (over_pfd->revents & POLLIN)
424 .iov_len =
sizeof(buf),
426 struct msghdr msg = {
430 ssize_t got = recvmsg(over_sock, &msg, 0);
435 mock_bpa_ctr_init(&item);
438 data_queue_push(over_rx, item);
441 if (over_pfd->revents & POLLOUT)
444 data_queue_pop(&item, over_tx);
451 struct msghdr msg = {
452 .msg_name = &app_addr,
453 .msg_namelen =
sizeof(app_addr),
457 ssize_t got = sendmsg(over_sock, &msg, 0);
460 BSL_LOG_ERR(
"over_sock failed to send all %zd bytes, only %zd sent: %d", item.
encoded.
len, got, errno);
462 mock_bpa_ctr_deinit(&item);
465 if (under_pfd->revents & POLLIN)
470 .iov_len =
sizeof(buf),
472 struct msghdr msg = {
476 ssize_t got = recvmsg(under_sock, &msg, 0);
481 mock_bpa_ctr_init(&item);
484 data_queue_push(under_rx, item);
487 if (under_pfd->revents & POLLOUT)
490 data_queue_pop(&item, under_tx);
497 struct msghdr msg = {
498 .msg_name = &router_addr,
499 .msg_namelen =
sizeof(router_addr),
503 ssize_t got = sendmsg(under_sock, &msg, 0);
508 mock_bpa_ctr_deinit(&item);
517static void bpa_cleanup(
void)
523 data_queue_push(under_rx, item);
525 data_queue_push(over_rx, item);
526 if (pthread_join(thr_under_rx, NULL))
530 if (pthread_join(thr_over_rx, NULL))
537 data_queue_push(forward, item);
539 data_queue_push(deliver, item);
540 if (pthread_join(thr_forward, NULL))
544 if (pthread_join(thr_deliver, NULL))
551 data_queue_clear(over_rx);
552 data_queue_clear(over_tx);
553 data_queue_clear(under_rx);
554 data_queue_clear(under_tx);
555 data_queue_clear(deliver);
556 data_queue_clear(forward);
563static void show_usage(
const char *argv0)
566 "Usage: %s -o <over-socket address:port> -a <application address:port>\n"
567 " -u <under-socket address:port> -r <router address:port>\n"
568 " -e <app-EID> -s <sec-src-EID>\n",
575int main(
int argc,
char **argv)
580 atomic_init(&stop_state,
false);
589 bsl = calloc(50000, 1);
598 .user_data = malloc(100000) };
602 (void)security_context_callbacks;
609 while ((opt = getopt(argc, argv,
"ha:o:a:u:r:e:s:")) != -1)
614 ingest_netaddr(&over_addr, optarg);
617 ingest_netaddr(&app_addr, optarg);
620 ingest_netaddr(&under_addr, optarg);
623 ingest_netaddr(&router_addr, optarg);
628 BSL_LOG_ERR(
"Failed to decode app EID: %s", optarg);
635 BSL_LOG_ERR(
"Failed to decode BPSec EID: %s", optarg);
646 if (!retval && (over_addr.sin6_family != AF_INET6))
652 if (!retval && (app_addr.sin6_family != AF_INET6))
658 if (!retval && (under_addr.sin6_family != AF_INET6))
664 if (!retval && (router_addr.sin6_family != AF_INET6))
Single entry-point include file for all of the BPSec Lib (BSL) frontend API.
#define BSL_LOG_DEBUG(...)
This is an overloaded member function, provided for convenience. It differs from the above function o...
#define BSL_LOG_INFO(...)
This is an overloaded member function, provided for convenience. It differs from the above function o...
#define _U_
Mark an unused parameter Within a function definition.
#define BSL_LOG_ERR(...)
This is an overloaded member function, provided for convenience. It differs from the above function o...
@ BSL_SUCCESS
Placeholder for non-error code.
Single entry-point include file for all of the "Public" BPSec Lib (BSL) frontend API.
BSL_PolicyLocation_e
Indicates where in the lifecycle of the BPA the bundle is querying for security policy.
@ BSL_POLICYLOCATION_APPOUT
Bundle destination at delivery.
@ BSL_POLICYLOCATION_APPIN
Bundle source at creation.
@ BSL_POLICYLOCATION_CLIN
Bundle ingress from CLA.
@ BSL_POLICYLOCATION_CLOUT
Bundle egress to CLA.
Header for the implementation of an example default security context (RFC 9173).
int BSL_HostEID_Init(BSL_HostEID_t *eid)
Initialize an abstract EID.
int BSL_HostEID_DecodeFromText(BSL_HostEID_t *eid, const char *text)
Decode an EID from its text form.
void BSL_HostEID_Deinit(BSL_HostEID_t *eid)
De-initialize an abstract EID.
void BSL_openlog(void)
Opens the event log.
void BSL_closelog(void)
Closes the event log.
int BSL_API_InitLib(BSL_LibCtx_t *lib)
Initialize the BPSecLib (BSL) library context.
int BSL_API_QuerySecurity(const BSL_LibCtx_t *bsl, BSL_SecurityActionSet_t *output_action_set, const BSL_BundleRef_t *bundle, BSL_PolicyLocation_e location)
Query BSL to populate a BSL_SecurityActionSet_t containg security processing instructions.
int BSL_API_RegisterPolicyProvider(BSL_LibCtx_t *lib, BSL_PolicyDesc_t desc)
Register a Policy Provider module with the BSL.
int BSL_API_ApplySecurity(const BSL_LibCtx_t *bsl, BSL_SecurityResponseSet_t *response_output, BSL_BundleRef_t *bundle, const BSL_SecurityActionSet_t *policy_actions)
Performs the given security operations on a Bundle, modifying or even dropping it entirely.
int BSL_API_DeinitLib(BSL_LibCtx_t *lib)
Deinitialize and release any resources held by the BSL.
int BSLP_QueryPolicy(const void *user_data, BSL_SecurityActionSet_t *output_action_set, const BSL_BundleRef_t *bundle, BSL_PolicyLocation_e location)
Note that criticality is HIGH.
Spec of locally-defined data structures.
size_t BSL_SecurityActionSet_Sizeof(void)
Returns size of the struct, helpful for dynamic allocation.
size_t BSL_SecurityResponseSet_Sizeof()
Returns size of this struct type.
int BSL_Data_AppendFrom(BSL_Data_t *data, size_t len, BSL_DataConstPtr_t src)
Append an initialized data struct with a given size.
void bsl_mock_bpa_deinit(void)
Clean up the mock BPA for the current process.
int bsl_mock_bpa_init(void)
Register this mock BPA for the current process.
Declarations for Agent initialization.
Reference to a Bundle owned and stored in the host BPA.
void * data
Opaque pointer, not used by the BSL.
size_t len
Size of the data buffer.
BSL_DataPtr_t ptr
Pointer to the front of the buffer.
Opaque pointer to BPA-specific Endpoint ID storage.
Concrete definition of library context.
Descriptor of opaque data and callbacks for Policy Provider.
BSL_PolicyDeinit_f deinit_fn
Function to deinit the policy provider at termination of BPA.
Security Context descriptor (interface)
Contains the populated security operations for this bundle.
Contains the results and outcomes after performing the security operations.
A container for encoded and decoded bundle data.
BSL_Data_t encoded
Encoded PDU.
BSL_BundleRef_t bundle_ref
The decoded bundle.