Path: blob/main/tests/sys/netpfil/common/divapp.c
105154 views
/*-1* SPDX-License-Identifier: BSD-2-Clause2*3* Copyright (c) 2023 Igor Ostapenko <[email protected]>4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8* 1. Redistributions of source code must retain the above copyright9* notice, this list of conditions and the following disclaimer.10* 2. Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND15* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE16* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE17* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE18* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL19* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS20* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)21* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT22* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY23* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF24* SUCH DAMAGE.25*/2627/* Used by divert(4) related tests */2829#include <errno.h>30#include <stdlib.h>31#include <stdbool.h>32#include <err.h>33#include <sysexits.h>34#include <string.h>3536#include <sys/types.h>37#include <sys/socket.h>38#include <netinet/in.h>39#include <netinet/ip.h>404142struct context {43unsigned short divert_port;44bool divert_back;4546int fd;47struct sockaddr_in sin;48socklen_t sin_len;49char pkt[IP_MAXPACKET];50ssize_t pkt_n;51};5253static void54init(struct context *c)55{56c->fd = socket(PF_DIVERT, SOCK_RAW, 0);57if (c->fd == -1)58errx(EX_OSERR, "init: Cannot create divert socket.");5960memset(&c->sin, 0, sizeof(c->sin));61c->sin.sin_family = AF_INET;62c->sin.sin_port = htons(c->divert_port);63c->sin.sin_addr.s_addr = INADDR_ANY;64c->sin_len = sizeof(struct sockaddr_in);6566if (bind(c->fd, (struct sockaddr *) &c->sin, c->sin_len) != 0)67errx(EX_OSERR, "init: Cannot bind divert socket.");68}6970static ssize_t71recv_pkt(struct context *c)72{73fd_set readfds;74struct timeval timeout;75int s;7677FD_ZERO(&readfds);78FD_SET(c->fd, &readfds);79timeout.tv_sec = 3;80timeout.tv_usec = 0;8182s = select(c->fd + 1, &readfds, 0, 0, &timeout);83if (s == -1)84errx(EX_IOERR, "recv_pkt: select() errors.");85if (s != 1) /* timeout */86return (-1);8788c->pkt_n = recvfrom(c->fd, c->pkt, sizeof(c->pkt), 0,89(struct sockaddr *) &c->sin, &c->sin_len);90if (c->pkt_n == -1)91errx(EX_IOERR, "recv_pkt: recvfrom() errors.");9293return (c->pkt_n);94}9596static void97send_pkt(struct context *c)98{99ssize_t n;100101n = sendto(c->fd, c->pkt, c->pkt_n, 0,102(struct sockaddr *) &c->sin, c->sin_len);103if (n == -1)104err(EX_IOERR, "send_pkt: sendto() errors");105if (n != c->pkt_n)106errx(EX_IOERR, "send_pkt: sendto() sent %zd of %zd bytes.",107n, c->pkt_n);108}109110int111main(int argc, char *argv[])112{113struct context c;114int npkt;115116if (argc < 2)117errx(EX_USAGE,118"Usage: %s <divert-port> [divert-back]", argv[0]);119120memset(&c, 0, sizeof(struct context));121122c.divert_port = (unsigned short) strtol(argv[1], NULL, 10);123if (c.divert_port == 0)124errx(EX_USAGE, "divert port is not defined.");125126if (argc >= 3 && strcmp(argv[2], "divert-back") == 0)127c.divert_back = true;128129130init(&c);131132npkt = 0;133while (recv_pkt(&c) > 0) {134if (c.divert_back)135send_pkt(&c);136npkt++;137if (npkt >= 20)138break;139}140141if (npkt != 1)142errx(EXIT_FAILURE, "%d: npkt=%d.", c.divert_port, npkt);143144return (EXIT_SUCCESS);145}146147148