Thanks Claudio, Ill investigate a little further On Tue, 21 Jan 2020 at 03:09, Claudio Jeker <cje...@diehard.n-r-g.com> wrote: > > On Tue, Jan 21, 2020 at 02:44:35AM +0000, Tom Smyth wrote: > > Claudio, > > Thanks for this, > > I compiled it on Openbsd 6.6 (stable) amd64 > > > > it compiled without error > > > > the binary seems to run fine but, > > ./tbridge -k /dev/tap0 /dev/tap1 > > > > runs and displays the usage message and gives an errorlevel of 1 > > every time use the -k or -t or -s or -p arguments see terminal > > conversation below > > > > Shit, I added a last minute check and as usual introduced a bug. > Line 189 change if (ch != 0) to if (mode != 0) > > -- > :wq Claudio > > /* > * Copyright (c) 2020 Claudio Jeker <clau...@openbsd.org> > * > * Permission to use, copy, modify, and distribute this software for any > * purpose with or without fee is hereby granted, provided that the above > * copyright notice and this permission notice appear in all copies. > * > * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES > * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF > * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR > * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES > * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN > * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF > * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. > */ > #include <sys/types.h> > #include <sys/event.h> > #include <sys/time.h> > > #include <err.h> > #include <errno.h> > #include <fcntl.h> > #include <poll.h> > #include <pthread.h> > #include <signal.h> > #include <stdio.h> > #include <stdlib.h> > #include <string.h> > #include <unistd.h> > > volatile sig_atomic_t quit; > > static void > do_read(int in, int out) > { > char buf[2048]; > ssize_t n, o; > > n = read(in, buf, sizeof(buf)); > if (n == -1) > err(1, "read"); > o = write(out, buf, n); > if (o == -1) > err(1, "read"); > if (o != n) > errx(1, "short write"); > } > > static void > do_poll(int fd[2]) > { > struct pollfd pfd[2]; > int n, i; > > while (quit == 0) { > memset(pfd, 0, sizeof(pfd)); > pfd[0].fd = fd[0]; > pfd[0].events = POLLIN; > > pfd[1].fd = fd[1]; > pfd[1].events = POLLIN; > > n = poll(pfd, 2, INFTIM); > if (n == -1) > err(1, "poll"); > if (n == 0) > errx(1, "poll: timeout"); > for (i = 0; i < 2; i++) { > if (pfd[i].revents & POLLIN) > do_read(fd[i], fd[(i + 1) & 0x1]); > else if (pfd[i].revents & (POLLHUP | POLLERR)) > errx(1, "fd %d revents %x", i, > pfd[i].revents); > } > } > > } > > static void > do_select(int fd[2]) > { > fd_set readfds; > int n, i, maxfd = -1; > > while (quit == 0) { > FD_ZERO(&readfds); > for (i = 0; i < 2; i++) { > if (fd[i] > maxfd) > maxfd = fd[i]; > FD_SET(fd[i], &readfds); > } > n = select(maxfd + 1, &readfds, NULL, NULL, NULL); > if (n == -1) > err(1, "select"); > if (n == 0) > errx(1, "select: timeout"); > for (i = 0; i < 2; i++) { > if (FD_ISSET(fd[i], &readfds)) > do_read(fd[i], fd[(i + 1) & 0x1]); > } > } > } > > static void > do_kqueue(int fd[2]) > { > struct kevent kev[2]; > int kq, i, n; > > if ((kq = kqueue()) == -1) > err(1, "kqueue"); > > memset(kev, 0, sizeof(kev)); > for (i = 0; i < 2; i++) { > EV_SET(&kev[i], fd[i], EVFILT_READ, EV_ADD | EV_ENABLE, > 0, 0, (void *)(intptr_t)i); > } > if (kevent(kq, kev, 2, NULL, 0, NULL) == -1) > err(1, "kevent register"); > > while (quit == 0) { > n = kevent(kq, NULL, 0, kev, 2, NULL); > if (n == -1) > err(1, "kevent"); > if (n == 0) > errx(1, "kevent: timeout"); > for (i = 0; i < n; i++) { > if (kev[i].flags & EV_ERROR) > errc(1, kev[i].data, "kevent EV_ERROR"); > if (kev[i].filter == EVFILT_READ) { > int r = (int)kev[i].udata; > do_read(fd[r], fd[(r + 1) & 0x1]); > } > } > } > } > > static void * > run_thread(void *arg) > { > int *fd = arg; > > while (quit == 0) > do_read(fd[0], fd[1]); > > return NULL; > } > > static void > do_thread(int fd[2]) > { > pthread_t tid; > int ret; > > ret = pthread_create(&tid, NULL, run_thread, fd); > if (ret) { > errc(1, ret, "pthread_create"); > } > > while (quit == 0) > do_read(fd[1], fd[0]); > } > > static void > sighdlr(int sig) > { > quit = 1; > } > > static __dead void > usage(void) > { > fprintf(stderr, "tbridge -k | -p | -s | -t tapA tapB\n"); > exit(1); > } > > int > main(int argc, char **argv) > { > int fd[2]; > int ch = 0; > int mode = 0; > > while ((ch = getopt(argc, argv, "kpst")) != -1) { > switch (ch) { > case 'k': > case 'p': > case 's': > case 't': > if (mode != 0) > usage(); > mode = ch; > break; > default: > usage(); > } > } > argc -= optind; > argv += optind; > if (argc != 2) > usage(); > > signal(SIGTERM, sighdlr); > signal(SIGINT, sighdlr); > signal(SIGHUP, sighdlr); > > fd[0] = open(argv[0], O_RDWR); > if (fd[0] == -1) > err(1, "open %s", argv[1]); > > fd[1] = open(argv[1], O_RDWR); > if (fd[1] == -1) > err(1, "open %s", argv[2]); > > switch (mode) { > case 'k': > do_kqueue(fd); > break; > case 'p': > do_poll(fd); > break; > case 's': > do_select(fd); > break; > case 't': > do_thread(fd); > break; > } > exit(0); > }
-- Kindest regards, Tom Smyth.