udpsvd: forgotten 'svn add'
This commit is contained in:
parent
60fadaca28
commit
b05a939bcc
221
ipsvd/udpsvd.c
Normal file
221
ipsvd/udpsvd.c
Normal file
@ -0,0 +1,221 @@
|
||||
/* Based on ipsvd utilities written by Gerrit Pape <pape@smarden.org>
|
||||
* which are released into public domain by the author.
|
||||
* Homepage: http://smarden.sunsite.dk/ipsvd/
|
||||
*
|
||||
* Copyright (C) 2007 Denis Vlasenko.
|
||||
*
|
||||
* Licensed under GPLv2, see file LICENSE in this tarball for details.
|
||||
*/
|
||||
|
||||
/* Based on ipsvd ipsvd-0.12.1. This tcpsvd accepts all options
|
||||
* which are supported by one from ipsvd-0.12.1, but not all are
|
||||
* functional. See help text at the end of this file for details.
|
||||
*
|
||||
* Code inside #if 0" is parts of original tcpsvd which are not implemented
|
||||
* for busyboxed version.
|
||||
*
|
||||
* Output of verbose mode matches original (modulo bugs and
|
||||
* unimplemented stuff). Unnatural splitting of IP and PORT
|
||||
* is retained (personally I prefer one-value "IP:PORT" notation -
|
||||
* it is a natural string representation of struct sockaddr_XX).
|
||||
*/
|
||||
|
||||
#include "busybox.h"
|
||||
|
||||
unsigned verbose;
|
||||
|
||||
static void sig_term_handler(int sig)
|
||||
{
|
||||
if (verbose)
|
||||
printf("udpsvd: info: sigterm received, exit\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int udpsvd_main(int argc, char **argv);
|
||||
int udpsvd_main(int argc, char **argv)
|
||||
{
|
||||
const char *instructs;
|
||||
char *str_t, *user;
|
||||
unsigned opt;
|
||||
// unsigned lookuphost = 0;
|
||||
// unsigned paranoid = 0;
|
||||
// unsigned long timeout = 0;
|
||||
|
||||
char *remote_hostname;
|
||||
char *local_hostname;
|
||||
char *remote_ip;
|
||||
char *local_ip;
|
||||
uint16_t local_port, remote_port;
|
||||
union {
|
||||
struct sockaddr sa;
|
||||
struct sockaddr_in sin;
|
||||
USE_FEATURE_IPV6(struct sockaddr_in6 sin6;)
|
||||
} sock_adr;
|
||||
socklen_t sockadr_size;
|
||||
int sock;
|
||||
int wstat;
|
||||
unsigned pid;
|
||||
struct bb_uidgid_t ugid;
|
||||
|
||||
enum {
|
||||
OPT_v = (1 << 0),
|
||||
OPT_u = (1 << 1),
|
||||
OPT_l = (1 << 2),
|
||||
OPT_h = (1 << 3),
|
||||
OPT_p = (1 << 4),
|
||||
OPT_i = (1 << 5),
|
||||
OPT_x = (1 << 6),
|
||||
OPT_t = (1 << 7),
|
||||
};
|
||||
|
||||
opt_complementary = "ph:vv";
|
||||
opt = getopt32(argc, argv, "vu:l:hpi:x:t:",
|
||||
&user, &local_hostname, &instructs, &instructs, &str_t, &verbose);
|
||||
//if (opt & OPT_x) iscdb =1;
|
||||
//if (opt & OPT_t) timeout = xatou(str_t);
|
||||
if (!(opt & OPT_h))
|
||||
remote_hostname = (char *)"";
|
||||
if (opt & OPT_u) {
|
||||
if (!get_uidgid(&ugid, user, 1))
|
||||
bb_error_msg_and_die("unknown user/group: %s", user);
|
||||
}
|
||||
argv += optind;
|
||||
if (!argv[0][0] || LONE_CHAR(argv[0], '0'))
|
||||
argv[0] = (char*)"0.0.0.0";
|
||||
|
||||
setlinebuf(stdout);
|
||||
|
||||
signal(SIGTERM, sig_term_handler);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
local_port = bb_lookup_port(argv[1], "udp", 0);
|
||||
sock = create_and_bind_dgram_or_die(argv[0], local_port);
|
||||
|
||||
if (opt & OPT_u) { /* drop permissions */
|
||||
xsetgid(ugid.gid);
|
||||
xsetuid(ugid.uid);
|
||||
}
|
||||
bb_sanitize_stdio(); /* fd# 1,2 must be opened */
|
||||
close(0);
|
||||
|
||||
if (verbose) {
|
||||
/* we do it only for ":port" cosmetics... oh well */
|
||||
len_and_sockaddr *lsa = xhost2sockaddr(argv[0], local_port);
|
||||
char *addr = xmalloc_sockaddr2dotted(&lsa->sa, lsa->len);
|
||||
printf("udpsvd: info: listening on %s", addr);
|
||||
free(addr);
|
||||
if (option_mask32 & OPT_u)
|
||||
printf(", uid %u, gid %u",
|
||||
(unsigned)ugid.uid, (unsigned)ugid.gid);
|
||||
puts(", starting");
|
||||
}
|
||||
|
||||
again:
|
||||
/* io[0].fd = s;
|
||||
io[0].events = IOPAUSE_READ;
|
||||
io[0].revents = 0;
|
||||
taia_now(&now);
|
||||
taia_uint(&deadline, 3600);
|
||||
taia_add(&deadline, &now, &deadline);
|
||||
iopause(io, 1, &deadline, &now);
|
||||
if (!(io[0].revents | IOPAUSE_READ))
|
||||
goto again;
|
||||
io[0].revents = 0;
|
||||
*/
|
||||
sockadr_size = sizeof(sock_adr);
|
||||
if (recvfrom(sock, NULL, 0, MSG_PEEK, &sock_adr.sa, &sockadr_size) == -1) {
|
||||
bb_perror_msg("recvfrom");
|
||||
goto again;
|
||||
}
|
||||
|
||||
while ((pid = fork()) < 0) {
|
||||
bb_perror_msg("fork failed, sleeping");
|
||||
sleep(5);
|
||||
}
|
||||
if (pid > 0) { /* parent */
|
||||
while (wait_pid(&wstat, pid) == -1)
|
||||
bb_perror_msg("error waiting for child");
|
||||
if (verbose)
|
||||
printf("udpsvd: info: end %u\n", pid);
|
||||
goto again;
|
||||
}
|
||||
|
||||
/* Child */
|
||||
|
||||
/* if (recvfrom(sock, 0, 0, MSG_PEEK, (struct sockaddr *)&sock_adr, &sockadr_size) == -1)
|
||||
drop("unable to read from socket");
|
||||
*/
|
||||
remote_ip = xmalloc_sockaddr2dotted_noport(&sock_adr.sa, sockadr_size);
|
||||
remote_port = get_nport(&sock_adr.sa);
|
||||
remote_port = ntohs(remote_port);
|
||||
if (verbose) {
|
||||
printf("udpsvd: info: pid %u from %s\n", pid, remote_ip);
|
||||
}
|
||||
if (opt & OPT_h) {
|
||||
remote_hostname = xmalloc_sockaddr2host(&sock_adr.sa, sizeof(sock_adr));
|
||||
if (!remote_hostname) {
|
||||
bb_error_msg("warning: cannot look up hostname for %s", remote_ip);
|
||||
remote_hostname = (char*)"";
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (instructs) {
|
||||
ac = ipsvd_check(iscdb, &inst, &match, (char*)instructs,
|
||||
remote_ip, remote_hostname.s, timeout);
|
||||
if (ac == -1) discard("unable to check inst", remote_ip);
|
||||
if (ac == IPSVD_ERR) discard("unable to read", (char*)instructs);
|
||||
} else
|
||||
ac = IPSVD_DEFAULT;
|
||||
#endif
|
||||
|
||||
if (verbose) {
|
||||
#if 0
|
||||
out("udpsvd: info: ");
|
||||
switch(ac) {
|
||||
case IPSVD_DENY: out("deny "); break;
|
||||
case IPSVD_DEFAULT: case IPSVD_INSTRUCT: out("start "); break;
|
||||
case IPSVD_EXEC: out("exec "); break;
|
||||
}
|
||||
#endif
|
||||
printf("udpsvd: info: %u %s:%s :%s:%s:%u\n",
|
||||
pid, local_hostname, local_ip,
|
||||
remote_hostname, remote_ip, remote_port);
|
||||
#if 0
|
||||
if (instructs) {
|
||||
out(" ");
|
||||
if (iscdb) {
|
||||
out((char*)instructs); out("/");
|
||||
}
|
||||
outfix(match.s);
|
||||
if(inst.s && inst.len && (verbose > 1)) {
|
||||
out(": "); outinst(&inst);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (ac == IPSVD_DENY) {
|
||||
recv(s, 0, 0, 0);
|
||||
_exit(100);
|
||||
}
|
||||
if (ac == IPSVD_EXEC) {
|
||||
args[0] = "/bin/sh";
|
||||
args[1] = "-c";
|
||||
args[2] = inst.s;
|
||||
args[3] = NULL;
|
||||
run = args;
|
||||
} else run = prog;
|
||||
#endif
|
||||
|
||||
xmove_fd(sock, 0);
|
||||
dup2(0, 1);
|
||||
|
||||
signal(SIGTERM, SIG_DFL);
|
||||
signal(SIGPIPE, SIG_DFL);
|
||||
argv += 2;
|
||||
|
||||
BB_EXECVP(argv[0], argv);
|
||||
bb_perror_msg_and_die("exec '%s'", argv[0]);
|
||||
}
|
Loading…
Reference in New Issue
Block a user