From aa1f699e11e882dd1a8af4a7ceb114b85b1c28dd Mon Sep 17 00:00:00 2001 From: mdw Date: Mon, 26 Jul 1999 23:34:11 +0000 Subject: [PATCH] New socket address types. --- inet.c | 291 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ inet.h | 60 ++++++++++++++ un.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++ un.h | 60 ++++++++++++++ 4 files changed, 621 insertions(+) create mode 100644 inet.c create mode 100644 inet.h create mode 100644 un.c create mode 100644 un.h diff --git a/inet.c b/inet.c new file mode 100644 index 0000000..9980199 --- /dev/null +++ b/inet.c @@ -0,0 +1,291 @@ +/* -*-c-*- + * + * $Id: inet.c,v 1.1 1999/07/26 23:34:11 mdw Exp $ + * + * Protocol specific definitions for IPv4 sockets + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of the `fw' port forwarder. + * + * `fw' is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * `fw' is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with `fw'; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/*----- Revision history --------------------------------------------------* + * + * $Log: inet.c,v $ + * Revision 1.1 1999/07/26 23:34:11 mdw + * New socket address types. + * + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "acl.h" +#include "addr.h" +#include "conf.h" +#include "identify.h" +#include "inet.h" +#include "reffd.h" +#include "scan.h" + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct inet_addrx { + addr a; + struct sockaddr_in sin; +} inet_addrx; + +typedef struct inet_opts { + addr_opts ao; + acl_entry *acl; + acl_entry **acltail; +} inet_opts; + +/*----- Protocol operations -----------------------------------------------*/ + +/* --- @read@ --- */ + +static addr *inet_read(scanner *sc, unsigned type) +{ + inet_addrx *ia = xmalloc(sizeof(*ia)); + + ia->a.ops = &inet_ops; + ia->a.sz = sizeof(struct sockaddr_in); + ia->sin.sin_family = AF_INET; + + /* --- Read the host address part --- */ + + switch (type) { + case ADDR_SRC: + if (sc->t == CTOK_WORD && strcmp(sc->d.buf, "port") == 0) + token(sc); + ia->sin.sin_addr.s_addr = htonl(INADDR_ANY); + break; + case ADDR_DEST: { + struct hostent *h; + dstr d = DSTR_INIT; + conf_name(sc, '.', &d); + if ((h = gethostbyname(d.buf)) == 0) + error(sc, "couldn't resolve Internet address `%s'", d.buf); + memcpy(&ia->sin.sin_addr, h->h_addr, sizeof(struct in_addr)); + dstr_destroy(&d); + if (sc->t == ':') + token(sc); + } break; + } + + /* --- Read the port number --- */ + + { + struct servent *s; + + if (sc->t != CTOK_WORD) + error(sc, "parse error, TCP port expected"); + if (isdigit((unsigned char)sc->d.buf[0])) + ia->sin.sin_port = htons(atoi(sc->d.buf)); + else if ((s = getservbyname(sc->d.buf, "tcp")) == 0) + error(sc, "unknown tcp service `%s'", sc->d.buf); + else + ia->sin.sin_port = s->s_port; + token(sc); + } + + return (&ia->a); +} + +/* --- @destroy@ --- */ + +static void inet_destroy(addr *a) +{ + inet_addrx *ia = (inet_addrx *)a; + DESTROY(ia); +} + +/* --- @print@ --- */ + +static void inet_print(addr *a, unsigned type, dstr *d) +{ + inet_addrx *ia = (inet_addrx *)a; + switch (type) { + case ADDR_SRC: + dstr_putf(d, "inet:%u", (unsigned)ntohs(ia->sin.sin_port)); + break; + case ADDR_DEST: + dstr_putf(d, "inet:%s:%u", + inet_ntoa(ia->sin.sin_addr), + (unsigned)ntohs(ia->sin.sin_port)); + break; + } +} + +/* --- @initopts@ --- */ + +static addr_opts *inet_initopts(void) +{ + inet_opts *io = CREATE(inet_opts); + io->acl = 0; + io->acltail = &io->acl; + return (&io->ao); +} + +/* --- @option@ --- */ + +static int inet_option(scanner *sc, addr_opts *ao) +{ + inet_opts *io = (inet_opts *)ao; + + CONF_BEGIN(sc, "inet", "Internet socket") + + unsigned act; + + /* --- Access control limitations --- */ + + if ((strcmp(sc->d.buf, "allow") == 0 && (act = ACL_ALLOW, 1)) || + (strcmp(sc->d.buf, "deny") == 0 && (act = ACL_DENY, 1))) { + struct hostent *h; + struct netent *n; + struct in_addr a, m; + dstr d = DSTR_INIT; + + /* --- Find the host or network address --- */ + + token(sc); + if (sc->t == CTOK_WORD && strcmp(sc->d.buf, "from") == 0) + token(sc); + conf_name(sc, '.', &d); + if ((n = getnetbyname(d.buf)) != 0) + a.s_addr = htonl(n->n_net); + else if ((h = gethostbyname(d.buf)) == 0) + error(sc, "couldn't resolve address `%s'", d.buf); + else + memcpy(&a, h->h_addr, sizeof(struct in_addr)); + + /* --- Find the netmask, if any --- */ + + if (sc->t != '/') + m.s_addr = ~0ul; + else { + token(sc); + DRESET(&d); + conf_name(sc, '.', &d); + if (strchr(d.buf, '.') == 0) { + int n = atoi(d.buf); + if (n == 0) + m.s_addr = 0; + else + m.s_addr = htonl((~0ul << (32 - n)) & 0xffffffff); + } else { +#ifdef HAVE_INET_ATON + if (!inet_aton(d.buf, &m)) + error(sc, "bad netmask `%s'", d.buf); +#else + m.s_addr = inet_addr(d.buf); +#endif + } + } + dstr_destroy(&d); + + /* --- Add the access control entry --- */ + + acl_add(io ? &io->acltail : 0, act, a, m); + CONF_ACCEPT; + } + + /* --- Anything unrecognized --- */ + + CONF_END; +} + +/* --- @accept@ --- */ + +static reffd *inet_accept(int fd, addr_opts *ao, const char *desc) +{ + inet_opts *io = (inet_opts *)ao; + int nfd; + id_req q; + int lsinsz = sizeof(q.lsin), rsinsz = sizeof(q.rsin); + + /* --- Accept the new connection --- */ + + if ((nfd = accept(fd, (struct sockaddr *)&q.rsin, &rsinsz)) < 0) + return (0); + if (getsockname(nfd, (struct sockaddr *)&q.lsin, &lsinsz)) { + close(nfd); + return (0); + } + q.desc = desc; + q.r = reffd_init(nfd); + + /* --- Find out whether this connection is allowed --- */ + + if (!acl_check(io->acl, q.rsin.sin_addr)) { + q.act = "refused"; + if (!(io->ao.f & ADDRF_NOLOG)) + identify(&q); + REFFD_DEC(q.r); + return (0); + } + + /* --- Everything seems to be OK --- */ + + q.act = "accepted"; + if (!(io->ao.f & ADDRF_NOLOG)) + identify(&q); + return (q.r); +} + +/* --- @freeopts@ --- */ + +static void inet_freeopts(addr_opts *ao) +{ + inet_opts *io = (inet_opts *)ao; + acl_free(io->acl); + DESTROY(ao); +} + +/* --- Ops table --- */ + +addr_ops inet_ops = { + "inet", PF_INET, + inet_read, inet_destroy, inet_print, + inet_initopts, inet_option, inet_accept, inet_freeopts, 0, 0 +}; + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/inet.h b/inet.h new file mode 100644 index 0000000..ed3eed4 --- /dev/null +++ b/inet.h @@ -0,0 +1,60 @@ +/* -*-c-*- + * + * $Id: inet.h,v 1.1 1999/07/26 23:34:11 mdw Exp $ + * + * Protocol specific definitions for IPv4 sockets + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of the `fw' port forwarder. + * + * `fw' is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * `fw' is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with `fw'; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/*----- Revision history --------------------------------------------------* + * + * $Log: inet.h,v $ + * Revision 1.1 1999/07/26 23:34:11 mdw + * New socket address types. + * + */ + +#ifndef INET_H +#define INET_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef ADDR_H +# include "addr.h" +#endif + +/*----- Protocol definition -----------------------------------------------*/ + +extern addr_ops inet_ops; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif diff --git a/un.c b/un.c new file mode 100644 index 0000000..c0a2cc9 --- /dev/null +++ b/un.c @@ -0,0 +1,210 @@ +/* -*-c-*- + * + * $Id: un.c,v 1.1 1999/07/26 23:34:11 mdw Exp $ + * + * Protocol specific definitions for Unix-domain sockets + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of the `fw' port forwarder. + * + * `fw' is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * `fw' is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with `fw'; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/*----- Revision history --------------------------------------------------* + * + * $Log: un.c,v $ + * Revision 1.1 1999/07/26 23:34:11 mdw + * New socket address types. + * + */ + +/*----- Header files ------------------------------------------------------*/ + +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "addr.h" +#include "conf.h" +#include "fattr.h" +#include "fw.h" +#include "reffd.h" +#include "scan.h" +#include "un.h" + +/*----- Data structures ---------------------------------------------------*/ + +typedef struct un_addr { + addr a; + struct sockaddr_un sun; +} un_addr; + +typedef struct un_opts { + addr_opts ao; + fattr f; +} un_opts; + +/*----- Protocol operations -----------------------------------------------*/ + +/* --- @read@ --- */ + +static addr *un_read(scanner *sc, unsigned type) +{ + dstr d = DSTR_INIT; + un_addr *ua; + + conf_name(sc, '/', &d); + ua = xmalloc(sizeof(addr) + + offsetof(struct sockaddr_un, sun_path) + + d.len + 1); + ua->a.ops = &un_ops; + ua->a.sz = offsetof(struct sockaddr_un, sun_path) + d.len + 1; + ua->sun.sun_family = AF_UNIX; + memcpy(ua->sun.sun_path, d.buf, d.len + 1); + dstr_destroy(&d); + return (&ua->a); +} + +/* --- @destroy@ --- */ + +static void un_destroy(addr *a) +{ + un_addr *ua = (un_addr *)a; + free(ua); +} + +/* --- @print@ --- */ + +static void un_print(addr *a, unsigned type, dstr *d) +{ + un_addr *ua = (un_addr *)a; + dstr_puts(d, "unix:"); + dstr_puts(d, ua->sun.sun_path); +} + +/* --- @initopts@ --- */ + +static addr_opts *un_initopts(void) +{ + un_opts *uo = CREATE(un_opts); + uo->f = fattr_global; + return (&uo->ao); +} + +/* --- @option@ --- */ + +static int un_option(scanner *sc, addr_opts *ao) +{ + un_opts *uo = (un_opts *)ao; + CONF_BEGIN(sc, "unix", "Unix domain socket") + + if (fattr_option(sc, uo ? &uo->f : &fattr_global)) + CONF_ACCEPT; + + CONF_END; +} + +/* --- @accept@ --- */ + +static reffd *un_accept(int fd, addr_opts *ao, const char *desc) +{ + int nfd; + un_opts *uo = (un_opts *)ao; + + /* --- Accept the new connection --- */ + + { + char buf[PATH_MAX + sizeof(struct sockaddr)]; + struct sockaddr_un *sun = (struct sockaddr_un *)buf; + int sunsz = sizeof(buf); + + if ((nfd = accept(fd, (struct sockaddr *)sun, &sunsz)) < 0) + return (0); + } + + /* --- Log the connection --- * + * + * It'd be really nice if I could find out who the user is, but I can't in + * anything like a portable way. + */ + + if (!(uo->ao.f & ADDRF_NOLOG)) + fw_log(-1, "[%s] accepted", desc); + return (reffd_init(nfd)); +} + +/* --- @freeopts@ --- */ + +static void un_freeopts(addr_opts *ao) +{ + un_opts *uo = (un_opts *)ao; + DESTROY(uo); +} + +/* --- @bound@ --- */ + +static void un_bound(addr *a, addr_opts *ao) +{ + un_addr *ua = (un_addr *)a; + un_opts *uo = (un_opts *)ao; + if (fattr_apply(ua->sun.sun_path, &uo->f)) { + dstr d = DSTR_INIT; + un_print(a, ADDR_SRC, &d); + fw_log(-1, "[%s] couldn't apply file attributes: %s", + d.buf, strerror(errno)); + dstr_destroy(&d); + } +} + +/* --- @unbind@ --- */ + +static void un_unbind(addr *a) +{ + un_addr *ua = (un_addr *)a; + unlink(ua->sun.sun_path); +} + +/* --- Protocol definition --- */ + +addr_ops un_ops = { + "unix", PF_UNIX, + un_read, un_destroy, un_print, + un_initopts, un_option, un_accept, un_freeopts, un_bound, un_unbind +}; + +/*----- That's all, folks -------------------------------------------------*/ diff --git a/un.h b/un.h new file mode 100644 index 0000000..145313a --- /dev/null +++ b/un.h @@ -0,0 +1,60 @@ +/* -*-c-*- + * + * $Id: un.h,v 1.1 1999/07/26 23:34:11 mdw Exp $ + * + * Protocol specific definitions for Unix-domain sockets + * + * (c) 1999 Straylight/Edgeware + */ + +/*----- Licensing notice --------------------------------------------------* + * + * This file is part of the `fw' port forwarder. + * + * `fw' is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * `fw' is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with `fw'; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/*----- Revision history --------------------------------------------------* + * + * $Log: un.h,v $ + * Revision 1.1 1999/07/26 23:34:11 mdw + * New socket address types. + * + */ + +#ifndef UN_H +#define UN_H + +#ifdef __cplusplus + extern "C" { +#endif + +/*----- Header files ------------------------------------------------------*/ + +#ifndef ADDR_H +# include "addr.h" +#endif + +/*----- Protocol defintions -----------------------------------------------*/ + +extern addr_ops un_ops; + +/*----- That's all, folks -------------------------------------------------*/ + +#ifdef __cplusplus + } +#endif + +#endif -- 2.11.0