mirror of
https://github.com/sheumann/hush.git
synced 2025-01-02 09:31:26 +00:00
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.
This commit is contained in:
parent
02fd66885c
commit
64a15124e7
120
ipsvd/tcpudp.c
120
ipsvd/tcpudp.c
@ -22,9 +22,9 @@
|
|||||||
*
|
*
|
||||||
* udp server is hacked up by reusing TCP code. It has the following
|
* udp server is hacked up by reusing TCP code. It has the following
|
||||||
* limitation inherent in Unix DGRAM sockets implementation:
|
* limitation inherent in Unix DGRAM sockets implementation:
|
||||||
* - local IP address is reptrieved (using recvmsg voodoo) but
|
* - local IP address is retrieved (using recvmsg voodoo) but
|
||||||
* child's socket is not bound to it (bind cannot be called on
|
* child's socket is not bound to it (bind cannot be called on
|
||||||
* already bound socket). Thus you still can get outgoing packets
|
* already bound socket). Thus it still can emit outgoing packets
|
||||||
* with wrong sorce IP...
|
* with wrong sorce IP...
|
||||||
* - don't know how to retrieve ORIGDST for udp.
|
* - don't know how to retrieve ORIGDST for udp.
|
||||||
*/
|
*/
|
||||||
@ -100,7 +100,7 @@ enum {
|
|||||||
|
|
||||||
static void connection_status(void)
|
static void connection_status(void)
|
||||||
{
|
{
|
||||||
/* UDP and "only 1 client max" TCP don't need this */
|
/* "only 1 client max" don't need this */
|
||||||
if (cmax > 1)
|
if (cmax > 1)
|
||||||
printf("%s: info: status %u/%u\n", applet_name, cnum, cmax);
|
printf("%s: info: status %u/%u\n", applet_name, cnum, cmax);
|
||||||
}
|
}
|
||||||
@ -131,34 +131,35 @@ int tcpudpsvd_main(int argc, char **argv)
|
|||||||
const char *instructs;
|
const char *instructs;
|
||||||
char *msg_per_host = NULL;
|
char *msg_per_host = NULL;
|
||||||
unsigned len_per_host = len_per_host; /* gcc */
|
unsigned len_per_host = len_per_host; /* gcc */
|
||||||
int need_hostnames, need_remote_ip;
|
#ifndef SSLSVD
|
||||||
int tcp;
|
struct bb_uidgid_t ugid;
|
||||||
|
#endif
|
||||||
|
bool need_hostnames, need_remote_ip, tcp;
|
||||||
|
uint16_t local_port;
|
||||||
|
char *local_hostname = NULL;
|
||||||
|
char *remote_hostname = (char*)""; /* "" used if no -h */
|
||||||
|
char *local_addr = local_addr; /* gcc */
|
||||||
|
char *remote_addr = remote_addr; /* gcc */
|
||||||
|
char *remote_ip = remote_addr; /* gcc */
|
||||||
|
len_and_sockaddr *lsa;
|
||||||
|
len_and_sockaddr local, remote;
|
||||||
|
socklen_t sa_len;
|
||||||
int pid;
|
int pid;
|
||||||
int sock;
|
int sock;
|
||||||
int conn;
|
int conn;
|
||||||
unsigned backlog = 20;
|
unsigned backlog = 20;
|
||||||
len_and_sockaddr *lsa;
|
|
||||||
len_and_sockaddr local, remote;
|
|
||||||
uint16_t local_port;
|
|
||||||
uint16_t remote_port = remote_port; /* gcc */
|
|
||||||
char *local_hostname = NULL;
|
|
||||||
char *remote_hostname = (char*)""; /* "" used if no -h */
|
|
||||||
char *local_ip = local_ip; /* gcc */
|
|
||||||
char *remote_ip = remote_ip; /* gcc */
|
|
||||||
#ifndef SSLSVD
|
|
||||||
struct bb_uidgid_t ugid;
|
|
||||||
#endif
|
|
||||||
tcp = (applet_name[0] == 't');
|
tcp = (applet_name[0] == 't');
|
||||||
|
|
||||||
/* 3+ args, -i at most once, -p implies -h, -v is counter */
|
/* 3+ args, -i at most once, -p implies -h, -v is counter */
|
||||||
opt_complementary = "-3:?:i--i:ph:vv";
|
opt_complementary = "-3:?:i--i:ph:vv";
|
||||||
#ifdef SSLSVD
|
#ifdef SSLSVD
|
||||||
getopt32(argc, argv, "c:C:i:x:u:l:Eb:hpt:vU:/:Z:K:",
|
getopt32(argc, argv, "+c:C:i:x:u:l:Eb:hpt:vU:/:Z:K:",
|
||||||
&str_c, &str_C, &instructs, &instructs, &user, &local_hostname,
|
&str_c, &str_C, &instructs, &instructs, &user, &local_hostname,
|
||||||
&str_b, &str_t, &ssluser, &root, &cert, &key, &verbose
|
&str_b, &str_t, &ssluser, &root, &cert, &key, &verbose
|
||||||
);
|
);
|
||||||
#else
|
#else
|
||||||
getopt32(argc, argv, "c:C:i:x:u:l:Eb:hpt:v",
|
getopt32(argc, argv, "+c:C:i:x:u:l:Eb:hpt:v",
|
||||||
&str_c, &str_C, &instructs, &instructs, &user, &local_hostname,
|
&str_c, &str_C, &instructs, &instructs, &user, &local_hostname,
|
||||||
&str_b, &str_t, &verbose
|
&str_b, &str_t, &verbose
|
||||||
);
|
);
|
||||||
@ -213,10 +214,8 @@ int tcpudpsvd_main(int argc, char **argv)
|
|||||||
if (option_mask32 & OPT_u)
|
if (option_mask32 & OPT_u)
|
||||||
if (!uidgid_get(&sslugid, ssluser, 1)) {
|
if (!uidgid_get(&sslugid, ssluser, 1)) {
|
||||||
if (errno) {
|
if (errno) {
|
||||||
xfunc_exitcode = 100;
|
|
||||||
bb_perror_msg_and_die("fatal: cannot get user/group: %s", ssluser);
|
bb_perror_msg_and_die("fatal: cannot get user/group: %s", ssluser);
|
||||||
}
|
}
|
||||||
xfunc_exitcode = 111;
|
|
||||||
bb_error_msg_and_die("fatal: unknown user/group '%s'", ssluser);
|
bb_error_msg_and_die("fatal: unknown user/group '%s'", ssluser);
|
||||||
}
|
}
|
||||||
if (!cert) cert = "./cert.pem";
|
if (!cert) cert = "./cert.pem";
|
||||||
@ -244,7 +243,8 @@ int tcpudpsvd_main(int argc, char **argv)
|
|||||||
lsa = xhost2sockaddr(argv[0], local_port);
|
lsa = xhost2sockaddr(argv[0], local_port);
|
||||||
sock = xsocket(lsa->sa.sa_family, tcp ? SOCK_STREAM : SOCK_DGRAM, 0);
|
sock = xsocket(lsa->sa.sa_family, tcp ? SOCK_STREAM : SOCK_DGRAM, 0);
|
||||||
setsockopt_reuseaddr(sock);
|
setsockopt_reuseaddr(sock);
|
||||||
xbind(sock, &lsa->sa, lsa->len);
|
sa_len = lsa->len; /* I presume sockaddr len stays the same */
|
||||||
|
xbind(sock, &lsa->sa, sa_len);
|
||||||
if (tcp)
|
if (tcp)
|
||||||
xlisten(sock, backlog);
|
xlisten(sock, backlog);
|
||||||
else /* udp: needed for recv_from_to to work: */
|
else /* udp: needed for recv_from_to to work: */
|
||||||
@ -260,9 +260,7 @@ int tcpudpsvd_main(int argc, char **argv)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
/* we do it only for ":port" cosmetics... oh well */
|
char *addr = xmalloc_sockaddr2dotted(&lsa->sa, sa_len);
|
||||||
char *addr = xmalloc_sockaddr2dotted(&lsa->sa, lsa->len);
|
|
||||||
|
|
||||||
printf("%s: info: listening on %s", applet_name, addr);
|
printf("%s: info: listening on %s", applet_name, addr);
|
||||||
free(addr);
|
free(addr);
|
||||||
#ifndef SSLSVD
|
#ifndef SSLSVD
|
||||||
@ -287,10 +285,14 @@ int tcpudpsvd_main(int argc, char **argv)
|
|||||||
again2:
|
again2:
|
||||||
sig_unblock(SIGCHLD);
|
sig_unblock(SIGCHLD);
|
||||||
if (tcp) {
|
if (tcp) {
|
||||||
remote.len = lsa->len;
|
remote.len = sa_len;
|
||||||
conn = accept(sock, &remote.sa, &remote.len);
|
conn = accept(sock, &remote.sa, &remote.len);
|
||||||
} else
|
} else {
|
||||||
conn = recv_from_to(sock, NULL, 0, MSG_PEEK, &remote.sa, &local.sa, lsa->len);
|
/* In case we won't be able to recover local below.
|
||||||
|
* Also sets port - recv_from_to is unable to do it. */
|
||||||
|
local = *lsa;
|
||||||
|
conn = recv_from_to(sock, NULL, 0, MSG_PEEK, &remote.sa, &local.sa, sa_len);
|
||||||
|
}
|
||||||
sig_block(SIGCHLD);
|
sig_block(SIGCHLD);
|
||||||
if (conn < 0) {
|
if (conn < 0) {
|
||||||
if (errno != EINTR)
|
if (errno != EINTR)
|
||||||
@ -302,7 +304,7 @@ int tcpudpsvd_main(int argc, char **argv)
|
|||||||
if (max_per_host) {
|
if (max_per_host) {
|
||||||
/* Drop connection immediately if cur_per_host > max_per_host
|
/* Drop connection immediately if cur_per_host > max_per_host
|
||||||
* (minimizing load under SYN flood) */
|
* (minimizing load under SYN flood) */
|
||||||
remote_ip = xmalloc_sockaddr2dotted_noport(&remote.sa, lsa->len);
|
remote_ip = xmalloc_sockaddr2dotted_noport(&remote.sa, sa_len);
|
||||||
cur_per_host = ipsvd_perhost_add(remote_ip, max_per_host, &hccp);
|
cur_per_host = ipsvd_perhost_add(remote_ip, max_per_host, &hccp);
|
||||||
if (cur_per_host > max_per_host) {
|
if (cur_per_host > max_per_host) {
|
||||||
/* ipsvd_perhost_add detected that max is exceeded
|
/* ipsvd_perhost_add detected that max is exceeded
|
||||||
@ -319,16 +321,21 @@ int tcpudpsvd_main(int argc, char **argv)
|
|||||||
|
|
||||||
if (!tcp) {
|
if (!tcp) {
|
||||||
/* Voodoo magic: making udp sockets each receive its own
|
/* Voodoo magic: making udp sockets each receive its own
|
||||||
* packets is not trivial */
|
* packets is not trivial, and I still not sure
|
||||||
|
* I do it 100% right.
|
||||||
|
* 1) we have to do it before fork()
|
||||||
|
* 2) order is important - is it right now? */
|
||||||
|
|
||||||
/* Make plain write work for this socket by supplying default
|
/* Make plain write/send work for this socket by supplying default
|
||||||
* destination address. This also restricts incoming packets
|
* destination address. This also restricts incoming packets
|
||||||
* to ones coming from this remote IP. */
|
* to ones coming from this remote IP. */
|
||||||
xconnect(0, &remote.sa, lsa->len);
|
xconnect(0, &remote.sa, sa_len);
|
||||||
|
/* hole? at this point we have no wildcard udp socket...
|
||||||
|
* can this cause clients to get "port unreachable" icmp? */
|
||||||
/* Open new non-connected UDP socket for further clients */
|
/* Open new non-connected UDP socket for further clients */
|
||||||
sock = xsocket(lsa->sa.sa_family, tcp ? SOCK_STREAM : SOCK_DGRAM, 0);
|
sock = xsocket(lsa->sa.sa_family, tcp ? SOCK_STREAM : SOCK_DGRAM, 0);
|
||||||
setsockopt_reuseaddr(sock);
|
setsockopt_reuseaddr(sock);
|
||||||
xbind(sock, &lsa->sa, lsa->len);
|
xbind(sock, &lsa->sa, sa_len);
|
||||||
socket_want_pktinfo(sock);
|
socket_want_pktinfo(sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -355,50 +362,44 @@ int tcpudpsvd_main(int argc, char **argv)
|
|||||||
if (tcp)
|
if (tcp)
|
||||||
close(sock);
|
close(sock);
|
||||||
|
|
||||||
if (need_remote_ip) {
|
if (need_remote_ip)
|
||||||
if (!max_per_host)
|
remote_addr = xmalloc_sockaddr2dotted(&remote.sa, sa_len);
|
||||||
remote_ip = xmalloc_sockaddr2dotted_noport(&remote.sa, lsa->len);
|
|
||||||
/* else it is already done */
|
|
||||||
remote_port = get_nport(&remote.sa);
|
|
||||||
remote_port = ntohs(remote_port);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (need_hostnames) {
|
if (need_hostnames) {
|
||||||
if (option_mask32 & OPT_h) {
|
if (option_mask32 & OPT_h) {
|
||||||
remote_hostname = xmalloc_sockaddr2host(&remote.sa, lsa->len);
|
remote_hostname = xmalloc_sockaddr2host_noport(&remote.sa, sa_len);
|
||||||
if (!remote_hostname) {
|
if (!remote_hostname) {
|
||||||
bb_error_msg("warning: cannot look up hostname for %s", remote_ip);
|
bb_error_msg("warning: cannot look up hostname for %s", remote_addr);
|
||||||
remote_hostname = (char*)"";
|
remote_hostname = (char*)"";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Find out local IP peer connected to.
|
/* Find out local IP peer connected to.
|
||||||
* Errors ignored (I'm not paranoid enough to imagine kernel
|
* Errors ignored (I'm not paranoid enough to imagine kernel
|
||||||
* which doesn't know local IP). */
|
* which doesn't know local IP). */
|
||||||
if (tcp)
|
if (tcp) {
|
||||||
|
local.len = sa_len;
|
||||||
getsockname(0, &local.sa, &local.len);
|
getsockname(0, &local.sa, &local.len);
|
||||||
local_ip = xmalloc_sockaddr2dotted_noport(&local.sa, lsa->len);
|
}
|
||||||
local_port = get_nport(&local.sa);
|
local_addr = xmalloc_sockaddr2dotted(&local.sa, sa_len);
|
||||||
local_port = ntohs(local_port);
|
|
||||||
if (!local_hostname) {
|
if (!local_hostname) {
|
||||||
local_hostname = xmalloc_sockaddr2host_noport(&local.sa, lsa->len);
|
local_hostname = xmalloc_sockaddr2host_noport(&local.sa, sa_len);
|
||||||
if (!local_hostname)
|
if (!local_hostname)
|
||||||
bb_error_msg_and_die("warning: cannot look up hostname for %s"+9, local_ip);
|
bb_error_msg_and_die("warning: cannot look up hostname for %s"+9, local_addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
pid = getpid();
|
pid = getpid();
|
||||||
printf("%s: info: pid %u from %s\n", applet_name, pid, remote_ip);
|
printf("%s: info: pid %u from %s\n", applet_name, pid, remote_addr);
|
||||||
if (max_per_host)
|
if (max_per_host)
|
||||||
printf("%s: info: concurrency %u %s %u/%u\n",
|
printf("%s: info: concurrency %u %s %u/%u\n",
|
||||||
applet_name, pid, remote_ip, cur_per_host, max_per_host);
|
applet_name, pid, remote_ip, cur_per_host, max_per_host);
|
||||||
printf("%s: info: start %u %s:%s :%s:%s:%u\n",
|
printf("%s: info: start %u %s:%s :%s:%s\n",
|
||||||
applet_name, pid,
|
applet_name, pid,
|
||||||
local_hostname, local_ip,
|
local_hostname, local_addr,
|
||||||
remote_hostname, remote_ip, (unsigned)remote_port);
|
remote_hostname, remote_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: stop splitiing port# from IP?
|
|
||||||
if (!(option_mask32 & OPT_E)) {
|
if (!(option_mask32 & OPT_E)) {
|
||||||
/* setup ucspi env */
|
/* setup ucspi env */
|
||||||
const char *proto = tcp ? "TCP" : "UDP";
|
const char *proto = tcp ? "TCP" : "UDP";
|
||||||
@ -408,19 +409,14 @@ int tcpudpsvd_main(int argc, char **argv)
|
|||||||
* an outbond connection to local handler, and it needs
|
* an outbond connection to local handler, and it needs
|
||||||
* to know where it originally tried to connect */
|
* to know where it originally tried to connect */
|
||||||
if (tcp && getsockopt(0, SOL_IP, SO_ORIGINAL_DST, &lsa->sa, &lsa->len) == 0) {
|
if (tcp && getsockopt(0, SOL_IP, SO_ORIGINAL_DST, &lsa->sa, &lsa->len) == 0) {
|
||||||
char *ip = xmalloc_sockaddr2dotted_noport(&lsa->sa, lsa->len);
|
char *addr = xmalloc_sockaddr2dotted(&lsa->sa, sa_len);
|
||||||
unsigned port = get_nport(&lsa->sa);
|
xsetenv("TCPORIGDSTADDR", addr);
|
||||||
port = ntohs(port);
|
free(addr);
|
||||||
xsetenv("TCPORIGDSTIP", ip);
|
|
||||||
xsetenv("TCPORIGDSTPORT", utoa(port));
|
|
||||||
free(ip);
|
|
||||||
}
|
}
|
||||||
xsetenv("PROTO", proto);
|
xsetenv("PROTO", proto);
|
||||||
xsetenv_proto(proto, "LOCALIP", local_ip);
|
xsetenv_proto(proto, "LOCALADDR", local_addr);
|
||||||
xsetenv_proto(proto, "LOCALPORT", utoa(local_port));
|
|
||||||
xsetenv_proto(proto, "LOCALHOST", local_hostname);
|
xsetenv_proto(proto, "LOCALHOST", local_hostname);
|
||||||
xsetenv_proto(proto, "REMOTEIP", remote_ip);
|
xsetenv_proto(proto, "REMOTEADDR", remote_addr);
|
||||||
xsetenv_proto(proto, "REMOTEPORT", utoa(remote_port));
|
|
||||||
if (option_mask32 & OPT_h) {
|
if (option_mask32 & OPT_h) {
|
||||||
xsetenv_proto(proto, "REMOTEHOST", remote_hostname);
|
xsetenv_proto(proto, "REMOTEHOST", remote_hostname);
|
||||||
}
|
}
|
||||||
|
@ -18,12 +18,13 @@ socket_want_pktinfo(int fd)
|
|||||||
#ifdef IP_PKTINFO
|
#ifdef IP_PKTINFO
|
||||||
setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &const_int_1, sizeof(int));
|
setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &const_int_1, sizeof(int));
|
||||||
#endif
|
#endif
|
||||||
#ifdef IPV6_PKTINFO
|
#if ENABLE_FEATURE_IPV6 && defined(IPV6_PKTINFO)
|
||||||
setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &const_int_1, sizeof(int));
|
setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &const_int_1, sizeof(int));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef UNUSED
|
||||||
ssize_t
|
ssize_t
|
||||||
send_to_from(int fd, void *buf, size_t len, int flags,
|
send_to_from(int fd, void *buf, size_t len, int flags,
|
||||||
const struct sockaddr *from, const struct sockaddr *to,
|
const struct sockaddr *from, const struct sockaddr *to,
|
||||||
@ -34,8 +35,11 @@ send_to_from(int fd, void *buf, size_t len, int flags,
|
|||||||
#else
|
#else
|
||||||
struct iovec iov[1];
|
struct iovec iov[1];
|
||||||
struct msghdr msg;
|
struct msghdr msg;
|
||||||
char cbuf[LSA_SIZEOF_SA];
|
char cbuf[sizeof(struct in_pktinfo)
|
||||||
/* actually, max(sizeof(in_pktinfo),sizeof(in6_pktinfo)) */
|
#if ENABLE_FEATURE_IPV6 && defined(IPV6_PKTINFO)
|
||||||
|
| sizeof(struct in6_pktinfo) /* (a|b) is poor man's max(a,b) */
|
||||||
|
#endif
|
||||||
|
];
|
||||||
struct cmsghdr* cmsgptr;
|
struct cmsghdr* cmsgptr;
|
||||||
|
|
||||||
if (from->sa_family != AF_INET
|
if (from->sa_family != AF_INET
|
||||||
@ -73,11 +77,11 @@ send_to_from(int fd, void *buf, size_t len, int flags,
|
|||||||
/* pktptr->ipi_ifindex = 0; -- already done by memset(cbuf...) */
|
/* pktptr->ipi_ifindex = 0; -- already done by memset(cbuf...) */
|
||||||
pktptr->ipi_spec_dst = ((struct sockaddr_in*)from)->sin_addr;
|
pktptr->ipi_spec_dst = ((struct sockaddr_in*)from)->sin_addr;
|
||||||
}
|
}
|
||||||
#if ENABLE_FEATURE_IPV6 && defined(IP6_PKTINFO)
|
#if ENABLE_FEATURE_IPV6 && defined(IPV6_PKTINFO)
|
||||||
else if (to->sa_family == AF_INET6 && from->sa_family == AF_INET6) {
|
else if (to->sa_family == AF_INET6 && from->sa_family == AF_INET6) {
|
||||||
struct in6_pktinfo *pktptr;
|
struct in6_pktinfo *pktptr;
|
||||||
cmsgptr->cmsg_level = IPPROTO_IPV6;
|
cmsgptr->cmsg_level = IPPROTO_IPV6;
|
||||||
cmsgptr->cmsg_type = IP6_PKTINFO;
|
cmsgptr->cmsg_type = IPV6_PKTINFO;
|
||||||
cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
|
cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
|
||||||
pktptr = (struct in6_pktinfo *)(CMSG_DATA(cmsgptr));
|
pktptr = (struct in6_pktinfo *)(CMSG_DATA(cmsgptr));
|
||||||
/* pktptr->ipi6_ifindex = 0; -- already done by memset(cbuf...) */
|
/* 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,
|
|||||||
return sendmsg(fd, &msg, flags);
|
return sendmsg(fd, &msg, flags);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif /* UNUSED */
|
||||||
|
|
||||||
/* NB: this will never set port# in *to! */
|
/* NB: this will never set port# in 'to'!
|
||||||
|
* _Only_ IP/IPv6 address part of 'to' is _maybe_ modified.
|
||||||
|
* Typical usage is to preinit it with "default" value
|
||||||
|
* before calling recv_from_to(). */
|
||||||
ssize_t
|
ssize_t
|
||||||
recv_from_to(int fd, void *buf, size_t len, int flags,
|
recv_from_to(int fd, void *buf, size_t len, int flags,
|
||||||
struct sockaddr *from, struct sockaddr *to,
|
struct sockaddr *from, struct sockaddr *to,
|
||||||
@ -123,7 +131,6 @@ recv_from_to(int fd, void *buf, size_t len, int flags,
|
|||||||
return recv_length;
|
return recv_length;
|
||||||
|
|
||||||
/* Here we try to retrieve destination IP and memorize it */
|
/* Here we try to retrieve destination IP and memorize it */
|
||||||
memset(to, 0, sa_size);
|
|
||||||
for (cmsgptr = CMSG_FIRSTHDR(&msg);
|
for (cmsgptr = CMSG_FIRSTHDR(&msg);
|
||||||
cmsgptr != NULL;
|
cmsgptr != NULL;
|
||||||
cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)
|
cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)
|
||||||
@ -138,9 +145,9 @@ recv_from_to(int fd, void *buf, size_t len, int flags,
|
|||||||
#undef pktinfo
|
#undef pktinfo
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#if ENABLE_FEATURE_IPV6 && defined(IP6_PKTINFO)
|
#if ENABLE_FEATURE_IPV6 && defined(IPV6_PKTINFO)
|
||||||
if (cmsgptr->cmsg_level == IPPROTO_IPV6
|
if (cmsgptr->cmsg_level == IPPROTO_IPV6
|
||||||
&& cmsgptr->cmsg_type == IP6_PKTINFO
|
&& cmsgptr->cmsg_type == IPV6_PKTINFO
|
||||||
) {
|
) {
|
||||||
#define pktinfo(cmsgptr) ( (struct in6_pktinfo*)(CMSG_DATA(cmsgptr)) )
|
#define pktinfo(cmsgptr) ( (struct in6_pktinfo*)(CMSG_DATA(cmsgptr)) )
|
||||||
to->sa_family = AF_INET6;
|
to->sa_family = AF_INET6;
|
||||||
|
Loading…
Reference in New Issue
Block a user