aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277>2007-04-02 06:17:45 +0000
committervda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277>2007-04-02 06:17:45 +0000
commite076974fc1f9c841f5a689120bbeb667d76cd5b7 (patch)
tree8e1f0418114dbbfeb9369fba5ca38935b82f3a89
parent3ce5169de28ddad622c2a365d19c516810997ecd (diff)
downloadbusybox-w32-e076974fc1f9c841f5a689120bbeb667d76cd5b7.tar.gz
busybox-w32-e076974fc1f9c841f5a689120bbeb667d76cd5b7.tar.bz2
busybox-w32-e076974fc1f9c841f5a689120bbeb667d76cd5b7.zip
udpsvd: forgotten 'svn add'
git-svn-id: svn://busybox.net/trunk/busybox@18299 69ca8d6d-28ef-0310-b511-8ec308f3f277
-rw-r--r--ipsvd/udpsvd.c221
1 files changed, 221 insertions, 0 deletions
diff --git a/ipsvd/udpsvd.c b/ipsvd/udpsvd.c
new file mode 100644
index 000000000..b3f60823f
--- /dev/null
+++ b/ipsvd/udpsvd.c
@@ -0,0 +1,221 @@
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
25unsigned verbose;
26
27static void sig_term_handler(int sig)
28{
29 if (verbose)
30 printf("udpsvd: info: sigterm received, exit\n");
31 exit(0);
32}
33
34int udpsvd_main(int argc, char **argv);
35int udpsvd_main(int argc, char **argv)
36{
37 const char *instructs;
38 char *str_t, *user;
39 unsigned opt;
40// unsigned lookuphost = 0;
41// unsigned paranoid = 0;
42// unsigned long timeout = 0;
43
44 char *remote_hostname;
45 char *local_hostname;
46 char *remote_ip;
47 char *local_ip;
48 uint16_t local_port, remote_port;
49 union {
50 struct sockaddr sa;
51 struct sockaddr_in sin;
52 USE_FEATURE_IPV6(struct sockaddr_in6 sin6;)
53 } sock_adr;
54 socklen_t sockadr_size;
55 int sock;
56 int wstat;
57 unsigned pid;
58 struct bb_uidgid_t ugid;
59
60 enum {
61 OPT_v = (1 << 0),
62 OPT_u = (1 << 1),
63 OPT_l = (1 << 2),
64 OPT_h = (1 << 3),
65 OPT_p = (1 << 4),
66 OPT_i = (1 << 5),
67 OPT_x = (1 << 6),
68 OPT_t = (1 << 7),
69 };
70
71 opt_complementary = "ph:vv";
72 opt = getopt32(argc, argv, "vu:l:hpi:x:t:",
73 &user, &local_hostname, &instructs, &instructs, &str_t, &verbose);
74 //if (opt & OPT_x) iscdb =1;
75 //if (opt & OPT_t) timeout = xatou(str_t);
76 if (!(opt & OPT_h))
77 remote_hostname = (char *)"";
78 if (opt & OPT_u) {
79 if (!get_uidgid(&ugid, user, 1))
80 bb_error_msg_and_die("unknown user/group: %s", user);
81 }
82 argv += optind;
83 if (!argv[0][0] || LONE_CHAR(argv[0], '0'))
84 argv[0] = (char*)"0.0.0.0";
85
86 setlinebuf(stdout);
87
88 signal(SIGTERM, sig_term_handler);
89 signal(SIGPIPE, SIG_IGN);
90
91 local_port = bb_lookup_port(argv[1], "udp", 0);
92 sock = create_and_bind_dgram_or_die(argv[0], local_port);
93
94 if (opt & OPT_u) { /* drop permissions */
95 xsetgid(ugid.gid);
96 xsetuid(ugid.uid);
97 }
98 bb_sanitize_stdio(); /* fd# 1,2 must be opened */
99 close(0);
100
101 if (verbose) {
102 /* we do it only for ":port" cosmetics... oh well */
103 len_and_sockaddr *lsa = xhost2sockaddr(argv[0], local_port);
104 char *addr = xmalloc_sockaddr2dotted(&lsa->sa, lsa->len);
105 printf("udpsvd: info: listening on %s", addr);
106 free(addr);
107 if (option_mask32 & OPT_u)
108 printf(", uid %u, gid %u",
109 (unsigned)ugid.uid, (unsigned)ugid.gid);
110 puts(", starting");
111 }
112
113 again:
114/* io[0].fd = s;
115 io[0].events = IOPAUSE_READ;
116 io[0].revents = 0;
117 taia_now(&now);
118 taia_uint(&deadline, 3600);
119 taia_add(&deadline, &now, &deadline);
120 iopause(io, 1, &deadline, &now);
121 if (!(io[0].revents | IOPAUSE_READ))
122 goto again;
123 io[0].revents = 0;
124*/
125 sockadr_size = sizeof(sock_adr);
126 if (recvfrom(sock, NULL, 0, MSG_PEEK, &sock_adr.sa, &sockadr_size) == -1) {
127 bb_perror_msg("recvfrom");
128 goto again;
129 }
130
131 while ((pid = fork()) < 0) {
132 bb_perror_msg("fork failed, sleeping");
133 sleep(5);
134 }
135 if (pid > 0) { /* parent */
136 while (wait_pid(&wstat, pid) == -1)
137 bb_perror_msg("error waiting for child");
138 if (verbose)
139 printf("udpsvd: info: end %u\n", pid);
140 goto again;
141 }
142
143 /* Child */
144
145/* if (recvfrom(sock, 0, 0, MSG_PEEK, (struct sockaddr *)&sock_adr, &sockadr_size) == -1)
146 drop("unable to read from socket");
147*/
148 remote_ip = xmalloc_sockaddr2dotted_noport(&sock_adr.sa, sockadr_size);
149 remote_port = get_nport(&sock_adr.sa);
150 remote_port = ntohs(remote_port);
151 if (verbose) {
152 printf("udpsvd: info: pid %u from %s\n", pid, remote_ip);
153 }
154 if (opt & OPT_h) {
155 remote_hostname = xmalloc_sockaddr2host(&sock_adr.sa, sizeof(sock_adr));
156 if (!remote_hostname) {
157 bb_error_msg("warning: cannot look up hostname for %s", remote_ip);
158 remote_hostname = (char*)"";
159 }
160 }
161
162#if 0
163 if (instructs) {
164 ac = ipsvd_check(iscdb, &inst, &match, (char*)instructs,
165 remote_ip, remote_hostname.s, timeout);
166 if (ac == -1) discard("unable to check inst", remote_ip);
167 if (ac == IPSVD_ERR) discard("unable to read", (char*)instructs);
168 } else
169 ac = IPSVD_DEFAULT;
170#endif
171
172 if (verbose) {
173#if 0
174 out("udpsvd: info: ");
175 switch(ac) {
176 case IPSVD_DENY: out("deny "); break;
177 case IPSVD_DEFAULT: case IPSVD_INSTRUCT: out("start "); break;
178 case IPSVD_EXEC: out("exec "); break;
179 }
180#endif
181 printf("udpsvd: info: %u %s:%s :%s:%s:%u\n",
182 pid, local_hostname, local_ip,
183 remote_hostname, remote_ip, remote_port);
184#if 0
185 if (instructs) {
186 out(" ");
187 if (iscdb) {
188 out((char*)instructs); out("/");
189 }
190 outfix(match.s);
191 if(inst.s && inst.len && (verbose > 1)) {
192 out(": "); outinst(&inst);
193 }
194 }
195#endif
196 }
197
198#if 0
199 if (ac == IPSVD_DENY) {
200 recv(s, 0, 0, 0);
201 _exit(100);
202 }
203 if (ac == IPSVD_EXEC) {
204 args[0] = "/bin/sh";
205 args[1] = "-c";
206 args[2] = inst.s;
207 args[3] = NULL;
208 run = args;
209 } else run = prog;
210#endif
211
212 xmove_fd(sock, 0);
213 dup2(0, 1);
214
215 signal(SIGTERM, SIG_DFL);
216 signal(SIGPIPE, SIG_DFL);
217 argv += 2;
218
219 BB_EXECVP(argv[0], argv);
220 bb_perror_msg_and_die("exec '%s'", argv[0]);
221}