summaryrefslogtreecommitdiff
path: root/ipsvd/udpsvd.c
diff options
context:
space:
mode:
Diffstat (limited to 'ipsvd/udpsvd.c')
-rw-r--r--ipsvd/udpsvd.c307
1 files changed, 0 insertions, 307 deletions
diff --git a/ipsvd/udpsvd.c b/ipsvd/udpsvd.c
deleted file mode 100644
index 700e1aff4..000000000
--- a/ipsvd/udpsvd.c
+++ /dev/null
@@ -1,307 +0,0 @@
1/* Based on ipsvd utilities written by Gerrit Pape <pape@smarden.org>
2 * which are released into public domain by the author.
3 * Homepage: http://smarden.sunsite.dk/ipsvd/
4 *
5 * Copyright (C) 2007 Denis Vlasenko.
6 *
7 * Licensed under GPLv2, see file LICENSE in this tarball for details.
8 */
9
10/* Based on ipsvd ipsvd-0.12.1. This tcpsvd accepts all options
11 * which are supported by one from ipsvd-0.12.1, but not all are
12 * functional. See help text at the end of this file for details.
13 *
14 * Code inside #if 0" is parts of original tcpsvd which are not implemented
15 * for busyboxed version.
16 *
17 * Output of verbose mode matches original (modulo bugs and
18 * unimplemented stuff). Unnatural splitting of IP and PORT
19 * is retained (personally I prefer one-value "IP:PORT" notation -
20 * it is a natural string representation of struct sockaddr_XX).
21 */
22
23#include "busybox.h"
24
25#include "udp_io.c"
26
27unsigned verbose;
28
29static void sig_term_handler(int sig)
30{
31 if (verbose)
32 printf("%s: info: sigterm received, exit\n", applet_name);
33 exit(0);
34}
35
36int udpsvd_main(int argc, char **argv);
37int udpsvd_main(int argc, char **argv)
38{
39 const char *instructs;
40 char *str_t, *user;
41 unsigned opt;
42
43 char *remote_hostname;
44 char *local_hostname = NULL;
45 char *remote_ip;
46 char *local_ip = local_ip; /* gcc */
47 uint16_t local_port, remote_port;
48 len_and_sockaddr remote;
49 len_and_sockaddr *localp;
50 int sock;
51 int wstat;
52 unsigned pid;
53 struct bb_uidgid_t ugid;
54
55 enum {
56 OPT_v = (1 << 0),
57 OPT_u = (1 << 1),
58 OPT_l = (1 << 2),
59 OPT_h = (1 << 3),
60 OPT_p = (1 << 4),
61 OPT_i = (1 << 5),
62 OPT_x = (1 << 6),
63 OPT_t = (1 << 7),
64 };
65
66 opt_complementary = "-3:ph:vv";
67 opt = getopt32(argc, argv, "vu:l:hpi:x:t:",
68 &user, &local_hostname, &instructs, &instructs, &str_t, &verbose);
69 //if (opt & OPT_x) iscdb =1;
70 //if (opt & OPT_t) timeout = xatou(str_t);
71 if (!(opt & OPT_h))
72 remote_hostname = (char *)"";
73 if (opt & OPT_u) {
74 if (!get_uidgid(&ugid, user, 1))
75 bb_error_msg_and_die("unknown user/group: %s", user);
76 }
77 argv += optind;
78 if (!argv[0][0] || LONE_CHAR(argv[0], '0'))
79 argv[0] = (char*)"0.0.0.0";
80
81 /* stdout is used for logging, don't buffer */
82 setlinebuf(stdout);
83 bb_sanitize_stdio(); /* fd# 1,2 must be opened */
84
85 signal(SIGTERM, sig_term_handler);
86 signal(SIGPIPE, SIG_IGN);
87
88 local_port = bb_lookup_port(argv[1], "udp", 0);
89 localp = xhost2sockaddr(argv[0], local_port);
90 sock = xsocket(localp->sa.sa_family, SOCK_DGRAM, 0);
91 xmove_fd(sock, 0); /* fd# 0 is the open UDP socket */
92 xbind(0, &localp->sa, localp->len);
93 socket_want_pktinfo(0);
94
95 if (opt & OPT_u) { /* drop permissions */
96 xsetgid(ugid.gid);
97 xsetuid(ugid.uid);
98 }
99
100 if (verbose) {
101 /* we do it only for ":port" cosmetics... oh well */
102 char *addr = xmalloc_sockaddr2dotted(&localp->sa, localp->len);
103 printf("%s: info: listening on %s", applet_name, addr);
104 free(addr);
105 if (option_mask32 & OPT_u)
106 printf(", uid %u, gid %u",
107 (unsigned)ugid.uid, (unsigned)ugid.gid);
108 puts(", starting");
109 }
110
111 again:
112 /* if (recvfrom(0, NULL, 0, MSG_PEEK, &remote.sa, &localp->len) < 0) { */
113 if (recv_from_to(0, NULL, 0, MSG_PEEK, &remote.sa, &localp->sa, localp->len) < 0) {
114 bb_perror_msg("recvfrom");
115 goto again;
116 }
117
118 while ((pid = fork()) < 0) {
119 bb_perror_msg("fork failed, sleeping");
120 sleep(5);
121 }
122 if (pid > 0) { /* parent */
123 while (wait_pid(&wstat, pid) == -1)
124 bb_perror_msg("error waiting for child");
125 if (verbose)
126 printf("%s: info: end %u\n", applet_name, pid);
127 goto again;
128 }
129
130 /* Child */
131
132#if 0
133 /* I'd like to make it so that local addr is fixed to localp->sa,
134 * but how? The below trick doesn't work... */
135 close(0);
136 set_nport(localp, htons(local_port));
137 xmove_fd(xsocket(localp->sa.sa_family, SOCK_DGRAM, 0), 0);
138 xbind(0, &localp->sa, localp->len);
139#endif
140
141 if (verbose) {
142 local_ip = xmalloc_sockaddr2dotted_noport(&localp->sa, localp->len);
143 if (!local_hostname) {
144 local_hostname = xmalloc_sockaddr2host_noport(&localp->sa, localp->len);
145 if (!local_hostname)
146 bb_error_msg_and_die("cannot look up local hostname for %s", local_ip);
147 }
148 }
149
150 remote_ip = xmalloc_sockaddr2dotted_noport(&remote.sa, localp->len);
151 remote_port = get_nport(&remote.sa);
152 remote_port = ntohs(remote_port);
153 if (verbose)
154 printf("%s: info: pid %u from %s\n", applet_name, pid, remote_ip);
155
156 if (opt & OPT_h) {
157 remote_hostname = xmalloc_sockaddr2host(&remote.sa, localp->len);
158 if (!remote_hostname) {
159 bb_error_msg("warning: cannot look up hostname for %s", remote_ip);
160 remote_hostname = (char*)"";
161 }
162 }
163
164#if 0
165 if (instructs) {
166 ac = ipsvd_check(iscdb, &inst, &match, (char*)instructs,
167 remote_ip, remote_hostname.s, timeout);
168 if (ac == -1) discard("unable to check inst", remote_ip);
169 if (ac == IPSVD_ERR) discard("unable to read", (char*)instructs);
170 } else
171 ac = IPSVD_DEFAULT;
172#endif
173
174 if (verbose) {
175#if 0
176 out("%s: info: ", applet_name);
177 switch(ac) {
178 case IPSVD_DENY: out("deny "); break;
179 case IPSVD_DEFAULT: case IPSVD_INSTRUCT: out("start "); break;
180 case IPSVD_EXEC: out("exec "); break;
181 }
182#endif
183 printf("%s: info: %u %s:%s :%s:%s:%u\n",
184 applet_name, pid, local_hostname, local_ip,
185 remote_hostname, remote_ip, remote_port);
186#if 0
187 if (instructs) {
188 out(" ");
189 if (iscdb) {
190 out((char*)instructs); out("/");
191 }
192 outfix(match.s);
193 if(inst.s && inst.len && (verbose > 1)) {
194 out(": "); outinst(&inst);
195 }
196 }
197#endif
198 }
199
200#if 0
201 if (ac == IPSVD_DENY) {
202 recv(0, 0, 0, 0);
203 _exit(100);
204 }
205 if (ac == IPSVD_EXEC) {
206 args[0] = "/bin/sh";
207 args[1] = "-c";
208 args[2] = inst.s;
209 args[3] = NULL;
210 run = args;
211 } else run = prog;
212#endif
213 /* Make plain write(1) work for the child by supplying default
214 * destination address */
215 xconnect(0, &remote.sa, localp->len);
216 dup2(0, 1);
217
218 signal(SIGTERM, SIG_DFL);
219 signal(SIGPIPE, SIG_DFL);
220
221 argv += 2;
222 BB_EXECVP(argv[0], argv);
223 bb_perror_msg_and_die("exec '%s'", argv[0]);
224}
225
226/*
227udpsvd [-hpvv] [-u user] [-l name] [-i dir|-x cdb] [-t sec] host port prog
228
229udpsvd creates an UDP/IP socket, binds it to the address host:port,
230and listens on the socket for incoming datagrams.
231
232If a datagram is available on the socket, udpsvd conditionally starts
233a program, with standard input reading from the socket, and standard
234output redirected to standard error, to handle this, and possibly
235more datagrams. udpsvd does not start the program if another program
236that it has started before still is running. If the program exits,
237udpsvd again listens to the socket until a new datagram is available.
238If there are still datagrams available on the socket, the program
239is restarted immediately.
240
241udpsvd optionally checks for special intructions depending on
242the IP address or hostname of the client sending the datagram which
243not yet was handled by a running program, see ipsvd-instruct(5)
244for details.
245
246Attention:
247UDP is a connectionless protocol. Most programs that handle user datagrams,
248such as talkd(8), keep running after receiving a datagram, and process
249subsequent datagrams sent to the socket until a timeout is reached.
250udpsvd only checks special instructions for a datagram that causes a startup
251of the program; not if a program handling datagrams already is running.
252It doesn't make much sense to restrict access through special instructions
253when using such a program.
254
255On the other hand, it makes perfectly sense with programs like tftpd(8),
256that fork to establish a separate connection to the client when receiving
257the datagram. In general it's adequate to set up special instructions for
258programs that support being run by tcpwrapper.
259Options
260
261host
262 host either is a hostname, or a dotted-decimal IP address, or 0.
263 If host is 0, udpsvd accepts datagrams to any local IP address.
264port
265 udpsvd accepts datagrams to host:port. port may be a name from
266 /etc/services or a number.
267prog
268 prog consists of one or more arguments. udpsvd normally runs prog
269 to handle a datagram, and possibly more, that is sent to the socket,
270 if there is no program that was started before by udpsvd still running
271 and handling datagrams.
272-i dir
273 read instructions for handling new connections from the instructions
274 directory dir. See ipsvd-instruct(5) for details.
275-x cdb
276 read instructions for handling new connections from the constant
277 database cdb. The constant database normally is created from
278 an instructions directory by running ipsvd-cdb(8).
279-t sec
280 timeout. This option only takes effect if the -i option is given.
281 While checking the instructions directory, check the time of last
282 access of the file that matches the clients address or hostname if any,
283 discard and remove the file if it wasn't accessed within the last
284 sec seconds; udpsvd does not discard or remove a file if the user's
285 write permission is not set, for those files the timeout is disabled.
286 Default is 0, which means that the timeout is disabled.
287-l name
288 local hostname. Do not look up the local hostname in DNS, but use name
289 as hostname. By default udpsvd looks up the local hostname once at startup.
290-u user[:group]
291 drop permissions. Switch user ID to user's UID, and group ID to user's
292 primary GID after creating and binding to the socket. If user
293 is followed by a colon and a group name, the group ID is switched
294 to the GID of group instead. All supplementary groups are removed.
295-h
296 Look up the client's hostname in DNS.
297-p
298 paranoid. After looking up the client's hostname in DNS, look up
299 the IP addresses in DNS for that hostname, and forget the hostname
300 if none of the addresses match the client's IP address. You should
301 set this option if you use hostname based instructions. The -p option
302 implies the -h option.
303-v
304 verbose. Print verbose messages to standard output.
305-vv
306 more verbose. Print more verbose messages to standard output.
307*/