diff options
author | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-04-02 06:17:45 +0000 |
---|---|---|
committer | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-04-02 06:17:45 +0000 |
commit | e076974fc1f9c841f5a689120bbeb667d76cd5b7 (patch) | |
tree | 8e1f0418114dbbfeb9369fba5ca38935b82f3a89 | |
parent | 3ce5169de28ddad622c2a365d19c516810997ecd (diff) | |
download | busybox-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.c | 221 |
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 | |||
25 | unsigned verbose; | ||
26 | |||
27 | static void sig_term_handler(int sig) | ||
28 | { | ||
29 | if (verbose) | ||
30 | printf("udpsvd: info: sigterm received, exit\n"); | ||
31 | exit(0); | ||
32 | } | ||
33 | |||
34 | int udpsvd_main(int argc, char **argv); | ||
35 | int 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 | } | ||