File ucspi-tcp-0.88-systemd.patch of Package ucspi-tcp
(C) 2012 Peter Conrad <conrad@quisquis.de>
Licensed under the terms and conditions of the GNU General Public License
(version 2). See http://www.gnu.org/licenses/old-licenses/gpl-2.0 .
diff -rNU3 ucspi-tcp-0.88/Makefile ucspi-tcp-0.88.systemd/Makefile
--- ucspi-tcp-0.88/Makefile 2012-02-22 10:22:24.000000000 +0100
+++ ucspi-tcp-0.88.systemd/Makefile 2012-02-21 16:34:21.000000000 +0100
@@ -566,6 +566,16 @@
compile subgetopt.c subgetopt.h
./compile subgetopt.c
+systemd.h: \
+trysystemd.c choose compile load systemd.h1 systemd.h2
+ cp /dev/null systemd.h
+ ./choose cL trysystemd systemd.h1 systemd.h2 > systemd.h
+
+systemd.lib: \
+trysystemd.c choose compile load systemd.h1 systemd.h2
+ cp /dev/null systemd.lib
+ ./choose cL trysystemd systemd.lib.1 systemd.lib.2 > systemd.lib
+
systype: \
find-systype.sh conf-cc conf-ld trycpp.c x86cpuid.c
( cat warn-auto.sh; \
@@ -651,9 +661,9 @@
tcpserver: \
load tcpserver.o rules.o remoteinfo.o timeoutconn.o cdb.a \
-time.a unix.a byte.a socket.lib
+time.a unix.a byte.a socket.lib systemd.lib
./load tcpserver rules.o remoteinfo.o timeoutconn.o cdb.a \
- time.a unix.a byte.a `cat socket.lib`
+ time.a unix.a byte.a `cat socket.lib systemd.lib`
tcpserver.o: \
compile tcpserver.c uint16.h str.h byte.h fmt.h scan.h ip4.h fd.h \
@@ -661,7 +671,7 @@
alloc.h buffer.h error.h strerr.h sgetopt.h subgetopt.h pathexec.h \
socket.h uint16.h ndelay.h remoteinfo.h stralloc.h uint16.h rules.h \
stralloc.h sig.h dns.h stralloc.h iopause.h taia.h tai.h uint64.h \
-taia.h
+taia.h systemd.h
./compile tcpserver.c
time.a: \
diff -rNU3 ucspi-tcp-0.88/systemd.h1 ucspi-tcp-0.88.systemd/systemd.h1
--- ucspi-tcp-0.88/systemd.h1 1970-01-01 01:00:00.000000000 +0100
+++ ucspi-tcp-0.88.systemd/systemd.h1 2012-02-21 16:32:03.000000000 +0100
@@ -0,0 +1 @@
+
diff -rNU3 ucspi-tcp-0.88/systemd.h2 ucspi-tcp-0.88.systemd/systemd.h2
--- ucspi-tcp-0.88/systemd.h2 1970-01-01 01:00:00.000000000 +0100
+++ ucspi-tcp-0.88.systemd/systemd.h2 2012-02-21 16:32:03.000000000 +0100
@@ -0,0 +1,9 @@
+#ifndef _MY_SYSTEMD_H_
+#define _MY_SYSTEMD_H_
+
+#include <systemd/sd-daemon.h>
+#include <sys/socket.h>
+
+#define HAVE_SYSTEMD
+
+#endif
diff -rNU3 ucspi-tcp-0.88/systemd.lib.1 ucspi-tcp-0.88.systemd/systemd.lib.1
--- ucspi-tcp-0.88/systemd.lib.1 1970-01-01 01:00:00.000000000 +0100
+++ ucspi-tcp-0.88.systemd/systemd.lib.1 2012-02-21 16:32:03.000000000 +0100
@@ -0,0 +1 @@
+
diff -rNU3 ucspi-tcp-0.88/systemd.lib.2 ucspi-tcp-0.88.systemd/systemd.lib.2
--- ucspi-tcp-0.88/systemd.lib.2 1970-01-01 01:00:00.000000000 +0100
+++ ucspi-tcp-0.88.systemd/systemd.lib.2 2012-02-21 16:32:03.000000000 +0100
@@ -0,0 +1 @@
+-lsystemd-daemon
diff -rNU3 ucspi-tcp-0.88/TARGETS ucspi-tcp-0.88.systemd/TARGETS
--- ucspi-tcp-0.88/TARGETS 2000-03-18 16:18:42.000000000 +0100
+++ ucspi-tcp-0.88.systemd/TARGETS 2012-02-21 16:33:30.000000000 +0100
@@ -169,3 +169,6 @@
it
setup
check
+trysystemd
+systemd.h
+systemd.lib
diff -rNU3 ucspi-tcp-0.88/tcpserver.c ucspi-tcp-0.88.systemd/tcpserver.c
--- ucspi-tcp-0.88/tcpserver.c 2012-02-22 10:22:24.000000000 +0100
+++ ucspi-tcp-0.88.systemd/tcpserver.c 2012-02-22 10:36:56.000000000 +0100
@@ -37,7 +37,13 @@
#include "rules.h"
#include "sig.h"
#include "dns.h"
+#include "systemd.h"
+#ifndef HAVE_SYSTEMD
+#define SD_CRIT ""
+#define SD_WARNING ""
+#define SD_INFO ""
+#endif
#ifdef SOLARIS
#include <kstat.h>
@@ -50,6 +56,8 @@
#define loaddouble(la) ((double)(la) / FSCALE)
#endif
+static int systemd_fds = 0;
+
int verbosity = 1;
int flagkillopts = 1;
int flagdelay = 1;
@@ -107,7 +115,7 @@
void drop_nomem(void)
{
- strerr_die2sys(111,DROP,"out of memory");
+ strerr_die2sys(111, systemd_fds > 0 ? SD_WARNING DROP : DROP, "out of memory");
}
void cats(char *s)
{
@@ -139,7 +147,8 @@
}
void drop_rules(void)
{
- strerr_die4sys(111,DROP,"unable to read ",fnrules,": ");
+ strerr_die4sys(111, systemd_fds > 0 ? SD_WARNING DROP : DROP,
+ "unable to read ", fnrules, ": ");
}
unsigned long limit = 40;
@@ -228,12 +237,14 @@
if (getnameinfo((struct sockaddr *) &remote, sizeof(remote), remoteipstr, sizeof(remoteipstr),
remoteportstr, sizeof(remoteportstr),
NI_NUMERICHOST|NI_NUMERICSERV)) {
- strerr_die2sys(111,DROP,"unable to get remote host + port: ");
+ strerr_die2sys(111, systemd_fds > 0 ? SD_WARNING DROP : DROP,
+ "unable to get remote host + port: ");
}
if (verbosity >= 2) {
strnum[fmt_ulong(strnum,getpid())] = 0;
- strerr_warn4("tcpserver: pid ",strnum," from ",remoteipstr,0);
+ strerr_warn5(systemd_fds > 0 ? SD_INFO : "", "tcpserver: pid ", strnum,
+ " from ", remoteipstr, 0);
}
if (flagkillopts)
@@ -244,16 +255,19 @@
if (*banner) {
buffer_init(&b,write,t,bspace,sizeof bspace);
if (buffer_putsflush(&b,banner) == -1)
- strerr_die2sys(111,DROP,"unable to print banner: ");
+ strerr_die2sys(111, systemd_fds > 0 ? SD_WARNING DROP : DROP,
+ "unable to print banner: ");
}
if (getsockname(t,(struct sockaddr *) &local, &addrlen))
- strerr_die2sys(111,DROP,"unable to get local address: ");
+ strerr_die2sys(111, systemd_fds > 0 ? SD_WARNING DROP : DROP,
+ "unable to get local address: ");
if (getnameinfo((struct sockaddr *) &local, sizeof(local), localipstr, sizeof(localipstr),
localportstr, sizeof(localportstr),
NI_NUMERICHOST|NI_NUMERICSERV)) {
- strerr_die2sys(111,DROP,"unable to get local host + port: ");
+ strerr_die2sys(111, systemd_fds > 0 ? SD_WARNING DROP : DROP,
+ "unable to get local host + port: ");
}
if (!localhost) {
@@ -393,7 +407,8 @@
buffer_init(&b,write,t,bspace,sizeof bspace);
buffer_puts(&b,diemsg);
if (buffer_putsflush(&b,"\r\n") == -1)
- strerr_die2sys(111,DROP,"unable to print diemsg: ");
+ strerr_die2sys(111, systemd_fds > 0 ? SD_WARNING DROP : DROP,
+ "unable to print diemsg: ");
}
sleep(1);
_exit(100);
@@ -403,7 +418,6 @@
/* ---------------------------- parent */
-
#define FATAL "tcpserver: fatal: "
void usage(void)
@@ -435,7 +449,8 @@
if (verbosity < 2) return;
strnum[fmt_ulong(strnum,numchildren)] = 0;
strnum2[fmt_ulong(strnum2,limit)] = 0;
- strerr_warn4("tcpserver: status: ",strnum,"/",strnum2,0);
+ strerr_warn5(systemd_fds > 0 ? SD_INFO : "", "tcpserver: status: ", strnum,
+ "/", strnum2, 0);
}
void sigterm()
@@ -453,11 +468,13 @@
if (verbosity >= 2) {
strnum[fmt_ulong(strnum,pid)] = 0;
strnum2[fmt_ulong(strnum2,wstat)] = 0;
- strerr_warn4("tcpserver: end ",strnum," status ",strnum2,0);
+ strerr_warn5(systemd_fds > 0 ? SD_INFO : "", "tcpserver: end ", strnum,
+ " status ", strnum2, 0);
}
if (numchildren) --numchildren; printstatus();
for (u=0; u < limit; u++) if (child[u].pid == pid) { child[u].pid = 0; break; }
- if (u == limit) strerr_die1x(111,"tcpserver: ERROR: dead child not found?!"); /* never happens */
+ if (u == limit) strerr_die2x(111, systemd_fds > 0 ? SD_CRIT : "",
+ "tcpserver: ERROR: dead child not found?!"); /* never happens */
}
}
@@ -538,6 +555,22 @@
sig_catch(sig_term,sigterm);
sig_ignore(sig_pipe);
+#ifdef HAVE_SYSTEMD
+ if ((systemd_fds = sd_listen_fds(0)) > 0) {
+ for (s = 1; s < systemd_fds; s++) {
+ if (!(pid = fork())) {
+ break;
+ } else if (pid < 0) {
+ strerr_die2sys(111, SD_CRIT FATAL, "unable to fork(): ");
+ }
+ }
+ s += SD_LISTEN_FDS_START-1;
+ if (sd_is_socket(s, AF_UNSPEC, SOCK_STREAM, 1) <= 0)
+ strerr_die2x(111, SD_CRIT FATAL, "expected only listening STREAM sockets");
+ if (getsockname(s, (struct sockaddr *) &local, &addrlen))
+ strerr_die2sys(111, SD_CRIT FATAL, "unable to get local address: ");
+ } else {
+#endif
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
if (hints.ai_family == AF_UNSPEC) {
@@ -570,18 +599,24 @@
strerr_die2sys(111,FATAL,"unable to get local address: ");
if (socket_listen(s,backlog) == -1)
strerr_die2sys(111,FATAL,"unable to listen: ");
+#ifdef HAVE_SYSTEMD
+ }
+#endif
ndelay_off(s);
if (gid) if (prot_gid(gid) == -1)
- strerr_die2sys(111,FATAL,"unable to set gid: ");
+ strerr_die2sys(111, systemd_fds > 0 ? SD_CRIT FATAL : FATAL,
+ "unable to set gid: ");
if (uid) if (prot_uid(uid) == -1)
- strerr_die2sys(111,FATAL,"unable to set uid: ");
+ strerr_die2sys(111, systemd_fds > 0 ? SD_CRIT FATAL : FATAL,
+ "unable to set uid: ");
if (getnameinfo((struct sockaddr *) &local, sizeof(local), NULL, 0,
localportstr, sizeof(localportstr),
NI_NUMERICHOST|NI_NUMERICSERV)) {
- strerr_die2sys(111,DROP,"unable to get local name: ");
+ strerr_die2sys(111, systemd_fds > 0 ? SD_WARNING DROP : DROP,
+ "unable to get local name: ");
}
if (flag1) {
buffer_init(&b,write,1,bspace,sizeof bspace);
@@ -613,15 +657,18 @@
close(s);
doit(t);
if ((fd_move(0,t) == -1) || (fd_copy(1,0) == -1))
- strerr_die2sys(111,DROP,"unable to set up descriptors: ");
+ strerr_die2sys(111, systemd_fds > 0 ? SD_WARNING DROP : DROP,
+ "unable to set up descriptors: ");
sig_uncatch(sig_child);
sig_unblock(sig_child);
sig_uncatch(sig_term);
sig_uncatch(sig_pipe);
pathexec(argv);
- strerr_die4sys(111,DROP,"unable to run ",*argv,": ");
+ strerr_die4sys(111, systemd_fds > 0 ? SD_WARNING DROP : DROP,
+ "unable to run ", *argv, ": ");
case -1:
- strerr_warn2(DROP,"unable to fork: ",&strerr_sys);
+ strerr_warn2(systemd_fds > 0 ? SD_WARNING DROP : DROP,
+ "unable to fork: ", &strerr_sys);
--numchildren; printstatus();
break;
default:
@@ -633,7 +680,7 @@
byte_copy(child[u].ip, 16, remote.sa6.sin6_addr.s6_addr);
child[u].pid = pid; break;
}
- if (u == limit) strerr_die1x(111,"tcpserver: ERROR: no empty space for new child?!"); /* never happens */
+ if (u == limit) strerr_die2x(111, systemd_fds > 0 ? SD_CRIT : "", "tcpserver: ERROR: no empty space for new child?!"); /* never happens */
}
close(t);
}
diff -rNU3 ucspi-tcp-0.88/trysystemd.c ucspi-tcp-0.88.systemd/trysystemd.c
--- ucspi-tcp-0.88/trysystemd.c 1970-01-01 01:00:00.000000000 +0100
+++ ucspi-tcp-0.88.systemd/trysystemd.c 2012-02-21 16:30:17.000000000 +0100
@@ -0,0 +1,7 @@
+#include <systemd/sd-daemon.h>
+#include <string.h>
+
+int main(int argc, char **argv) {
+ argc = write(1, SD_INFO "OK", strlen(SD_INFO) + 2);
+}
+
diff -rNU3 ucspi-tcp-0.88/ucspi-tcp-0.88-man/tcpserver-systemd.8 ucspi-tcp-0.88.systemd/ucspi-tcp-0.88-man/tcpserver-systemd.8
--- ucspi-tcp-0.88/ucspi-tcp-0.88-man/tcpserver-systemd.8 1970-01-01 01:00:00.000000000 +0100
+++ ucspi-tcp-0.88.systemd/ucspi-tcp-0.88-man/tcpserver-systemd.8 2012-02-22 10:59:22.000000000 +0100
@@ -0,0 +1,163 @@
+.TH tcpserver 8
+.SH NAME
+tcpserver \- tcpserver accepts incoming TCP connections.
+.SH SYNOPSIS
+\fBtcpserver\fI opts host port prog
+.SH DESCRIPTION
+\fIopts\fR is a series of getopt-style options:
+.TP
+\fIhost\fR
+is one argument.
+.TP
+\fIport\fR
+is one argument.
+.TP
+\fIprog\fR
+consists of one or more arguments.
+.PP
+\fBtcpserver\fR waits for connections from TCP clients. For each connection, it runs
+\fIprog\fR, with descriptor 0 reading from the network and descriptor 1
+writing to the network. It also sets up several environment variables.
+.PP
+The server's address is given by \fIhost\fR and \fIport\fR. \fIport\fR
+may be a name from /etc/services or a number; if it is 0, \fBtcpserver\fR
+will choose a free TCP port. \fIhost\fR may be 0, allowing connections to
+any local IP address; or a dotted-decimal IP address, allowing connections
+only to that address; or a host name, allowing connections to the \fIfirst\fR
+IP address for that host. Host names are fed through qualification using
+dns_ip4_qualify.
+.PP
+\fBtcpserver\fR exits when it receives SIGTERM.
+.PP
+\fBtcpserver\fR also has the following options:
+.PP
+General options:
+.TP
+\fB-q\fR
+Quiet. Do not print error messages.
+.TP
+\fB-Q\fR
+(Default.) Print error messages.
+.TP
+\fB-v\fR
+Verbose. Print error messages and status messages.
+.PP
+Connection options:
+.TP
+\fB-c\fR n
+Do not handle more than n simultaneous connections. If there are n
+simultaneous copies of \fIprog\fR running, defer acceptance of a new
+connection until one copy finishes. n must be a positive integer. Default:
+40.
+.TP
+\fB-x\fR cdb
+Follow the rules compiled into cdb by tcprules. These rules may specify
+setting environment variables or rejecting connections from bad sources.
+You can rerun tcprules to change the rules while \fBtcpserver\fR is running.
+.TP
+\fB-X\fR
+With -x cdb, allows connections even if cdb does not exist. Normally
+\fBtcpserver\fR will drop the connection if cdb does not exist.
+.TP
+\fB-B\fR banner
+Write banner to the network immediately after each connection is made.
+\fBtcpserver\fR writes banner before looking up \fI$TCPREMOTEHOST\fR, before
+looking up \fI$TCPREMOTEINFO\fR, and before checking cdb. This feature can be
+used to reduce latency in protocols where the client waits for a greeting
+from the server.
+.TP
+\fB-g\fR gid
+Switch group ID to gid after preparing to receive connections. gid must be
+a positive integer.
+.TP
+\fB-u\fR uid
+Switch user ID to uid after preparing to receive connections. uid must be a
+positive integer.
+.TP
+\fB-U\fR
+Same as \fI-g $GID -u $UID\fR. Typically \fI$GID\fR and \fI$UID\fR are set
+by \fBenvuidgid\fR.
+.TP
+\fB-1\fR
+After preparing to receive connections, print the local port number to
+standard output.
+.TP
+\fB-b\fR n
+Allow a backlog of approximately n TCP SYNs. On some systems, n is silently
+limited to 5. On systems supporting SYN cookies, the backlog is irrelevant.
+.TP
+\fB-o\fR
+Leave IP options alone. If the client is sending packets along an IP source
+route, send packets back along the same route.
+.TP
+\fB-O\fR
+(Default.) Kill IP options. A client can still use source routing to connect
+and to send data, but packets will be sent back along the default route.
+.TP
+\fB-d\fR
+Delay sending data for a fraction of a second whenever the remote host is
+responding slowly. This is currently the default, but it may not be in the
+future; if you want it, set it explicitly.
+.TP
+\fB-D\fR
+Never delay sending data; enable \fITCP_NODELAY\fR.
+.PP
+Data-gathering options:
+.TP
+\fB-h\fR
+(Default.) Look up the remote host name in DNS to set the environment variable
+$TCPREMOTEHOST.
+.TP
+\fB-H\fR
+Do not look up the remote host name in DNS; remove the environment variable
+\fI$TCPREMOTEHOST\fR. To avoid loops, you \fImust\fR use this option for servers
+on TCP port 53.
+.TP
+\fB-p\fR
+Paranoid. After looking up the remote host name in DNS, look up the IP
+addresses in DNS for that host name, and remove the environment variable
+\fI$TCPREMOTEHOST\fR if none of the addresses match the client's IP address.
+.TP
+\fB-P\fR
+(Default.) Not paranoid.
+.TP
+\fB-l\fR localname
+Do not look up the local host name in DNS; use localname for the environment
+variable \fI$TCPLOCALHOST\fR. A common choice for localname is 0. To avoid loops,
+you \fImust\fR use this option for servers on TCP port 53.
+.TP
+\fB-r\fR
+(Default.) Attempt to obtain \fI$TCPREMOTEINFO\fR from the remote host.
+.TP
+\fB-R\fR
+Do not attempt to obtain \fI$TCPREMOTEINFO\fR from the remote host. To avoid loops,
+you \fImust\fR use this option for servers on TCP ports 53 and 113.
+.TP
+\fB-t\fR n
+Give up on the \fI$TCPREMOTEINFO\fR connection attempt after n seconds. Default: 26.
+.TP
+\fB-4\fR
+Listen on an IPv4 socket only. Default is to use what's available (see
+.B AI_ADDRCONFIG
+in
+.BR getaddrinfo(3) ).
+.TP
+\fB-6\fR
+Listen on an IPv6 socket only. Default is to use what's available (see
+.B AI_ADDRCONFIG
+in
+.BR getaddrinfo(3) ).
+
+\fBtcpserver\fR also supports the \fBsd-daemon\fR(1) interface. In particular,
+when \fBtcpserver\fR is run as a socket-activated service from \fBsystemd\fR(1),
+it will use the listening sockets provided by \fBsystemd\fR(1) and ignore the
+host and port arguments (which must still be present).
+
+Note that when run from systemd, tcpserver will create a separate process for
+each provided listening socket. This means that certain command line options
+(in particular \fB-c\fR) apply to each listening socket separately.
+
+.SH SEE ALSO
+tcp-environ(5),
+tcprules(8),
+envuidgid(8)
--- ucspi-tcp-0.88/tcpserver.c.orig 2012-02-23 15:28:47.000000000 +0100
+++ ucspi-tcp-0.88/tcpserver.c 2012-02-23 15:32:07.000000000 +0100
@@ -396,6 +396,7 @@
cats(" "); safecats ("MAXCONNC"); cats(":"); safecats(maxconstr);
}
cats("\n");
+ if (systemd_fds > 0) { buffer_puts(buffer_2, SD_INFO); }
buffer_putflush(buffer_2,tmp.s,tmp.len);
}