Merge remote-tracking branch 'origin/inetd-plugins'

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This commit is contained in:
Joachim Nilsson committed 2016-07-18 20:25:36 +02:00
commit 7b00969f6c
12 files changed
+473 -49

No files matched your search

+49 -13
View File
@@ -73,8 +73,11 @@ interface, reducing the need for a full blown firewall.
Built-in optional inetd services: Built-in optional inetd services:
- time (rdate) RFC862 - echo RFC862
- echo RFC868 - chargen RFC864
- daytime RFC867
- discard RFC863
- time (rdate) RFC868
**Runlevels** **Runlevels**
@@ -437,7 +440,8 @@ Inetd
A built-in *Internet Super Server* support was added in Finit v1.12 and A built-in *Internet Super Server* support was added in Finit v1.12 and
v1.13, along with an internal `time` inetd service, RFC 868 (rdate). v1.13, along with an internal `time` inetd service, RFC 868 (rdate).
The latter is supplied as a plugin to illustrate how simple it is to The latter is supplied as a plugin to illustrate how simple it is to
extend finit with more internal inetd services. extend finit with more internal inetd services. Today more built-in
services are available.
> Please note, not all UNIX daemons are prepared to run as inetd services. > Please note, not all UNIX daemons are prepared to run as inetd services.
> In the example below `sshd` also need the command line argument `-i`. > In the example below `sshd` also need the command line argument `-i`.
@@ -474,28 +478,40 @@ default port. To run ssh on port 222, and all others on port 22:
Compared to Finit v1.12 you must *explicitly deny* access from `eth0`! Compared to Finit v1.12 you must *explicitly deny* access from `eth0`!
To protect against looping attacks, the inetd server will refuse UDP
service if the reply port corresponds to any internal service. Similar
to how the FreeBSD inetd operates.
**Internal Services** **Internal Services**
The original `inetd` had a few standard services built-in: Like the original `inetd`, Finit has a few standard services built-in.
They are realized as plugins to provide a simple means of testing the
inetd functionality stand-alone. But this also provides both a useful
network testing/availability, as well as a rudimentary time server for
`rdate` clients.
- time
- echo - echo
- chargen - chargen
- daytime
- discard - discard
- time
Finit currently supports the `time` and `echo` services. Both of which For security reasons they are all disabled by default and have to be
are realized as plugins to provide a simple means of testing the inetd enabled with both the `configure` script and a special `inetd` stanza in
functionality stand-alone. But this also provides both a useful network the `finit.conf` or `finit.d/*.conf` like this:
testing/availability and a rudimentary time server for rdate clients.
Internal inetd services are set up as follows:
```shell ```shell
inetd time/udp wait [2345] internal
inetd time/tcp nowait [2345] internal
inetd echo/udp wait [2345] internal inetd echo/udp wait [2345] internal
inetd echo/tcp nowait [2345] internal inetd echo/tcp nowait [2345] internal
inetd chargen/udp wait [2345] internal
inetd chargen/tcp nowait [2345] internal
inetd daytime/udp wait [2345] internal
inetd daytime/tcp nowait [2345] internal
inetd discard/udp wait [2345] internal
inetd discard/tcp nowait [2345] internal
inetd time/udp wait [2345] internal
inetd time/tcp nowait [2345] internal
``` ```
Then call `rdate` from a remote machine (or use localhost): Then call `rdate` from a remote machine (or use localhost):
@@ -512,6 +528,20 @@ Or `echoping` to reach the echo service:
echoping -uv <IP> echoping -uv <IP>
``` ```
Or `echoping -d` to reach the discard service:
```shell
echoping -dv <IP>
echoping -duv <IP>
```
Or `echoping -c` to reach the chargen service:
```shell
echoping -cv <IP>
echoping -cuv <IP>
```
If you use `time/udp` you must use the standard rdate implementation and If you use `time/udp` you must use the standard rdate implementation and
then call it with `rdate -up` to connect using UDP. Without the `-p` then call it with `rdate -up` to connect using UDP. Without the `-p`
argument rdate will try to set the system clock. Please note that rdate argument rdate will try to set the system clock. Please note that rdate
@@ -554,6 +584,12 @@ For your convenience a set of *optional* plugins are available:
* *echo.so*: RFC 862 plugin. Start as inetd service, like time below. * *echo.so*: RFC 862 plugin. Start as inetd service, like time below.
* *chargen.so*: RFC 864 plugin. Start as inetd service, like time below.
* *daytime.so*: RFC 867 plugin. Start as inetd service, like time below.
* *discard.so*: RFC 863 plugin. Start as inetd service, like time below.
* *hwclock.so*: Restore and save system clock from/to RTC on * *hwclock.so*: Restore and save system clock from/to RTC on
startup/shutdown. startup/shutdown.
+11 -8
View File
@@ -53,14 +53,17 @@ AC_ARG_ENABLE(quiet,
# Check for extra plugins to enable # Check for extra plugins to enable
enable_all_plugins=auto enable_all_plugins=auto
AC_PLUGIN([alsa-utils], [no], [Save and restore ALSA sound settings using alsactl]) AC_PLUGIN([alsa-utils], [no], [Save and restore ALSA sound settings using alsactl])
AC_PLUGIN([dbus], [no], [Setup and start system message bus, D-Bus]) AC_PLUGIN([dbus], [no], [Setup and start system message bus, D-Bus])
AC_PLUGIN([inetd-echo], [no], [Inetd plugin: echo server, RFC862]) AC_PLUGIN([inetd-echo], [no], [Inetd plugin: echo server, RFC862])
AC_PLUGIN([inetd-time], [no], [Inetd plugin: time (rdate) server, RFC868]) AC_PLUGIN([inetd-chargen], [no], [Inetd plugin: character generator, RFC864])
AC_PLUGIN([lost], [no], [Example HOOK_SVC_LOST plugin, very noisy as-is!]) AC_PLUGIN([inetd-daytime], [no], [Inetd plugin: daytime server, RFC867])
AC_PLUGIN([resolvconf], [no], [Setup necessary files for resolvconf]) AC_PLUGIN([inetd-discard], [no], [Inetd plugin: discard server, RFC863])
AC_PLUGIN([x11-common], [no], [Console setup (for X)]) AC_PLUGIN([inetd-time], [no], [Inetd plugin: time (rdate) server, RFC868])
AC_PLUGIN([netlink], [yes], [Basic netlink plugin for IFUP/IFDN and GW events. Can be replaced with externally built plugin that links with libnl or similar.]) AC_PLUGIN([lost], [no], [Example HOOK_SVC_LOST plugin, very noisy as-is!])
AC_PLUGIN([resolvconf], [no], [Setup necessary files for resolvconf])
AC_PLUGIN([x11-common], [no], [Console setup (for X)])
AC_PLUGIN([netlink], [yes], [Basic netlink plugin for IFUP/IFDN and GW events. Can be replaced with externally built plugin that links with libnl or similar.])
# Check for extra arguments or packages # Check for extra arguments or packages
AC_ARG_WITH(heading, AC_ARG_WITH(heading,
-1
View File
@@ -38,7 +38,6 @@
#include "service.h" #include "service.h"
#include "sig.h" #include "sig.h"
#include "tty.h" #include "tty.h"
#include "inetd.h"
#include "sm.h" #include "sm.h"
int debug = 0; int debug = 0;
+28 -1
View File
@@ -107,8 +107,8 @@ static int inetd_stream_peek(int sd, char *ifname)
static int get_stdin(svc_t *svc) static int get_stdin(svc_t *svc)
{ {
char ifname[IF_NAMESIZE] = "UNKNOWN";
int stdin = svc->inetd.watcher.fd; int stdin = svc->inetd.watcher.fd;
char ifname[IF_NAMESIZE] = "UNKNOWN";
if (svc->inetd.type == SOCK_STREAM) { if (svc->inetd.type == SOCK_STREAM) {
/* Open new client socket from server socket */ /* Open new client socket from server socket */
@@ -189,6 +189,33 @@ static void socket_cb(uev_t *UNUSED(w), void *arg, int UNUSED(events))
service_step(task); service_step(task);
} }
/*
* Refuse service if the request specifies a reply port corresponding to any internal service.
* This is done as a defense against looping attacks; the remote IP address is logged.
* http://www.freebsd.org/cgi/man.cgi?inetd(8)
* https://svnweb.freebsd.org/base/head/usr.sbin/inetd/inetd.c?revision=298909&view=markup#l2094
*/
int inetd_check_loop(struct sockaddr *sa, socklen_t len, char *name)
{
svc_t *svc;
char pname[NI_MAXHOST];
for (svc = svc_inetd_iterator(1); svc; svc = svc_inetd_iterator(0)) {
inetd_t *i = &svc->inetd;
if (!i->builtin || i->type != SOCK_DGRAM)
continue;
if (((const struct sockaddr_in *)sa)->sin_port == i->port) {
getnameinfo(sa, len, pname, sizeof(pname), NULL, 0, NI_NUMERICHOST);
FLOG_WARN("%s/%s:%s/%s loop request REFUSED from %s", i->name, "UDP", name, "UDP", pname);
return 1;
}
}
return 0;
}
/* Launch Inet socket for service. /* Launch Inet socket for service.
* TODO: Add filtering ALLOW/DENY per interface. * TODO: Add filtering ALLOW/DENY per interface.
*/ */
+3
View File
@@ -46,6 +46,7 @@ typedef struct {
int proto; int proto;
int port; int port;
int forking; int forking;
int builtin; /* Set by built-in inetd services only */
int next_id; /* Next child job's id */ int next_id; /* Next child job's id */
char name[10]; char name[10];
int (*cmd)(int type); /* internal inetd service, like 'time' */ int (*cmd)(int type); /* internal inetd service, like 'time' */
@@ -53,6 +54,8 @@ typedef struct {
TAILQ_HEAD(, inetd_filter) filters; TAILQ_HEAD(, inetd_filter) filters;
} inetd_t; } inetd_t;
int inetd_check_loop (struct sockaddr *sa, socklen_t len, char *name);
int inetd_start (inetd_t *inetd); int inetd_start (inetd_t *inetd);
void inetd_stop (inetd_t *inetd); void inetd_stop (inetd_t *inetd);
+28
View File
@@ -15,13 +15,27 @@ if BUILD_DBUS_PLUGIN
libplug_la_SOURCES += dbus.c libplug_la_SOURCES += dbus.c
endif endif
if INETD
if BUILD_INETD_ECHO_PLUGIN if BUILD_INETD_ECHO_PLUGIN
libplug_la_SOURCES += echo.c libplug_la_SOURCES += echo.c
endif endif
if BUILD_INETD_CHARGEN_PLUGIN
libplug_la_SOURCES += chargen.c
endif
if BUILD_INETD_DAYTIME_PLUGIN
libplug_la_SOURCES += daytime.c
endif
if BUILD_INETD_DISCARD_PLUGIN
libplug_la_SOURCES += discard.c
endif
if BUILD_INETD_TIME_PLUGIN if BUILD_INETD_TIME_PLUGIN
libplug_la_SOURCES += time.c libplug_la_SOURCES += time.c
endif endif
endif
if BUILD_LOST_PLUGIN if BUILD_LOST_PLUGIN
libplug_la_SOURCES += lost.c libplug_la_SOURCES += lost.c
@@ -46,13 +60,27 @@ if BUILD_DBUS_PLUGIN
pkglib_LTLIBRARIES += dbus.la pkglib_LTLIBRARIES += dbus.la
endif endif
if INETD
if BUILD_INETD_ECHO_PLUGIN if BUILD_INETD_ECHO_PLUGIN
pkglib_LTLIBRARIES += echo.la pkglib_LTLIBRARIES += echo.la
endif endif
if BUILD_INETD_CHARGEN_PLUGIN
pkglib_LTLIBRARIES += chargen.la
endif
if BUILD_INETD_DAYTIME_PLUGIN
pkglib_LTLIBRARIES += daytime.la
endif
if BUILD_INETD_DISCARD_PLUGIN
pkglib_LTLIBRARIES += discard.la
endif
if BUILD_INETD_TIME_PLUGIN if BUILD_INETD_TIME_PLUGIN
pkglib_LTLIBRARIES += time.la pkglib_LTLIBRARIES += time.la
endif endif
endif
if BUILD_LOST_PLUGIN if BUILD_LOST_PLUGIN
pkglib_LTLIBRARIES += lost.la pkglib_LTLIBRARIES += lost.la
+114
View File
@@ -0,0 +1,114 @@
/* Optional inetd plugin for the Character Generator Protocol, RFC 864
*
* Copyright (c) 2016 Joachim Nilsson <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <arpa/inet.h>
#include <unistd.h> /* STDIN_FILENO */
#include <sys/socket.h>
#include "../plugin.h"
#define NAME "chargen"
#define PATTERN "!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~ "
static char *generator(char *buf, size_t len)
{
size_t num;
static size_t pos = 0;
const char pattern[] = PATTERN;
len = 72;
if (pos + len > sizeof(pattern)) {
num = sizeof(pattern) - pos;
len -= num;
} else {
num = 72;
len = 0;
}
strncpy(&buf[0], &pattern[pos], num--);
if (len++)
strncpy(&buf[num], pattern, len);
strcat(buf, "\r\n");
if (++pos >= sizeof(pattern) - 1)
pos = 0;
return buf;
}
static int recv_peer(int sd, char *buf, ssize_t len, struct sockaddr *sa, socklen_t *sa_len)
{
len = recvfrom(sd, buf, len, MSG_DONTWAIT, sa, sa_len);
if (-1 == len)
return -1; /* On error, close connection. */
if (inetd_check_loop(sa, *sa_len, NAME))
return -1;
return 0;
}
static int send_peer(int sd, char *buf, ssize_t len, struct sockaddr *sa, socklen_t sa_len)
{
char *pattern = generator(buf, len);
return sendto(sd, pattern, strlen(pattern), MSG_DONTWAIT, sa, sa_len);
}
static int cb(int type)
{
int sd = STDIN_FILENO;
ssize_t len;
char buf[BUFSIZ];
struct sockaddr_storage sa;
socklen_t sa_len = sizeof(sa);
if (recv_peer(sd, buf, sizeof(buf), (struct sockaddr *)&sa, &sa_len))
return -1;
return send_peer(sd, buf, sizeof(buf), (struct sockaddr *)&sa, sa_len);
}
static plugin_t plugin = {
.name = NAME, /* Must match the inetd /etc/services entry */
.inetd = {
.cmd = cb
},
};
PLUGIN_INIT(plugin_init)
{
plugin_register(&plugin);
}
PLUGIN_EXIT(plugin_exit)
{
plugin_unregister(&plugin);
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+102
View File
@@ -0,0 +1,102 @@
/* Optional inetd plugin for Daytime Protocol, RFC 867
*
* Copyright (c) 2016 Joachim Nilsson <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <arpa/inet.h>
#include <time.h>
#include <unistd.h> /* STDIN_FILENO */
#include <sys/socket.h>
#include "../plugin.h"
#define NAME "daytime"
static char *daytime(char *buf, size_t len)
{
time_t t;
struct tm *tmp;
t = time(NULL);
tmp = localtime(&t);
memset(buf, 0, len);
strftime(buf, len, "%a, %B %d, %Y %T-%Z", tmp);
return buf;
}
static int recv_peer(int sd, char *buf, ssize_t len, struct sockaddr *sa, socklen_t *sa_len)
{
len = recvfrom(sd, buf, sizeof(buf), MSG_DONTWAIT, sa, sa_len);
if (-1 == len)
return -1; /* On error, close connection. */
if (inetd_check_loop(sa, *sa_len, NAME))
return -1;
return 0;
}
static int send_peer(int sd, char *buf, ssize_t len, struct sockaddr *sa, socklen_t sa_len)
{
char *now = daytime(buf, len);
return sendto(sd, now, strlen(now), MSG_DONTWAIT, sa, sa_len);
}
static int cb(int type)
{
int sd = STDIN_FILENO;
char buf[BUFSIZ];
struct sockaddr_storage sa;
socklen_t sa_len = sizeof(sa);
if (recv_peer(sd, buf, sizeof(buf), (struct sockaddr *)&sa, &sa_len))
return -1;
return send_peer(sd, buf, sizeof(buf), (struct sockaddr *)&sa, sa_len);
}
static plugin_t plugin = {
.name = NAME, /* Must match the inetd /etc/services entry */
.inetd = {
.cmd = cb
}
};
PLUGIN_INIT(plugin_init)
{
plugin_register(&plugin);
}
PLUGIN_EXIT(plugin_exit)
{
plugin_unregister(&plugin);
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+67
View File
@@ -0,0 +1,67 @@
/* Optional inetd plugin for the Discard Protocol, RFC 863
*
* Copyright (c) 2016 Joachim Nilsson <troglobit@gmail.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <arpa/inet.h>
#include <unistd.h> /* STDIN_FILENO */
#include <sys/socket.h>
#include "../plugin.h"
static int cb(int type)
{
int sd = STDIN_FILENO;
char buf[BUFSIZ];
ssize_t len;
struct sockaddr_storage sa;
socklen_t sa_len = sizeof(sa);
len = recvfrom(sd, buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr *)&sa, &sa_len);
if (-1 == len)
return -1; /* On error, close connection. */
return 0;
}
static plugin_t plugin = {
.name = "discard", /* Must match the inetd /etc/services entry */
.inetd = {
.cmd = cb
},
};
PLUGIN_INIT(plugin_init)
{
plugin_register(&plugin);
}
PLUGIN_EXIT(plugin_exit)
{
plugin_unregister(&plugin);
}
/**
* Local Variables:
* indent-tabs-mode: t
* c-file-style: "linux"
* End:
*/
+19 -5
View File
@@ -1,4 +1,4 @@
/* Optional inetd plugin for the echo protocol RFC 862 /* Optional inetd plugin for the Echo Protocol, RFC 862
* *
* Copyright (c) 2016 Joachim Nilsson <troglobit@gmail.com> * Copyright (c) 2016 Joachim Nilsson <troglobit@gmail.com>
* *
@@ -27,7 +27,21 @@
#include "../plugin.h" #include "../plugin.h"
static int echo_cb(int type) #define NAME "echo"
static int recv_peer(int sd, char *buf, ssize_t len, struct sockaddr *sa, socklen_t *sa_len)
{
len = recvfrom(sd, buf, sizeof(buf), MSG_DONTWAIT, sa, sa_len);
if (-1 == len)
return -1; /* On error, close connection. */
if (inetd_check_loop(sa, *sa_len, NAME))
return -1;
return len;
}
static int cb(int type)
{ {
int sd = STDIN_FILENO; int sd = STDIN_FILENO;
char buf[BUFSIZ]; char buf[BUFSIZ];
@@ -35,7 +49,7 @@ static int echo_cb(int type)
struct sockaddr_storage sa; struct sockaddr_storage sa;
socklen_t sa_len = sizeof(sa); socklen_t sa_len = sizeof(sa);
len = recvfrom(sd, buf, sizeof(buf), MSG_DONTWAIT, (struct sockaddr *)&sa, &sa_len); len = recv_peer(sd, buf, sizeof(buf), (struct sockaddr *)&sa, &sa_len);
if (-1 == len) if (-1 == len)
return -1; /* On error, close connection. */ return -1; /* On error, close connection. */
@@ -43,9 +57,9 @@ static int echo_cb(int type)
} }
static plugin_t plugin = { static plugin_t plugin = {
.name = "echo", /* Must match the inetd /etc/services entry */ .name = NAME, /* Must match the inetd /etc/services entry */
.inetd = { .inetd = {
.cmd = echo_cb .cmd = cb
}, },
}; };
+51 -21
View File
@@ -1,4 +1,4 @@
/* Optional inetd plugin for time (rdate) protocol RFC 868 /* Optional inetd plugin for Time Protocol (rdate), RFC 868
* *
* Copyright (c) 2015 Joachim Nilsson <troglobit@gmail.com> * Copyright (c) 2015 Joachim Nilsson <troglobit@gmail.com>
* *
@@ -28,43 +28,73 @@
#include "../plugin.h" #include "../plugin.h"
#define NAME "time"
/* UNIX epoch starts midnight, 1st Jan, 1970 */ /* UNIX epoch starts midnight, 1st Jan, 1970 */
#define EPOCH_OFFSET 2208988800ULL #define EPOCH_OFFSET 2208988800ULL
/* Return number of seconds since midnight, 1st Jan, 1900 */ /* Return number of seconds since midnight, 1st Jan, 1900 */
static int rfc868(int type) static char *rfctime(char *buf, size_t *len)
{ {
int sd = STDIN_FILENO;
time_t now; time_t now;
struct sockaddr_storage sa;
socklen_t sa_len = sizeof(sa);
if (SOCK_DGRAM == type) {
int dummy;
/* Read empty datagram in UDP mode before sending reply. */
if (-1 == recvfrom(sd, &dummy, sizeof(dummy), MSG_DONTWAIT, (struct sockaddr *)&sa, &sa_len))
return -1; /* On error, close connection. */
}
now = time(NULL); now = time(NULL);
if ((time_t)-1 == now) if ((time_t)-1 == now)
return -1; /* On error, close connection. */ return NULL;
/* Account for UNIX epoch offset */ /*
* Account for UNIX epoch offset, and
* convert to network byte order
*/
now += EPOCH_OFFSET; now += EPOCH_OFFSET;
now = htonl(now);
/* Convert to network byte order, not explicitly stated in RFC */ *len = sizeof(now);
now = htonl(now); memcpy(buf, &now, *len);
/* Send reply, ignore error, simply close connection. */ return buf;
return sendto(sd, &now, sizeof(now), MSG_DONTWAIT, (struct sockaddr *)&sa, sa_len); }
static int recv_peer(int sd, char *buf, ssize_t len, struct sockaddr *sa, socklen_t *sa_len)
{
len = recvfrom(sd, buf, sizeof(buf), MSG_DONTWAIT, sa, sa_len);
if (-1 == len)
return -1; /* On error, close connection. */
if (inetd_check_loop(sa, *sa_len, NAME))
return -1;
return 0;
}
static int send_peer(int sd, char *buf, ssize_t len, struct sockaddr *sa, socklen_t sa_len)
{
char *now;
now = rfctime(buf, &len);
if (!now)
return -1; /* On error, close connection. */
return sendto(sd, now, len, MSG_DONTWAIT, sa, sa_len);
}
static int cb(int type)
{
int sd = STDIN_FILENO;
char buf[BUFSIZ];
struct sockaddr_storage sa;
socklen_t sa_len = sizeof(sa);
if (recv_peer(sd, buf, sizeof(buf), (struct sockaddr *)&sa, &sa_len))
return -1; /* On error, close connection. */
return send_peer(sd, buf, sizeof(buf), (struct sockaddr *)&sa, sa_len);
} }
static plugin_t plugin = { static plugin_t plugin = {
.name = "time", /* Must match the inetd /etc/services entry */ .name = NAME, /* Must match the inetd /etc/services entry */
.inetd = { .inetd = {
.cmd = rfc868 .cmd = cb
} }
}; };
+1
View File
@@ -589,6 +589,7 @@ recreate:
if (plugin) { if (plugin) {
/* Internal plugin provides this service */ /* Internal plugin provides this service */
svc->inetd.cmd = plugin->inetd.cmd; svc->inetd.cmd = plugin->inetd.cmd;
svc->inetd.builtin = 1;
} else { } else {
strlcpy(svc->args[i++], cmd, sizeof(svc->args[0])); strlcpy(svc->args[i++], cmd, sizeof(svc->args[0]));
while ((cmd = strtok(NULL, " "))) while ((cmd = strtok(NULL, " ")))