aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277>2007-04-03 01:13:04 +0000
committervda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277>2007-04-03 01:13:04 +0000
commit0ed6b531a5521c1aaed37c063f66da87cf55ad81 (patch)
treec64729c60f929f3007b4ed93543291b52cb50a02
parent5b15483f1f4ad2e5e01e73a05acd0306b88cfe14 (diff)
downloadbusybox-w32-0ed6b531a5521c1aaed37c063f66da87cf55ad81.tar.gz
busybox-w32-0ed6b531a5521c1aaed37c063f66da87cf55ad81.tar.bz2
busybox-w32-0ed6b531a5521c1aaed37c063f66da87cf55ad81.zip
udpsvd: more work on it. works in limited testing.
git-svn-id: svn://busybox.net/trunk/busybox@18311 69ca8d6d-28ef-0310-b511-8ec308f3f277
-rw-r--r--include/libbb.h11
-rw-r--r--include/usage.h27
-rw-r--r--ipsvd/tcpsvd.c5
-rw-r--r--ipsvd/udp_io.c156
-rw-r--r--ipsvd/udpsvd.c181
5 files changed, 320 insertions, 60 deletions
diff --git a/include/libbb.h b/include/libbb.h
index b802e01d3..e5413b1a4 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -321,6 +321,17 @@ typedef struct len_and_sockaddr {
321#endif 321#endif
322 }; 322 };
323} len_and_sockaddr; 323} len_and_sockaddr;
324enum {
325 LSA_SIZEOF_SA = sizeof(
326 union {
327 struct sockaddr sa;
328 struct sockaddr_in sin;
329#if ENABLE_FEATURE_IPV6
330 struct sockaddr_in6 sin6;
331#endif
332 }
333 )
334};
324/* Create stream socket, and allocated suitable lsa 335/* Create stream socket, and allocated suitable lsa
325 * (lsa of correct size and lsa->sa.sa_family (AF_INET/AF_INET6)) */ 336 * (lsa of correct size and lsa->sa.sa_family (AF_INET/AF_INET6)) */
326int xsocket_stream(len_and_sockaddr **lsap); 337int xsocket_stream(len_and_sockaddr **lsap);
diff --git a/include/usage.h b/include/usage.h
index cec2dd766..bab14f5c3 100644
--- a/include/usage.h
+++ b/include/usage.h
@@ -3326,32 +3326,41 @@ USE_FEATURE_RUN_PARTS_FANCY("\n -l Prints names of all matching files even when
3326 "1\n" 3326 "1\n"
3327 3327
3328#define tcpsvd_trivial_usage \ 3328#define tcpsvd_trivial_usage \
3329 "[-hpEvv] [-c n] [-C n:msg] [-b n] [-u user] [-l name] ip port prog..." 3329 "[-hEv] [-c n] [-C n:msg] [-b n] [-u user] [-l name] ip port prog..."
3330/* with not-implemented options: */ 3330/* with not-implemented options: */
3331/* "[-hpEvv] [-c n] [-C n:msg] [-b n] [-u user] [-l name] [-i dir|-x cdb] [ -t sec] ip port prog..." */ 3331/* "[-hpEvv] [-c n] [-C n:msg] [-b n] [-u user] [-l name] [-i dir|-x cdb] [ -t sec] ip port prog..." */
3332#define tcpsvd_full_usage \ 3332#define tcpsvd_full_usage \
3333 "tcpsvd creates TCP/IP socket, binds it to host:port\n" \ 3333 "Creates TCP socket, binds it to host:port and listens on in\n" \
3334 "and listens on in for incoming connections. For each connection\n" \ 3334 "for incoming connections. For each connection it runs prog" \
3335 "it runs prog" \
3336 "\n" \ 3335 "\n" \
3337 "\nip IP to listen on. '0' = 'all'" \ 3336 "\nip IP to listen on. '0' = all" \
3338 "\nport Port to listen on" \ 3337 "\nport Port to listen on" \
3339 "\nprog [arg] Program to run for each connection" \ 3338 "\nprog [arg] Program to run" \
3340 "\n-l name Local hostname (else looks up local hostname in DNS)" \ 3339 "\n-l name Local hostname (else looks up local hostname in DNS)" \
3341 "\n-u user[:group] Change to user/group after bind" \ 3340 "\n-u user[:group] Change to user/group after bind" \
3342 "\n-c n Handle up to n connections simultaneously" \ 3341 "\n-c n Handle up to n connections simultaneously" \
3343 "\n-C n[:msg] Allow only up to n connections from the same IP" \ 3342 "\n-C n[:msg] Allow only up to n connections from the same IP" \
3344 "\n New connections from this IP address are closed" \ 3343 "\n New connections from this IP address are closed" \
3345 "\n immediately. 'msg' is written to the peer before close" \ 3344 "\n immediately. 'msg' is written to the peer before close" \
3346 "\n-h Look up peer's hostname in DNS" \ 3345 "\n-h Look up peer's hostname" \
3347 "\n-b n Allow a backlog of approximately n TCP SYNs" \ 3346 "\n-b n Allow a backlog of approximately n TCP SYNs" \
3348 "\n-E Do not set up TCP-related environment variables" \ 3347 "\n-E Do not set up TCP-related environment variables" \
3349 "\n-v Verbose" 3348 "\n-v Verbose"
3350 3349
3351#define udpsvd_trivial_usage \ 3350#define udpsvd_trivial_usage \
3352 "TODO" 3351 "[-hv] [-u user] [-l name] host port prog"
3353#define udpsvd_full_usage \ 3352#define udpsvd_full_usage \
3354 "TODO" 3353 "Creates UDP socket, binds it to host:port and listens on in\n" \
3354 "for incoming packets. When packet arrives it runs prog.\n" \
3355 "When prog exits, it start to listen on the socket again" \
3356 "\n" \
3357 "\nip IP to listen on. '0' = all" \
3358 "\nport Port to listen on" \
3359 "\nprog [arg] Program to run" \
3360 "\n-l name Local hostname (else looks up local hostname in DNS)" \
3361 "\n-u user[:group] Change to user/group after bind" \
3362 "\n-h Look up peer's hostname" \
3363 "\n-v Verbose"
3355 3364
3356#define tftp_trivial_usage \ 3365#define tftp_trivial_usage \
3357 "[OPTION]... HOST [PORT]" 3366 "[OPTION]... HOST [PORT]"
diff --git a/ipsvd/tcpsvd.c b/ipsvd/tcpsvd.c
index 98234a78b..056deff33 100644
--- a/ipsvd/tcpsvd.c
+++ b/ipsvd/tcpsvd.c
@@ -179,7 +179,10 @@ int tcpsvd_main(int argc, char **argv)
179 if (!argv[0][0] || LONE_CHAR(argv[0], '0')) 179 if (!argv[0][0] || LONE_CHAR(argv[0], '0'))
180 argv[0] = (char*)"0.0.0.0"; 180 argv[0] = (char*)"0.0.0.0";
181 181
182 /* stdout is used for logging, don't buffer */
182 setlinebuf(stdout); 183 setlinebuf(stdout);
184 bb_sanitize_stdio(); /* fd# 1,2 must be opened */
185
183 need_hostnames = verbose || !(option_mask32 & OPT_E); 186 need_hostnames = verbose || !(option_mask32 & OPT_E);
184 need_remote_ip = max_per_host || need_hostnames; 187 need_remote_ip = max_per_host || need_hostnames;
185 188
@@ -232,7 +235,6 @@ int tcpsvd_main(int argc, char **argv)
232 xsetuid(ugid.uid); 235 xsetuid(ugid.uid);
233 } 236 }
234#endif 237#endif
235 bb_sanitize_stdio(); /* fd# 1,2 must be opened */
236 close(0); 238 close(0);
237 239
238 if (verbose) { 240 if (verbose) {
@@ -439,6 +441,7 @@ int tcpsvd_main(int argc, char **argv)
439 441
440 xmove_fd(conn, 0); 442 xmove_fd(conn, 0);
441 dup2(0, 1); 443 dup2(0, 1);
444
442 signal(SIGTERM, SIG_DFL); 445 signal(SIGTERM, SIG_DFL);
443 signal(SIGPIPE, SIG_DFL); 446 signal(SIGPIPE, SIG_DFL);
444 signal(SIGCHLD, SIG_DFL); 447 signal(SIGCHLD, SIG_DFL);
diff --git a/ipsvd/udp_io.c b/ipsvd/udp_io.c
new file mode 100644
index 000000000..68999d44d
--- /dev/null
+++ b/ipsvd/udp_io.c
@@ -0,0 +1,156 @@
1/* Thus far used only by udpsvd.c */
2
3void socket_want_pktinfo(int fd);
4ssize_t send_to_from(int fd, void *buf, size_t len, int flags,
5 const struct sockaddr *from, const struct sockaddr *to,
6 socklen_t tolen);
7ssize_t recv_from_to(int fd, void *buf, size_t len, int flags,
8 struct sockaddr *from, struct sockaddr *to,
9 socklen_t sa_size);
10
11/*
12 * This asks kernel to let us know dst addr/port of incoming packets
13 * We don't check for errors here. Not supported == won't be used
14 */
15void
16socket_want_pktinfo(int fd)
17{
18#ifdef IP_PKTINFO
19 setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &const_int_1, sizeof(int));
20#endif
21#ifdef IPV6_PKTINFO
22 setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &const_int_1, sizeof(int));
23#endif
24}
25
26
27ssize_t
28send_to_from(int fd, void *buf, size_t len, int flags,
29 const struct sockaddr *from, const struct sockaddr *to,
30 socklen_t tolen)
31{
32#ifndef IP_PKTINFO
33 return sendto(fd, buf, len, flags, to, tolen);
34#else
35 struct iovec iov[1];
36 struct msghdr msg;
37 char cbuf[LSA_SIZEOF_SA];
38 /* actually, max(sizeof(in_pktinfo),sizeof(in6_pktinfo)) */
39 struct cmsghdr* cmsgptr;
40
41 if (from->sa_family != AF_INET
42#if ENABLE_FEATURE_IPV6
43 && from->sa_family != AF_INET6
44#endif
45 ) {
46 /* ANY local address */
47 return sendto(fd, buf, len, flags, to, tolen);
48 }
49
50 /* man recvmsg and man cmsg is needed to make sense of code below */
51
52 iov[0].iov_base = buf;
53 iov[0].iov_len = len;
54
55 memset(cbuf, 0, sizeof(cbuf));
56
57 memset(&msg, 0, sizeof(msg));
58 msg.msg_name = (void *)(struct sockaddr *)to; /* or compiler will annoy us */
59 msg.msg_namelen = tolen;
60 msg.msg_iov = iov;
61 msg.msg_iovlen = 1;
62 msg.msg_control = cbuf;
63 msg.msg_controllen = sizeof(cbuf);
64 msg.msg_flags = flags;
65
66 cmsgptr = CMSG_FIRSTHDR(&msg);
67 if (to->sa_family == AF_INET && from->sa_family == AF_INET) {
68 struct in_pktinfo *pktptr;
69 cmsgptr->cmsg_level = IPPROTO_IP;
70 cmsgptr->cmsg_type = IP_PKTINFO;
71 cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
72 pktptr = (struct in_pktinfo *)(CMSG_DATA(cmsgptr));
73 /* pktptr->ipi_ifindex = 0; -- already done by memset(cbuf...) */
74 pktptr->ipi_spec_dst = ((struct sockaddr_in*)from)->sin_addr;
75 }
76#if ENABLE_FEATURE_IPV6 && defined(IP6_PKTINFO)
77 else if (to->sa_family == AF_INET6 && from->sa_family == AF_INET6) {
78 struct in6_pktinfo *pktptr;
79 cmsgptr->cmsg_level = IPPROTO_IPV6;
80 cmsgptr->cmsg_type = IP6_PKTINFO;
81 cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
82 pktptr = (struct in6_pktinfo *)(CMSG_DATA(cmsgptr));
83 /* pktptr->ipi6_ifindex = 0; -- already done by memset(cbuf...) */
84 pktptr->ipi6_addr = ((struct sockaddr_in6*)from)->sin6_addr;
85 }
86#endif
87 return sendmsg(fd, &msg, flags);
88#endif
89}
90
91/* NB: this will never set port# in *to! */
92ssize_t
93recv_from_to(int fd, void *buf, size_t len, int flags,
94 struct sockaddr *from, struct sockaddr *to,
95 socklen_t sa_size)
96{
97#ifndef IP_PKTINFO
98 return recvfrom(fd, buf, len, flags, from, &sa_size);
99#else
100 /* man recvmsg and man cmsg is needed to make sense of code below */
101 struct iovec iov[1];
102 union {
103 char cmsg[CMSG_SPACE(sizeof(struct in_pktinfo))];
104 char cmsg6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
105 } u;
106 struct cmsghdr *cmsgptr;
107 struct msghdr msg;
108 socklen_t recv_length;
109
110 iov[0].iov_base = buf;
111 iov[0].iov_len = len;
112
113 memset(&msg, 0, sizeof(msg));
114 msg.msg_name = (struct sockaddr *)from;
115 msg.msg_namelen = sa_size;
116 msg.msg_iov = iov;
117 msg.msg_iovlen = 1;
118 msg.msg_control = &u;
119 msg.msg_controllen = sizeof(u);
120
121 recv_length = recvmsg(fd, &msg, flags);
122 if (recv_length < 0)
123 return recv_length;
124
125 /* Here we try to retrieve destination IP and memorize it */
126 memset(to, 0, sa_size);
127 for (cmsgptr = CMSG_FIRSTHDR(&msg);
128 cmsgptr != NULL;
129 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)
130 ) {
131 if (cmsgptr->cmsg_level == IPPROTO_IP
132 && cmsgptr->cmsg_type == IP_PKTINFO
133 ) {
134#define pktinfo(cmsgptr) ( (struct in_pktinfo*)(CMSG_DATA(cmsgptr)) )
135 to->sa_family = AF_INET;
136 ((struct sockaddr_in*)to)->sin_addr = pktinfo(cmsgptr)->ipi_addr;
137 /* ((struct sockaddr_in*)to)->sin_port = 123; */
138#undef pktinfo
139 break;
140 }
141#if ENABLE_FEATURE_IPV6 && defined(IP6_PKTINFO)
142 if (cmsgptr->cmsg_level == IPPROTO_IPV6
143 && cmsgptr->cmsg_type == IP6_PKTINFO
144 ) {
145#define pktinfo(cmsgptr) ( (struct in6_pktinfo*)(CMSG_DATA(cmsgptr)) )
146 to->sa_family = AF_INET6;
147 ((struct sockaddr_in6*)to)->sin6_addr = pktinfo(cmsgptr)->ipi6_addr;
148 /* ((struct sockaddr_in6*)to)->sin6_port = 123; */
149#undef pktinfo
150 break;
151 }
152#endif
153 }
154 return recv_length;
155#endif
156}
diff --git a/ipsvd/udpsvd.c b/ipsvd/udpsvd.c
index 06c4f2e88..700e1aff4 100644
--- a/ipsvd/udpsvd.c
+++ b/ipsvd/udpsvd.c
@@ -22,12 +22,14 @@
22 22
23#include "busybox.h" 23#include "busybox.h"
24 24
25#include "udp_io.c"
26
25unsigned verbose; 27unsigned verbose;
26 28
27static void sig_term_handler(int sig) 29static void sig_term_handler(int sig)
28{ 30{
29 if (verbose) 31 if (verbose)
30 printf("udpsvd: info: sigterm received, exit\n"); 32 printf("%s: info: sigterm received, exit\n", applet_name);
31 exit(0); 33 exit(0);
32} 34}
33 35
@@ -37,21 +39,14 @@ int udpsvd_main(int argc, char **argv)
37 const char *instructs; 39 const char *instructs;
38 char *str_t, *user; 40 char *str_t, *user;
39 unsigned opt; 41 unsigned opt;
40// unsigned lookuphost = 0;
41// unsigned paranoid = 0;
42// unsigned long timeout = 0;
43 42
44 char *remote_hostname; 43 char *remote_hostname;
45 char *local_hostname = local_hostname; /* gcc */ 44 char *local_hostname = NULL;
46 char *remote_ip; 45 char *remote_ip;
47 char *local_ip = local_ip; /* gcc */ 46 char *local_ip = local_ip; /* gcc */
48 uint16_t local_port, remote_port; 47 uint16_t local_port, remote_port;
49 union { 48 len_and_sockaddr remote;
50 struct sockaddr sa; 49 len_and_sockaddr *localp;
51 struct sockaddr_in sin;
52 USE_FEATURE_IPV6(struct sockaddr_in6 sin6;)
53 } sock_adr;
54 socklen_t sockadr_size;
55 int sock; 50 int sock;
56 int wstat; 51 int wstat;
57 unsigned pid; 52 unsigned pid;
@@ -68,7 +63,7 @@ int udpsvd_main(int argc, char **argv)
68 OPT_t = (1 << 7), 63 OPT_t = (1 << 7),
69 }; 64 };
70 65
71 opt_complementary = "ph:vv"; 66 opt_complementary = "-3:ph:vv";
72 opt = getopt32(argc, argv, "vu:l:hpi:x:t:", 67 opt = getopt32(argc, argv, "vu:l:hpi:x:t:",
73 &user, &local_hostname, &instructs, &instructs, &str_t, &verbose); 68 &user, &local_hostname, &instructs, &instructs, &str_t, &verbose);
74 //if (opt & OPT_x) iscdb =1; 69 //if (opt & OPT_x) iscdb =1;
@@ -83,26 +78,29 @@ int udpsvd_main(int argc, char **argv)
83 if (!argv[0][0] || LONE_CHAR(argv[0], '0')) 78 if (!argv[0][0] || LONE_CHAR(argv[0], '0'))
84 argv[0] = (char*)"0.0.0.0"; 79 argv[0] = (char*)"0.0.0.0";
85 80
81 /* stdout is used for logging, don't buffer */
86 setlinebuf(stdout); 82 setlinebuf(stdout);
83 bb_sanitize_stdio(); /* fd# 1,2 must be opened */
87 84
88 signal(SIGTERM, sig_term_handler); 85 signal(SIGTERM, sig_term_handler);
89 signal(SIGPIPE, SIG_IGN); 86 signal(SIGPIPE, SIG_IGN);
90 87
91 local_port = bb_lookup_port(argv[1], "udp", 0); 88 local_port = bb_lookup_port(argv[1], "udp", 0);
92 sock = create_and_bind_dgram_or_die(argv[0], local_port); 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);
93 94
94 if (opt & OPT_u) { /* drop permissions */ 95 if (opt & OPT_u) { /* drop permissions */
95 xsetgid(ugid.gid); 96 xsetgid(ugid.gid);
96 xsetuid(ugid.uid); 97 xsetuid(ugid.uid);
97 } 98 }
98 bb_sanitize_stdio(); /* fd# 1,2 must be opened */
99 close(0);
100 99
101 if (verbose) { 100 if (verbose) {
102 /* we do it only for ":port" cosmetics... oh well */ 101 /* we do it only for ":port" cosmetics... oh well */
103 len_and_sockaddr *lsa = xhost2sockaddr(argv[0], local_port); 102 char *addr = xmalloc_sockaddr2dotted(&localp->sa, localp->len);
104 char *addr = xmalloc_sockaddr2dotted(&lsa->sa, lsa->len); 103 printf("%s: info: listening on %s", applet_name, addr);
105 printf("udpsvd: info: listening on %s", addr);
106 free(addr); 104 free(addr);
107 if (option_mask32 & OPT_u) 105 if (option_mask32 & OPT_u)
108 printf(", uid %u, gid %u", 106 printf(", uid %u, gid %u",
@@ -111,19 +109,8 @@ int udpsvd_main(int argc, char **argv)
111 } 109 }
112 110
113 again: 111 again:
114/* io[0].fd = s; 112 /* if (recvfrom(0, NULL, 0, MSG_PEEK, &remote.sa, &localp->len) < 0) { */
115 io[0].events = IOPAUSE_READ; 113 if (recv_from_to(0, NULL, 0, MSG_PEEK, &remote.sa, &localp->sa, localp->len) < 0) {
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"); 114 bb_perror_msg("recvfrom");
128 goto again; 115 goto again;
129 } 116 }
@@ -136,28 +123,38 @@ int udpsvd_main(int argc, char **argv)
136 while (wait_pid(&wstat, pid) == -1) 123 while (wait_pid(&wstat, pid) == -1)
137 bb_perror_msg("error waiting for child"); 124 bb_perror_msg("error waiting for child");
138 if (verbose) 125 if (verbose)
139 printf("udpsvd: info: end %u\n", pid); 126 printf("%s: info: end %u\n", applet_name, pid);
140 goto again; 127 goto again;
141 } 128 }
142 129
143 /* Child */ 130 /* Child */
144 131
145/* if (recvfrom(sock, 0, 0, MSG_PEEK, (struct sockaddr *)&sock_adr, &sockadr_size) == -1) 132#if 0
146 drop("unable to read from socket"); 133 /* I'd like to make it so that local addr is fixed to localp->sa,
147*/ 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
148 if (verbose) { 141 if (verbose) {
149 local_ip = argv[0]; // TODO: recv_from_to! 142 local_ip = xmalloc_sockaddr2dotted_noport(&localp->sa, localp->len);
150 local_hostname = (char*)"localhost"; 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 }
151 } 148 }
152 149
153 remote_ip = xmalloc_sockaddr2dotted_noport(&sock_adr.sa, sockadr_size); 150 remote_ip = xmalloc_sockaddr2dotted_noport(&remote.sa, localp->len);
154 remote_port = get_nport(&sock_adr.sa); 151 remote_port = get_nport(&remote.sa);
155 remote_port = ntohs(remote_port); 152 remote_port = ntohs(remote_port);
156 if (verbose) { 153 if (verbose)
157 printf("udpsvd: info: pid %u from %s\n", pid, remote_ip); 154 printf("%s: info: pid %u from %s\n", applet_name, pid, remote_ip);
158 } 155
159 if (opt & OPT_h) { 156 if (opt & OPT_h) {
160 remote_hostname = xmalloc_sockaddr2host(&sock_adr.sa, sizeof(sock_adr)); 157 remote_hostname = xmalloc_sockaddr2host(&remote.sa, localp->len);
161 if (!remote_hostname) { 158 if (!remote_hostname) {
162 bb_error_msg("warning: cannot look up hostname for %s", remote_ip); 159 bb_error_msg("warning: cannot look up hostname for %s", remote_ip);
163 remote_hostname = (char*)""; 160 remote_hostname = (char*)"";
@@ -176,15 +173,15 @@ int udpsvd_main(int argc, char **argv)
176 173
177 if (verbose) { 174 if (verbose) {
178#if 0 175#if 0
179 out("udpsvd: info: "); 176 out("%s: info: ", applet_name);
180 switch(ac) { 177 switch(ac) {
181 case IPSVD_DENY: out("deny "); break; 178 case IPSVD_DENY: out("deny "); break;
182 case IPSVD_DEFAULT: case IPSVD_INSTRUCT: out("start "); break; 179 case IPSVD_DEFAULT: case IPSVD_INSTRUCT: out("start "); break;
183 case IPSVD_EXEC: out("exec "); break; 180 case IPSVD_EXEC: out("exec "); break;
184 } 181 }
185#endif 182#endif
186 printf("udpsvd: info: %u %s:%s :%s:%s:%u\n", 183 printf("%s: info: %u %s:%s :%s:%s:%u\n",
187 pid, local_hostname, local_ip, 184 applet_name, pid, local_hostname, local_ip,
188 remote_hostname, remote_ip, remote_port); 185 remote_hostname, remote_ip, remote_port);
189#if 0 186#if 0
190 if (instructs) { 187 if (instructs) {
@@ -202,7 +199,7 @@ int udpsvd_main(int argc, char **argv)
202 199
203#if 0 200#if 0
204 if (ac == IPSVD_DENY) { 201 if (ac == IPSVD_DENY) {
205 recv(s, 0, 0, 0); 202 recv(0, 0, 0, 0);
206 _exit(100); 203 _exit(100);
207 } 204 }
208 if (ac == IPSVD_EXEC) { 205 if (ac == IPSVD_EXEC) {
@@ -213,14 +210,98 @@ int udpsvd_main(int argc, char **argv)
213 run = args; 210 run = args;
214 } else run = prog; 211 } else run = prog;
215#endif 212#endif
216 213 /* Make plain write(1) work for the child by supplying default
217 xmove_fd(sock, 0); 214 * destination address */
215 xconnect(0, &remote.sa, localp->len);
218 dup2(0, 1); 216 dup2(0, 1);
219 217
220 signal(SIGTERM, SIG_DFL); 218 signal(SIGTERM, SIG_DFL);
221 signal(SIGPIPE, SIG_DFL); 219 signal(SIGPIPE, SIG_DFL);
222 argv += 2;
223 220
221 argv += 2;
224 BB_EXECVP(argv[0], argv); 222 BB_EXECVP(argv[0], argv);
225 bb_perror_msg_and_die("exec '%s'", argv[0]); 223 bb_perror_msg_and_die("exec '%s'", argv[0]);
226} 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*/