diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-11-24 21:19:56 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2009-11-24 21:19:56 +0200 |
commit | 534098c3d35f36ab9d333fb0ee800c7ffaf0dcbd (patch) | |
tree | 5e8ed3f413000e73f8ff00286e1615f2408e9c37 /src/inetd-bi.c | |
parent | a7779d56bb758157e122a420a56f2d7b4475e554 (diff) | |
download | pies-534098c3d35f36ab9d333fb0ee800c7ffaf0dcbd.tar.gz pies-534098c3d35f36ab9d333fb0ee800c7ffaf0dcbd.tar.bz2 |
Implement inetd builtin services.
* src/inetd-bi.c: New file.
* src/Makefile.am (pies_SOURCES): Add inetd-bi.c.
* src/pies.h (struct component): New member `builtin'.
(qotdfile): New extern.
(inetd_builtin): New struct.
(inetd_builtin_lookup): New proto.
* src/progman.c (prog_start): Handle internal
services.
* src/inetd.c (inetd_conf_file): Handle internal
services.
* src/pies.c (qotdfile): New global.
(pies_keywords): New keyword "qotd-file".
Diffstat (limited to 'src/inetd-bi.c')
-rw-r--r-- | src/inetd-bi.c | 305 |
1 files changed, 305 insertions, 0 deletions
diff --git a/src/inetd-bi.c b/src/inetd-bi.c new file mode 100644 index 0000000..f86f373 --- /dev/null +++ b/src/inetd-bi.c @@ -0,0 +1,305 @@ +/* This file is part of GNU Pies. + Copyright (C) 2009 Sergey Poznyakoff + + GNU Pies 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 3, or (at your option) + any later version. + + GNU Pies 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 GNU Pies. If not, see <http://www.gnu.org/licenses/>. */ + +#include "pies.h" +#include <netdb.h> + +#define INTBUFSIZE 8192 + +/* Echo protocol, RFC 862 */ +void +echo_stream (int fd) +{ + int rc; + char buffer[INTBUFSIZE]; + + while ((rc = read (fd, buffer, sizeof buffer)) > 0 + && write (fd, buffer, rc) > 0) + ; +} + +void +echo_dg (int fd) +{ + int rc; + char buffer[INTBUFSIZE]; + struct sockaddr sa; + socklen_t size = sizeof sa; + + rc = recvfrom (fd, buffer, sizeof buffer, 0, &sa, &size); + if (rc < 0) + return; + sendto (fd, buffer, rc, 0, &sa, sizeof sa); +} + +/* Discard protocol, RFC 863 */ +void +discard_stream (int fd) +{ + int rc; + char buffer[INTBUFSIZE]; + + while (1) + { + while ((rc = read (fd, buffer, sizeof buffer)) > 0) + ; + if (rc == 0 || errno != EINTR) + break; + } +} + +void +discard_dg (int fd) +{ + char buffer[INTBUFSIZE]; + read (fd, buffer, sizeof buffer); +} + + +/* Time Protocol, RFC 868 */ + +/* Return a machine readable date and time as seconds since + midnight, Jan 1, 1900. */ + +#define SEVENTY_YEARS ((unsigned long)25567 * 24 * 60 * 60) + +unsigned long +time_since_1900 (void) +{ + struct timeval tv; + + if (gettimeofday (&tv, NULL) < 0) + { + logmsg (LOG_ERR, "gettimeofday: %s", strerror (errno)); + return 0; + } + return htonl ((long) (tv.tv_sec + SEVENTY_YEARS)); +} + +void +time_stream (int fd) +{ + unsigned long result = time_since_1900 (); + write (fd, (char *) &result, sizeof result); +} + +void +time_dg (int fd) +{ + unsigned long result; + struct sockaddr sa; + socklen_t size = sizeof sa; + + if (recvfrom (fd, (char *) &result, sizeof result, 0, &sa, &size) < 0) + return; + result = time_since_1900 (); + sendto (fd, (char *) &result, sizeof result, 0, &sa, sizeof sa); +} + +/* Daytime Protocol, RFC 867 */ +void +daytime_stream (int fd) +{ + char buffer[27]; + time_t now; + + time (&now); + sprintf (buffer, "%.24s\r\n", ctime (&now)); + write (fd, buffer, strlen (buffer)); +} + +void +daytime_dg (int fd) +{ + char buffer[27]; + time_t now; + struct sockaddr sa; + socklen_t size = sizeof sa; + + time (&now); + + if (recvfrom (fd, buffer, sizeof buffer, 0, &sa, &size) < 0) + return; + sprintf (buffer, "%.24s\r\n", ctime (&now)); + sendto (fd, buffer, strlen (buffer), 0, &sa, sizeof sa); +} + +/* Character Generator Protocol, RFC 864 */ + +#define LINESIZ 72 + +static void +chargen_next_line (char *text) +{ + static int ch = 0; + int i, c; + + do + ch = (ch + 1) % 128; + while (!c_isprint (ch)); + + for (i = 0, c = ch; i < LINESIZ; ) + { + if (c_isprint (c)) + text[i++] = c; + c = (c + 1) % 128; + } +} + +void +chargen_stream (int fd) +{ + char text[LINESIZ + 2]; + + text[LINESIZ] = '\r'; + text[LINESIZ + 1] = '\n'; + + while (1) + { + chargen_next_line (text); + if (write (fd, text, sizeof text) != sizeof text) + break; + } +} + +void +chargen_dg (int fd) +{ + struct sockaddr sa; + socklen_t size = sizeof sa; + char text[LINESIZ + 2]; + + if (recvfrom (fd, text, sizeof text, 0, &sa, &size) < 0) + return; + text[LINESIZ] = '\r'; + text[LINESIZ + 1] = '\n'; + chargen_next_line (text); + sendto (fd, text, sizeof text, 0, &sa, sizeof sa); +} + + +/* Quote of the Day Protocol, RFC 865 */ + +#define QOTD_MAX 512 +#define QOTD_DEF "Quote of the Day\r\n" + +static size_t +trnl (char *text, size_t size) +{ + size_t off = size; + + for (; off > 0; off--) + if (text[off] == '\n') + { + if (text[off-1] == '\r') + off--; + else + { + if (size == QOTD_MAX) + size--; + memmove (text + off + 1, text + off, size - off); + text[off] = '\r'; + size++; + } + } + return size; +} + +size_t +qotd_read (char *text) +{ + ssize_t rc; + int fd = open (qotdfile, O_RDONLY); + if (fd == -1) + { + logmsg (LOG_ERR, _("cannot open %s: %s"), qotdfile, strerror (errno)); + strncpy (text, QOTD_DEF, QOTD_MAX); + rc = QOTD_MAX; + } + else + { + rc = read (fd, text, QOTD_MAX); + if (rc >= 0) + rc = trnl (text, rc); + else + { + logmsg (LOG_ERR, _("error reading %s: %s"), + qotdfile, strerror (errno)); + strncpy (text, QOTD_DEF, QOTD_MAX); + rc = QOTD_MAX; + } + } + close (fd); + return rc; +} + +void +qotd_stream (int fd) +{ + char text[QOTD_MAX]; + size_t len = qotd_read (text); + write (fd, text, len); +} + +void +qotd_dg (int fd) +{ + char text[QOTD_MAX]; + struct sockaddr sa; + socklen_t size = sizeof sa; + size_t len; + if (recvfrom (fd, text, sizeof text, 0, &sa, &size) < 0) + return; + len = qotd_read (text); + sendto (fd, text, len, 0, &sa, sizeof sa); +} + + +struct inetd_builtin inetd_builtin_tab[] = { + /* Echo received data */ + {"echo", SOCK_STREAM, 0, 0, echo_stream}, + {"echo", SOCK_DGRAM, 1, 0, echo_dg}, + /* Internet /dev/null */ + {"discard", SOCK_STREAM, 0, 0, discard_stream}, + {"discard", SOCK_DGRAM, 1, 0, discard_dg}, + /* Return 32 bit time since 1900 */ + {"time", SOCK_STREAM, 1, 0, time_stream}, + {"time", SOCK_DGRAM, 1, 0, time_dg}, + /* Return human-readable time */ + {"daytime", SOCK_STREAM, 1, 0, daytime_stream}, + {"daytime", SOCK_DGRAM, 1, 0, daytime_dg}, + /* Character generator */ + {"chargen", SOCK_STREAM, 0, 0, chargen_stream}, + {"chargen", SOCK_DGRAM, 1, 0, chargen_dg}, + /* Quote of the Day */ + {"qotd", SOCK_STREAM, 0, 0, qotd_stream}, + {"qotd", SOCK_DGRAM, 1, 0, qotd_dg}, +#if 0 + {"tcpmux", SOCK_STREAM, 0, 0, tcpmux}, +#endif + {NULL, 0, 0, 0, NULL} +}; + +struct inetd_builtin * +inetd_builtin_lookup (const char *service, int socktype) +{ + struct inetd_builtin *bp; + + for (bp = inetd_builtin_tab; bp->service; bp++) + if (bp->socktype == socktype && strcmp (bp->service, service) == 0) + return bp; + return NULL; +} |