diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-04-04 10:16:15 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-04-04 10:16:15 +0000 |
commit | 64a15124e71b89dca7b00ba76a2ca821e69b5daa (patch) | |
tree | fe1aaf3729d9d7d2f862927fe2009b80d241d730 /ipsvd | |
parent | 02fd66885cfab933b8fcd747f680c9c0c7e61ff2 (diff) | |
download | busybox-w32-64a15124e71b89dca7b00ba76a2ca821e69b5daa.tar.gz busybox-w32-64a15124e71b89dca7b00ba76a2ca821e69b5daa.tar.bz2 busybox-w32-64a15124e71b89dca7b00ba76a2ca821e69b5daa.zip |
ipsvd: use IP:PORT syntax for environment vars. Pros:
1. it's saner (matches internal libc sockaddr abstraction).
2. it's smaller.
Cons: not compatible with smarden's ipsvd.
Fix IPv6 define typos.
Stop interpreting options in prog's args.
Code size -162 bytes.
Diffstat (limited to 'ipsvd')
-rw-r--r-- | ipsvd/tcpudp.c | 120 | ||||
-rw-r--r-- | ipsvd/udp_io.c | 25 |
2 files changed, 74 insertions, 71 deletions
diff --git a/ipsvd/tcpudp.c b/ipsvd/tcpudp.c index 6e8ec323c..9f098c32e 100644 --- a/ipsvd/tcpudp.c +++ b/ipsvd/tcpudp.c | |||
@@ -22,9 +22,9 @@ | |||
22 | * | 22 | * |
23 | * udp server is hacked up by reusing TCP code. It has the following | 23 | * udp server is hacked up by reusing TCP code. It has the following |
24 | * limitation inherent in Unix DGRAM sockets implementation: | 24 | * limitation inherent in Unix DGRAM sockets implementation: |
25 | * - local IP address is reptrieved (using recvmsg voodoo) but | 25 | * - local IP address is retrieved (using recvmsg voodoo) but |
26 | * child's socket is not bound to it (bind cannot be called on | 26 | * child's socket is not bound to it (bind cannot be called on |
27 | * already bound socket). Thus you still can get outgoing packets | 27 | * already bound socket). Thus it still can emit outgoing packets |
28 | * with wrong sorce IP... | 28 | * with wrong sorce IP... |
29 | * - don't know how to retrieve ORIGDST for udp. | 29 | * - don't know how to retrieve ORIGDST for udp. |
30 | */ | 30 | */ |
@@ -100,7 +100,7 @@ enum { | |||
100 | 100 | ||
101 | static void connection_status(void) | 101 | static void connection_status(void) |
102 | { | 102 | { |
103 | /* UDP and "only 1 client max" TCP don't need this */ | 103 | /* "only 1 client max" don't need this */ |
104 | if (cmax > 1) | 104 | if (cmax > 1) |
105 | printf("%s: info: status %u/%u\n", applet_name, cnum, cmax); | 105 | printf("%s: info: status %u/%u\n", applet_name, cnum, cmax); |
106 | } | 106 | } |
@@ -131,34 +131,35 @@ int tcpudpsvd_main(int argc, char **argv) | |||
131 | const char *instructs; | 131 | const char *instructs; |
132 | char *msg_per_host = NULL; | 132 | char *msg_per_host = NULL; |
133 | unsigned len_per_host = len_per_host; /* gcc */ | 133 | unsigned len_per_host = len_per_host; /* gcc */ |
134 | int need_hostnames, need_remote_ip; | 134 | #ifndef SSLSVD |
135 | int tcp; | 135 | struct bb_uidgid_t ugid; |
136 | #endif | ||
137 | bool need_hostnames, need_remote_ip, tcp; | ||
138 | uint16_t local_port; | ||
139 | char *local_hostname = NULL; | ||
140 | char *remote_hostname = (char*)""; /* "" used if no -h */ | ||
141 | char *local_addr = local_addr; /* gcc */ | ||
142 | char *remote_addr = remote_addr; /* gcc */ | ||
143 | char *remote_ip = remote_addr; /* gcc */ | ||
144 | len_and_sockaddr *lsa; | ||
145 | len_and_sockaddr local, remote; | ||
146 | socklen_t sa_len; | ||
136 | int pid; | 147 | int pid; |
137 | int sock; | 148 | int sock; |
138 | int conn; | 149 | int conn; |
139 | unsigned backlog = 20; | 150 | unsigned backlog = 20; |
140 | len_and_sockaddr *lsa; | 151 | |
141 | len_and_sockaddr local, remote; | ||
142 | uint16_t local_port; | ||
143 | uint16_t remote_port = remote_port; /* gcc */ | ||
144 | char *local_hostname = NULL; | ||
145 | char *remote_hostname = (char*)""; /* "" used if no -h */ | ||
146 | char *local_ip = local_ip; /* gcc */ | ||
147 | char *remote_ip = remote_ip; /* gcc */ | ||
148 | #ifndef SSLSVD | ||
149 | struct bb_uidgid_t ugid; | ||
150 | #endif | ||
151 | tcp = (applet_name[0] == 't'); | 152 | tcp = (applet_name[0] == 't'); |
152 | 153 | ||
153 | /* 3+ args, -i at most once, -p implies -h, -v is counter */ | 154 | /* 3+ args, -i at most once, -p implies -h, -v is counter */ |
154 | opt_complementary = "-3:?:i--i:ph:vv"; | 155 | opt_complementary = "-3:?:i--i:ph:vv"; |
155 | #ifdef SSLSVD | 156 | #ifdef SSLSVD |
156 | getopt32(argc, argv, "c:C:i:x:u:l:Eb:hpt:vU:/:Z:K:", | 157 | getopt32(argc, argv, "+c:C:i:x:u:l:Eb:hpt:vU:/:Z:K:", |
157 | &str_c, &str_C, &instructs, &instructs, &user, &local_hostname, | 158 | &str_c, &str_C, &instructs, &instructs, &user, &local_hostname, |
158 | &str_b, &str_t, &ssluser, &root, &cert, &key, &verbose | 159 | &str_b, &str_t, &ssluser, &root, &cert, &key, &verbose |
159 | ); | 160 | ); |
160 | #else | 161 | #else |
161 | getopt32(argc, argv, "c:C:i:x:u:l:Eb:hpt:v", | 162 | getopt32(argc, argv, "+c:C:i:x:u:l:Eb:hpt:v", |
162 | &str_c, &str_C, &instructs, &instructs, &user, &local_hostname, | 163 | &str_c, &str_C, &instructs, &instructs, &user, &local_hostname, |
163 | &str_b, &str_t, &verbose | 164 | &str_b, &str_t, &verbose |
164 | ); | 165 | ); |
@@ -213,10 +214,8 @@ int tcpudpsvd_main(int argc, char **argv) | |||
213 | if (option_mask32 & OPT_u) | 214 | if (option_mask32 & OPT_u) |
214 | if (!uidgid_get(&sslugid, ssluser, 1)) { | 215 | if (!uidgid_get(&sslugid, ssluser, 1)) { |
215 | if (errno) { | 216 | if (errno) { |
216 | xfunc_exitcode = 100; | ||
217 | bb_perror_msg_and_die("fatal: cannot get user/group: %s", ssluser); | 217 | bb_perror_msg_and_die("fatal: cannot get user/group: %s", ssluser); |
218 | } | 218 | } |
219 | xfunc_exitcode = 111; | ||
220 | bb_error_msg_and_die("fatal: unknown user/group '%s'", ssluser); | 219 | bb_error_msg_and_die("fatal: unknown user/group '%s'", ssluser); |
221 | } | 220 | } |
222 | if (!cert) cert = "./cert.pem"; | 221 | if (!cert) cert = "./cert.pem"; |
@@ -244,7 +243,8 @@ int tcpudpsvd_main(int argc, char **argv) | |||
244 | lsa = xhost2sockaddr(argv[0], local_port); | 243 | lsa = xhost2sockaddr(argv[0], local_port); |
245 | sock = xsocket(lsa->sa.sa_family, tcp ? SOCK_STREAM : SOCK_DGRAM, 0); | 244 | sock = xsocket(lsa->sa.sa_family, tcp ? SOCK_STREAM : SOCK_DGRAM, 0); |
246 | setsockopt_reuseaddr(sock); | 245 | setsockopt_reuseaddr(sock); |
247 | xbind(sock, &lsa->sa, lsa->len); | 246 | sa_len = lsa->len; /* I presume sockaddr len stays the same */ |
247 | xbind(sock, &lsa->sa, sa_len); | ||
248 | if (tcp) | 248 | if (tcp) |
249 | xlisten(sock, backlog); | 249 | xlisten(sock, backlog); |
250 | else /* udp: needed for recv_from_to to work: */ | 250 | else /* udp: needed for recv_from_to to work: */ |
@@ -260,9 +260,7 @@ int tcpudpsvd_main(int argc, char **argv) | |||
260 | #endif | 260 | #endif |
261 | 261 | ||
262 | if (verbose) { | 262 | if (verbose) { |
263 | /* we do it only for ":port" cosmetics... oh well */ | 263 | char *addr = xmalloc_sockaddr2dotted(&lsa->sa, sa_len); |
264 | char *addr = xmalloc_sockaddr2dotted(&lsa->sa, lsa->len); | ||
265 | |||
266 | printf("%s: info: listening on %s", applet_name, addr); | 264 | printf("%s: info: listening on %s", applet_name, addr); |
267 | free(addr); | 265 | free(addr); |
268 | #ifndef SSLSVD | 266 | #ifndef SSLSVD |
@@ -287,10 +285,14 @@ int tcpudpsvd_main(int argc, char **argv) | |||
287 | again2: | 285 | again2: |
288 | sig_unblock(SIGCHLD); | 286 | sig_unblock(SIGCHLD); |
289 | if (tcp) { | 287 | if (tcp) { |
290 | remote.len = lsa->len; | 288 | remote.len = sa_len; |
291 | conn = accept(sock, &remote.sa, &remote.len); | 289 | conn = accept(sock, &remote.sa, &remote.len); |
292 | } else | 290 | } else { |
293 | conn = recv_from_to(sock, NULL, 0, MSG_PEEK, &remote.sa, &local.sa, lsa->len); | 291 | /* In case we won't be able to recover local below. |
292 | * Also sets port - recv_from_to is unable to do it. */ | ||
293 | local = *lsa; | ||
294 | conn = recv_from_to(sock, NULL, 0, MSG_PEEK, &remote.sa, &local.sa, sa_len); | ||
295 | } | ||
294 | sig_block(SIGCHLD); | 296 | sig_block(SIGCHLD); |
295 | if (conn < 0) { | 297 | if (conn < 0) { |
296 | if (errno != EINTR) | 298 | if (errno != EINTR) |
@@ -302,7 +304,7 @@ int tcpudpsvd_main(int argc, char **argv) | |||
302 | if (max_per_host) { | 304 | if (max_per_host) { |
303 | /* Drop connection immediately if cur_per_host > max_per_host | 305 | /* Drop connection immediately if cur_per_host > max_per_host |
304 | * (minimizing load under SYN flood) */ | 306 | * (minimizing load under SYN flood) */ |
305 | remote_ip = xmalloc_sockaddr2dotted_noport(&remote.sa, lsa->len); | 307 | remote_ip = xmalloc_sockaddr2dotted_noport(&remote.sa, sa_len); |
306 | cur_per_host = ipsvd_perhost_add(remote_ip, max_per_host, &hccp); | 308 | cur_per_host = ipsvd_perhost_add(remote_ip, max_per_host, &hccp); |
307 | if (cur_per_host > max_per_host) { | 309 | if (cur_per_host > max_per_host) { |
308 | /* ipsvd_perhost_add detected that max is exceeded | 310 | /* ipsvd_perhost_add detected that max is exceeded |
@@ -319,16 +321,21 @@ int tcpudpsvd_main(int argc, char **argv) | |||
319 | 321 | ||
320 | if (!tcp) { | 322 | if (!tcp) { |
321 | /* Voodoo magic: making udp sockets each receive its own | 323 | /* Voodoo magic: making udp sockets each receive its own |
322 | * packets is not trivial */ | 324 | * packets is not trivial, and I still not sure |
325 | * I do it 100% right. | ||
326 | * 1) we have to do it before fork() | ||
327 | * 2) order is important - is it right now? */ | ||
323 | 328 | ||
324 | /* Make plain write work for this socket by supplying default | 329 | /* Make plain write/send work for this socket by supplying default |
325 | * destination address. This also restricts incoming packets | 330 | * destination address. This also restricts incoming packets |
326 | * to ones coming from this remote IP. */ | 331 | * to ones coming from this remote IP. */ |
327 | xconnect(0, &remote.sa, lsa->len); | 332 | xconnect(0, &remote.sa, sa_len); |
333 | /* hole? at this point we have no wildcard udp socket... | ||
334 | * can this cause clients to get "port unreachable" icmp? */ | ||
328 | /* Open new non-connected UDP socket for further clients */ | 335 | /* Open new non-connected UDP socket for further clients */ |
329 | sock = xsocket(lsa->sa.sa_family, tcp ? SOCK_STREAM : SOCK_DGRAM, 0); | 336 | sock = xsocket(lsa->sa.sa_family, tcp ? SOCK_STREAM : SOCK_DGRAM, 0); |
330 | setsockopt_reuseaddr(sock); | 337 | setsockopt_reuseaddr(sock); |
331 | xbind(sock, &lsa->sa, lsa->len); | 338 | xbind(sock, &lsa->sa, sa_len); |
332 | socket_want_pktinfo(sock); | 339 | socket_want_pktinfo(sock); |
333 | } | 340 | } |
334 | 341 | ||
@@ -355,50 +362,44 @@ int tcpudpsvd_main(int argc, char **argv) | |||
355 | if (tcp) | 362 | if (tcp) |
356 | close(sock); | 363 | close(sock); |
357 | 364 | ||
358 | if (need_remote_ip) { | 365 | if (need_remote_ip) |
359 | if (!max_per_host) | 366 | remote_addr = xmalloc_sockaddr2dotted(&remote.sa, sa_len); |
360 | remote_ip = xmalloc_sockaddr2dotted_noport(&remote.sa, lsa->len); | ||
361 | /* else it is already done */ | ||
362 | remote_port = get_nport(&remote.sa); | ||
363 | remote_port = ntohs(remote_port); | ||
364 | } | ||
365 | 367 | ||
366 | if (need_hostnames) { | 368 | if (need_hostnames) { |
367 | if (option_mask32 & OPT_h) { | 369 | if (option_mask32 & OPT_h) { |
368 | remote_hostname = xmalloc_sockaddr2host(&remote.sa, lsa->len); | 370 | remote_hostname = xmalloc_sockaddr2host_noport(&remote.sa, sa_len); |
369 | if (!remote_hostname) { | 371 | if (!remote_hostname) { |
370 | bb_error_msg("warning: cannot look up hostname for %s", remote_ip); | 372 | bb_error_msg("warning: cannot look up hostname for %s", remote_addr); |
371 | remote_hostname = (char*)""; | 373 | remote_hostname = (char*)""; |
372 | } | 374 | } |
373 | } | 375 | } |
374 | /* Find out local IP peer connected to. | 376 | /* Find out local IP peer connected to. |
375 | * Errors ignored (I'm not paranoid enough to imagine kernel | 377 | * Errors ignored (I'm not paranoid enough to imagine kernel |
376 | * which doesn't know local IP). */ | 378 | * which doesn't know local IP). */ |
377 | if (tcp) | 379 | if (tcp) { |
380 | local.len = sa_len; | ||
378 | getsockname(0, &local.sa, &local.len); | 381 | getsockname(0, &local.sa, &local.len); |
379 | local_ip = xmalloc_sockaddr2dotted_noport(&local.sa, lsa->len); | 382 | } |
380 | local_port = get_nport(&local.sa); | 383 | local_addr = xmalloc_sockaddr2dotted(&local.sa, sa_len); |
381 | local_port = ntohs(local_port); | ||
382 | if (!local_hostname) { | 384 | if (!local_hostname) { |
383 | local_hostname = xmalloc_sockaddr2host_noport(&local.sa, lsa->len); | 385 | local_hostname = xmalloc_sockaddr2host_noport(&local.sa, sa_len); |
384 | if (!local_hostname) | 386 | if (!local_hostname) |
385 | bb_error_msg_and_die("warning: cannot look up hostname for %s"+9, local_ip); | 387 | bb_error_msg_and_die("warning: cannot look up hostname for %s"+9, local_addr); |
386 | } | 388 | } |
387 | } | 389 | } |
388 | 390 | ||
389 | if (verbose) { | 391 | if (verbose) { |
390 | pid = getpid(); | 392 | pid = getpid(); |
391 | printf("%s: info: pid %u from %s\n", applet_name, pid, remote_ip); | 393 | printf("%s: info: pid %u from %s\n", applet_name, pid, remote_addr); |
392 | if (max_per_host) | 394 | if (max_per_host) |
393 | printf("%s: info: concurrency %u %s %u/%u\n", | 395 | printf("%s: info: concurrency %u %s %u/%u\n", |
394 | applet_name, pid, remote_ip, cur_per_host, max_per_host); | 396 | applet_name, pid, remote_ip, cur_per_host, max_per_host); |
395 | printf("%s: info: start %u %s:%s :%s:%s:%u\n", | 397 | printf("%s: info: start %u %s:%s :%s:%s\n", |
396 | applet_name, pid, | 398 | applet_name, pid, |
397 | local_hostname, local_ip, | 399 | local_hostname, local_addr, |
398 | remote_hostname, remote_ip, (unsigned)remote_port); | 400 | remote_hostname, remote_addr); |
399 | } | 401 | } |
400 | 402 | ||
401 | // TODO: stop splitiing port# from IP? | ||
402 | if (!(option_mask32 & OPT_E)) { | 403 | if (!(option_mask32 & OPT_E)) { |
403 | /* setup ucspi env */ | 404 | /* setup ucspi env */ |
404 | const char *proto = tcp ? "TCP" : "UDP"; | 405 | const char *proto = tcp ? "TCP" : "UDP"; |
@@ -408,19 +409,14 @@ int tcpudpsvd_main(int argc, char **argv) | |||
408 | * an outbond connection to local handler, and it needs | 409 | * an outbond connection to local handler, and it needs |
409 | * to know where it originally tried to connect */ | 410 | * to know where it originally tried to connect */ |
410 | if (tcp && getsockopt(0, SOL_IP, SO_ORIGINAL_DST, &lsa->sa, &lsa->len) == 0) { | 411 | if (tcp && getsockopt(0, SOL_IP, SO_ORIGINAL_DST, &lsa->sa, &lsa->len) == 0) { |
411 | char *ip = xmalloc_sockaddr2dotted_noport(&lsa->sa, lsa->len); | 412 | char *addr = xmalloc_sockaddr2dotted(&lsa->sa, sa_len); |
412 | unsigned port = get_nport(&lsa->sa); | 413 | xsetenv("TCPORIGDSTADDR", addr); |
413 | port = ntohs(port); | 414 | free(addr); |
414 | xsetenv("TCPORIGDSTIP", ip); | ||
415 | xsetenv("TCPORIGDSTPORT", utoa(port)); | ||
416 | free(ip); | ||
417 | } | 415 | } |
418 | xsetenv("PROTO", proto); | 416 | xsetenv("PROTO", proto); |
419 | xsetenv_proto(proto, "LOCALIP", local_ip); | 417 | xsetenv_proto(proto, "LOCALADDR", local_addr); |
420 | xsetenv_proto(proto, "LOCALPORT", utoa(local_port)); | ||
421 | xsetenv_proto(proto, "LOCALHOST", local_hostname); | 418 | xsetenv_proto(proto, "LOCALHOST", local_hostname); |
422 | xsetenv_proto(proto, "REMOTEIP", remote_ip); | 419 | xsetenv_proto(proto, "REMOTEADDR", remote_addr); |
423 | xsetenv_proto(proto, "REMOTEPORT", utoa(remote_port)); | ||
424 | if (option_mask32 & OPT_h) { | 420 | if (option_mask32 & OPT_h) { |
425 | xsetenv_proto(proto, "REMOTEHOST", remote_hostname); | 421 | xsetenv_proto(proto, "REMOTEHOST", remote_hostname); |
426 | } | 422 | } |
diff --git a/ipsvd/udp_io.c b/ipsvd/udp_io.c index 68999d44d..2efc15913 100644 --- a/ipsvd/udp_io.c +++ b/ipsvd/udp_io.c | |||
@@ -18,12 +18,13 @@ socket_want_pktinfo(int fd) | |||
18 | #ifdef IP_PKTINFO | 18 | #ifdef IP_PKTINFO |
19 | setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &const_int_1, sizeof(int)); | 19 | setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &const_int_1, sizeof(int)); |
20 | #endif | 20 | #endif |
21 | #ifdef IPV6_PKTINFO | 21 | #if ENABLE_FEATURE_IPV6 && defined(IPV6_PKTINFO) |
22 | setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &const_int_1, sizeof(int)); | 22 | setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &const_int_1, sizeof(int)); |
23 | #endif | 23 | #endif |
24 | } | 24 | } |
25 | 25 | ||
26 | 26 | ||
27 | #ifdef UNUSED | ||
27 | ssize_t | 28 | ssize_t |
28 | send_to_from(int fd, void *buf, size_t len, int flags, | 29 | send_to_from(int fd, void *buf, size_t len, int flags, |
29 | const struct sockaddr *from, const struct sockaddr *to, | 30 | const struct sockaddr *from, const struct sockaddr *to, |
@@ -34,8 +35,11 @@ send_to_from(int fd, void *buf, size_t len, int flags, | |||
34 | #else | 35 | #else |
35 | struct iovec iov[1]; | 36 | struct iovec iov[1]; |
36 | struct msghdr msg; | 37 | struct msghdr msg; |
37 | char cbuf[LSA_SIZEOF_SA]; | 38 | char cbuf[sizeof(struct in_pktinfo) |
38 | /* actually, max(sizeof(in_pktinfo),sizeof(in6_pktinfo)) */ | 39 | #if ENABLE_FEATURE_IPV6 && defined(IPV6_PKTINFO) |
40 | | sizeof(struct in6_pktinfo) /* (a|b) is poor man's max(a,b) */ | ||
41 | #endif | ||
42 | ]; | ||
39 | struct cmsghdr* cmsgptr; | 43 | struct cmsghdr* cmsgptr; |
40 | 44 | ||
41 | if (from->sa_family != AF_INET | 45 | if (from->sa_family != AF_INET |
@@ -73,11 +77,11 @@ send_to_from(int fd, void *buf, size_t len, int flags, | |||
73 | /* pktptr->ipi_ifindex = 0; -- already done by memset(cbuf...) */ | 77 | /* pktptr->ipi_ifindex = 0; -- already done by memset(cbuf...) */ |
74 | pktptr->ipi_spec_dst = ((struct sockaddr_in*)from)->sin_addr; | 78 | pktptr->ipi_spec_dst = ((struct sockaddr_in*)from)->sin_addr; |
75 | } | 79 | } |
76 | #if ENABLE_FEATURE_IPV6 && defined(IP6_PKTINFO) | 80 | #if ENABLE_FEATURE_IPV6 && defined(IPV6_PKTINFO) |
77 | else if (to->sa_family == AF_INET6 && from->sa_family == AF_INET6) { | 81 | else if (to->sa_family == AF_INET6 && from->sa_family == AF_INET6) { |
78 | struct in6_pktinfo *pktptr; | 82 | struct in6_pktinfo *pktptr; |
79 | cmsgptr->cmsg_level = IPPROTO_IPV6; | 83 | cmsgptr->cmsg_level = IPPROTO_IPV6; |
80 | cmsgptr->cmsg_type = IP6_PKTINFO; | 84 | cmsgptr->cmsg_type = IPV6_PKTINFO; |
81 | cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); | 85 | cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); |
82 | pktptr = (struct in6_pktinfo *)(CMSG_DATA(cmsgptr)); | 86 | pktptr = (struct in6_pktinfo *)(CMSG_DATA(cmsgptr)); |
83 | /* pktptr->ipi6_ifindex = 0; -- already done by memset(cbuf...) */ | 87 | /* pktptr->ipi6_ifindex = 0; -- already done by memset(cbuf...) */ |
@@ -87,8 +91,12 @@ send_to_from(int fd, void *buf, size_t len, int flags, | |||
87 | return sendmsg(fd, &msg, flags); | 91 | return sendmsg(fd, &msg, flags); |
88 | #endif | 92 | #endif |
89 | } | 93 | } |
94 | #endif /* UNUSED */ | ||
90 | 95 | ||
91 | /* NB: this will never set port# in *to! */ | 96 | /* NB: this will never set port# in 'to'! |
97 | * _Only_ IP/IPv6 address part of 'to' is _maybe_ modified. | ||
98 | * Typical usage is to preinit it with "default" value | ||
99 | * before calling recv_from_to(). */ | ||
92 | ssize_t | 100 | ssize_t |
93 | recv_from_to(int fd, void *buf, size_t len, int flags, | 101 | recv_from_to(int fd, void *buf, size_t len, int flags, |
94 | struct sockaddr *from, struct sockaddr *to, | 102 | struct sockaddr *from, struct sockaddr *to, |
@@ -123,7 +131,6 @@ recv_from_to(int fd, void *buf, size_t len, int flags, | |||
123 | return recv_length; | 131 | return recv_length; |
124 | 132 | ||
125 | /* Here we try to retrieve destination IP and memorize it */ | 133 | /* Here we try to retrieve destination IP and memorize it */ |
126 | memset(to, 0, sa_size); | ||
127 | for (cmsgptr = CMSG_FIRSTHDR(&msg); | 134 | for (cmsgptr = CMSG_FIRSTHDR(&msg); |
128 | cmsgptr != NULL; | 135 | cmsgptr != NULL; |
129 | cmsgptr = CMSG_NXTHDR(&msg, cmsgptr) | 136 | cmsgptr = CMSG_NXTHDR(&msg, cmsgptr) |
@@ -138,9 +145,9 @@ recv_from_to(int fd, void *buf, size_t len, int flags, | |||
138 | #undef pktinfo | 145 | #undef pktinfo |
139 | break; | 146 | break; |
140 | } | 147 | } |
141 | #if ENABLE_FEATURE_IPV6 && defined(IP6_PKTINFO) | 148 | #if ENABLE_FEATURE_IPV6 && defined(IPV6_PKTINFO) |
142 | if (cmsgptr->cmsg_level == IPPROTO_IPV6 | 149 | if (cmsgptr->cmsg_level == IPPROTO_IPV6 |
143 | && cmsgptr->cmsg_type == IP6_PKTINFO | 150 | && cmsgptr->cmsg_type == IPV6_PKTINFO |
144 | ) { | 151 | ) { |
145 | #define pktinfo(cmsgptr) ( (struct in6_pktinfo*)(CMSG_DATA(cmsgptr)) ) | 152 | #define pktinfo(cmsgptr) ( (struct in6_pktinfo*)(CMSG_DATA(cmsgptr)) ) |
146 | to->sa_family = AF_INET6; | 153 | to->sa_family = AF_INET6; |