mirror of
https://repo.or.cz/socat.git
synced 2025-07-14 23:33:23 +00:00
merged features ancillary, envvar
This commit is contained in:
parent
bd3810642b
commit
2ffe5a324e
42 changed files with 1898 additions and 287 deletions
228
xio-ip6.c
228
xio-ip6.c
|
@ -1,5 +1,5 @@
|
|||
/* source: xio-ip6.c */
|
||||
/* Copyright Gerhard Rieger 2001-2007 */
|
||||
/* Copyright Gerhard Rieger 2001-2008 */
|
||||
/* Published under the GNU General Public License V.2, see file COPYING */
|
||||
|
||||
/* this file contains the source for IP6 related functions */
|
||||
|
@ -9,17 +9,47 @@
|
|||
#if WITH_IP6
|
||||
|
||||
#include "xioopen.h"
|
||||
#include "xio-ascii.h"
|
||||
#include "xio-socket.h"
|
||||
#include "xio-ip.h" /* xiogetaddrinfo() */
|
||||
|
||||
#include "xio-ip6.h"
|
||||
|
||||
|
||||
static char *inet6addr_info(const struct in6_addr *sa, char *buff, size_t blen);
|
||||
|
||||
|
||||
#ifdef IPV6_V6ONLY
|
||||
const struct optdesc opt_ipv6_v6only = { "ipv6-v6only", "ipv6only", OPT_IPV6_V6ONLY, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_V6ONLY };
|
||||
#endif
|
||||
#ifdef IPV6_JOIN_GROUP
|
||||
const struct optdesc opt_ipv6_join_group = { "ipv6-join-group", "join-group", OPT_IPV6_JOIN_GROUP, GROUP_SOCK_IP6, PH_PASTBIND, TYPE_IP_MREQN, OFUNC_SOCKOPT, SOL_IPV6, IPV6_JOIN_GROUP };
|
||||
#endif
|
||||
const struct optdesc opt_ipv6_pktinfo = { "ipv6-pktinfo", "pktinfo", OPT_IPV6_PKTINFO, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_PKTINFO };
|
||||
const struct optdesc opt_ipv6_recvpktinfo = { "ipv6-recvpktinfo", "recvpktinfo", OPT_IPV6_RECVPKTINFO, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVPKTINFO };
|
||||
const struct optdesc opt_ipv6_rthdr = { "ipv6-rthdr", "rthdr", OPT_IPV6_RTHDR, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RTHDR };
|
||||
const struct optdesc opt_ipv6_recvrthdr = { "ipv6-recvrthdr", "recvrthdr", OPT_IPV6_RECVRTHDR, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVRTHDR };
|
||||
#ifdef IPV6_AUTHHDR
|
||||
const struct optdesc opt_ipv6_authhdr = { "ipv6-authhdr", "authhdr", OPT_IPV6_AUTHHDR, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_AUTHHDR };
|
||||
#endif
|
||||
const struct optdesc opt_ipv6_dstopts = { "ipv6-dstopts", "dstopts", OPT_IPV6_DSTOPTS, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_DSTOPTS };
|
||||
const struct optdesc opt_ipv6_recvdstopts = { "ipv6-recvdstopts", "recvdstopts", OPT_IPV6_RECVDSTOPTS, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVDSTOPTS };
|
||||
const struct optdesc opt_ipv6_hopopts = { "ipv6-hopopts", "hopopts", OPT_IPV6_HOPOPTS, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_HOPOPTS };
|
||||
const struct optdesc opt_ipv6_recvhopopts = { "ipv6-recvhopopts", "recvhopopts", OPT_IPV6_RECVHOPOPTS, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVHOPOPTS };
|
||||
#ifdef IPV6_FLOWINFO /* is in linux/in6.h */
|
||||
const struct optdesc opt_ipv6_flowinfo= { "ipv6-flowinfo","flowinfo",OPT_IPV6_FLOWINFO,GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_FLOWINFO };
|
||||
#endif
|
||||
const struct optdesc opt_ipv6_hoplimit= { "ipv6-hoplimit","hoplimit",OPT_IPV6_HOPLIMIT,GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_HOPLIMIT };
|
||||
const struct optdesc opt_ipv6_unicast_hops= { "ipv6-unicast-hops","unicast-hops",OPT_IPV6_UNICAST_HOPS,GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IPV6, IPV6_UNICAST_HOPS };
|
||||
const struct optdesc opt_ipv6_recvhoplimit= { "ipv6-recvhoplimit","recvhoplimit",OPT_IPV6_RECVHOPLIMIT,GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVHOPLIMIT };
|
||||
#ifdef IPV6_RECVERR
|
||||
const struct optdesc opt_ipv6_recverr = { "ipv6-recverr", "recverr", OPT_IPV6_RECVERR, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVERR };
|
||||
#endif
|
||||
const struct optdesc opt_ipv6_tclass = { "ipv6-tclass", "tclass", OPT_IPV6_TCLASS, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IPV6, IPV6_TCLASS };
|
||||
const struct optdesc opt_ipv6_recvtclass = { "ipv6-recvtclass", "recvtclass", OPT_IPV6_RECVTCLASS, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVTCLASS };
|
||||
#ifdef IPV6_RECVPATHMTU
|
||||
const struct optdesc opt_ipv6_recvpathmtu = { "ipv6-recvpathmtu", "recvpathmtu", OPT_IPV6_RECVPATHMTU, GROUP_SOCK_IP6, PH_PASTSOCKET, TYPE_BOOL, OFUNC_SOCKOPT, SOL_IPV6, IPV6_RECVPATHMTU };
|
||||
#endif
|
||||
|
||||
int xioparsenetwork_ip6(const char *rangename, struct xiorange_ip6 *range) {
|
||||
char *delimpos; /* absolute address of delimiter */
|
||||
|
@ -142,4 +172,200 @@ int xiocheckrange_ip6(struct sockaddr_in6 *pa, struct xiorange_ip6 *range) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if defined(HAVE_STRUCT_CMSGHDR) && defined(CMSG_DATA)
|
||||
/* provides info about the ancillary message */
|
||||
int xiolog_ancillary_ip6(struct cmsghdr *cmsg, int *num,
|
||||
char *typbuff, int typlen,
|
||||
char *nambuff, int namlen,
|
||||
char *envbuff, int envlen,
|
||||
char *valbuff, int vallen) {
|
||||
char scratch1[42]; /* can hold an IPv6 address in ASCII */
|
||||
char scratch2[32];
|
||||
size_t msglen;
|
||||
|
||||
*num = 1; /* good for most message types */
|
||||
msglen = cmsg->cmsg_len-((char *)CMSG_DATA(cmsg)-(char *)cmsg);
|
||||
envbuff[0] = '\0';
|
||||
switch (cmsg->cmsg_type) {
|
||||
case IPV6_PKTINFO: {
|
||||
struct in6_pktinfo *pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
|
||||
*num = 2;
|
||||
strncpy(typbuff, "IPV6_PKTINFO", typlen);
|
||||
snprintf(nambuff, namlen, "%s%c%s", "dstaddr", '\0', "if");
|
||||
snprintf(envbuff, envlen, "%s%c%s", "IPV6_DSTADDR", '\0', "IPV6_IF");
|
||||
snprintf(valbuff, vallen, "%s%c%s",
|
||||
inet6addr_info(&pktinfo->ipi6_addr, scratch1, sizeof(scratch1)),
|
||||
'\0', xiogetifname(pktinfo->ipi6_ifindex, scratch2, -1));
|
||||
}
|
||||
return STAT_OK;
|
||||
case IPV6_HOPLIMIT:
|
||||
strncpy(typbuff, "IPV6_HOPLIMIT", typlen);
|
||||
strncpy(nambuff, "hoplimit", namlen);
|
||||
snprintf(valbuff, vallen, "%d", *(int *)CMSG_DATA(cmsg));
|
||||
return STAT_OK;
|
||||
case IPV6_RTHDR:
|
||||
strncpy(typbuff, "IPV6_RTHDR", typlen);
|
||||
strncpy(nambuff, "rthdr", namlen);
|
||||
xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0);
|
||||
return STAT_OK;
|
||||
#ifdef IPV6_AUTHHDR
|
||||
case IPV6_AUTHHDR:
|
||||
strncpy(typbuff, "IPV6_AUTHHDR", typlen);
|
||||
strncpy(nambuff, "authhdr", namlen);
|
||||
xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0);
|
||||
return STAT_OK;
|
||||
#endif
|
||||
case IPV6_DSTOPTS:
|
||||
strncpy(typbuff, "IPV6_DSTOPTS", typlen);
|
||||
strncpy(nambuff, "dstopts", namlen);
|
||||
xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0);
|
||||
return STAT_OK;
|
||||
case IPV6_HOPOPTS:
|
||||
strncpy(typbuff, "IPV6_HOPOPTS", typlen);
|
||||
strncpy(nambuff, "hopopts", namlen);
|
||||
xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0);
|
||||
return STAT_OK;
|
||||
#ifdef IPV6_FLOWINFO
|
||||
case IPV6_FLOWINFO:
|
||||
strncpy(typbuff, "IPV6_FLOWINFO", typlen);
|
||||
strncpy(nambuff, "flowinfo", namlen);
|
||||
xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0);
|
||||
return STAT_OK;
|
||||
#endif
|
||||
case IPV6_TCLASS:
|
||||
strncpy(typbuff, "IPV6_TCLASS", typlen);
|
||||
strncpy(nambuff, "tclass", namlen);
|
||||
xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0);
|
||||
return STAT_OK;
|
||||
default:
|
||||
snprintf(typbuff, typlen, "IPV6.%u", cmsg->cmsg_type);
|
||||
strncpy(nambuff, "data", namlen);
|
||||
xiodump(CMSG_DATA(cmsg), msglen, valbuff, vallen, 0);
|
||||
return STAT_OK;
|
||||
}
|
||||
return STAT_OK;
|
||||
}
|
||||
#endif /* defined(HAVE_STRUCT_CMSGHDR) && defined(CMSG_DATA) */
|
||||
|
||||
|
||||
/* convert the IP6 socket address to human readable form. buff should be at
|
||||
least 50 chars long. output includes the port number */
|
||||
static char *inet6addr_info(const struct in6_addr *sa, char *buff, size_t blen) {
|
||||
if (snprintf(buff, blen, "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]",
|
||||
#if HAVE_IP6_SOCKADDR==0
|
||||
(sa->s6_addr[0]<<8)+sa->s6_addr[1],
|
||||
(sa->s6_addr[2]<<8)+sa->s6_addr[3],
|
||||
(sa->s6_addr[4]<<8)+sa->s6_addr[5],
|
||||
(sa->s6_addr[6]<<8)+sa->s6_addr[7],
|
||||
(sa->s6_addr[8]<<8)+sa->s6_addr[9],
|
||||
(sa->s6_addr[10]<<8)+sa->s6_addr[11],
|
||||
(sa->s6_addr[12]<<8)+sa->s6_addr[13],
|
||||
(sa->s6_addr[14]<<8)+sa->s6_addr[15]
|
||||
#elif HAVE_IP6_SOCKADDR==1
|
||||
ntohs(((unsigned short *)&sa->u6_addr.u6_addr16)[0]),
|
||||
ntohs(((unsigned short *)&sa->u6_addr.u6_addr16)[1]),
|
||||
ntohs(((unsigned short *)&sa->u6_addr.u6_addr16)[2]),
|
||||
ntohs(((unsigned short *)&sa->u6_addr.u6_addr16)[3]),
|
||||
ntohs(((unsigned short *)&sa->u6_addr.u6_addr16)[4]),
|
||||
ntohs(((unsigned short *)&sa->u6_addr.u6_addr16)[5]),
|
||||
ntohs(((unsigned short *)&sa->u6_addr.u6_addr16)[6]),
|
||||
ntohs(((unsigned short *)&sa->u6_addr.u6_addr16)[7])
|
||||
#elif HAVE_IP6_SOCKADDR==2
|
||||
ntohs(((unsigned short *)&sa->u6_addr16)[0]),
|
||||
ntohs(((unsigned short *)&sa->u6_addr16)[1]),
|
||||
ntohs(((unsigned short *)&sa->u6_addr16)[2]),
|
||||
ntohs(((unsigned short *)&sa->u6_addr16)[3]),
|
||||
ntohs(((unsigned short *)&sa->u6_addr16)[4]),
|
||||
ntohs(((unsigned short *)&sa->u6_addr16)[5]),
|
||||
ntohs(((unsigned short *)&sa->u6_addr16)[6]),
|
||||
ntohs(((unsigned short *)&sa->u6_addr16)[7])
|
||||
#elif HAVE_IP6_SOCKADDR==3
|
||||
ntohs(((unsigned short *)&sa->in6_u.u6_addr16)[0]),
|
||||
ntohs(((unsigned short *)&sa->in6_u.u6_addr16)[1]),
|
||||
ntohs(((unsigned short *)&sa->in6_u.u6_addr16)[2]),
|
||||
ntohs(((unsigned short *)&sa->in6_u.u6_addr16)[3]),
|
||||
ntohs(((unsigned short *)&sa->in6_u.u6_addr16)[4]),
|
||||
ntohs(((unsigned short *)&sa->in6_u.u6_addr16)[5]),
|
||||
ntohs(((unsigned short *)&sa->in6_u.u6_addr16)[6]),
|
||||
ntohs(((unsigned short *)&sa->in6_u.u6_addr16)[7])
|
||||
#elif HAVE_IP6_SOCKADDR==4
|
||||
(sa->_S6_un._S6_u8[0]<<8)|(sa->_S6_un._S6_u8[1]&0xff),
|
||||
(sa->_S6_un._S6_u8[2]<<8)|(sa->_S6_un._S6_u8[3]&0xff),
|
||||
(sa->_S6_un._S6_u8[4]<<8)|(sa->_S6_un._S6_u8[5]&0xff),
|
||||
(sa->_S6_un._S6_u8[6]<<8)|(sa->_S6_un._S6_u8[7]&0xff),
|
||||
(sa->_S6_un._S6_u8[8]<<8)|(sa->_S6_un._S6_u8[9]&0xff),
|
||||
(sa->_S6_un._S6_u8[10]<<8)|(sa->_S6_un._S6_u8[11]&0xff),
|
||||
(sa->_S6_un._S6_u8[12]<<8)|(sa->_S6_un._S6_u8[13]&0xff),
|
||||
(sa->_S6_un._S6_u8[14]<<8)|(sa->_S6_un._S6_u8[15]&0xff)
|
||||
#elif HAVE_IP6_SOCKADDR==5
|
||||
ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[0]),
|
||||
ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[1]),
|
||||
ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[2]),
|
||||
ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[3]),
|
||||
ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[4]),
|
||||
ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[5]),
|
||||
ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[6]),
|
||||
ntohs(((unsigned short *)&sa->__u6_addr.__u6_addr16)[7])
|
||||
#endif
|
||||
) < 0) {
|
||||
Warn("sockaddr_inet6_info(): buffer too short");
|
||||
buff[blen-1] = '\0';
|
||||
}
|
||||
return buff;
|
||||
}
|
||||
|
||||
|
||||
/* returns information that can be used for constructing an environment
|
||||
variable describing the socket address.
|
||||
if idx is 0, this function writes "ADDR" into namebuff and the IP address
|
||||
into valuebuff, and returns 1 (which means that one more info is there).
|
||||
if idx is 1, it writes "PORT" into namebuff and the port number into
|
||||
valuebuff, and returns 0 (no more info)
|
||||
namelen and valuelen contain the max. allowed length of output chars in the
|
||||
respective buffer.
|
||||
on error this function returns -1.
|
||||
*/
|
||||
int
|
||||
xiosetsockaddrenv_ip6(int idx, char *namebuff, size_t namelen,
|
||||
char *valuebuff, size_t valuelen,
|
||||
struct sockaddr_in6 *sa, int ipproto) {
|
||||
switch (idx) {
|
||||
case 0:
|
||||
strcpy(namebuff, "ADDR");
|
||||
snprintf(valuebuff, valuelen, "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]",
|
||||
(sa->sin6_addr.s6_addr[0]<<8)+
|
||||
sa->sin6_addr.s6_addr[1],
|
||||
(sa->sin6_addr.s6_addr[2]<<8)+
|
||||
sa->sin6_addr.s6_addr[3],
|
||||
(sa->sin6_addr.s6_addr[4]<<8)+
|
||||
sa->sin6_addr.s6_addr[5],
|
||||
(sa->sin6_addr.s6_addr[6]<<8)+
|
||||
sa->sin6_addr.s6_addr[7],
|
||||
(sa->sin6_addr.s6_addr[8]<<8)+
|
||||
sa->sin6_addr.s6_addr[9],
|
||||
(sa->sin6_addr.s6_addr[10]<<8)+
|
||||
sa->sin6_addr.s6_addr[11],
|
||||
(sa->sin6_addr.s6_addr[12]<<8)+
|
||||
sa->sin6_addr.s6_addr[13],
|
||||
(sa->sin6_addr.s6_addr[14]<<8)+
|
||||
sa->sin6_addr.s6_addr[15]);
|
||||
switch (ipproto) {
|
||||
case IPPROTO_TCP:
|
||||
case IPPROTO_UDP:
|
||||
#ifdef IPPROTO_SCTP
|
||||
case IPPROTO_SCTP:
|
||||
#endif
|
||||
return 1; /* there is port information to also be retrieved */
|
||||
default:
|
||||
return 0; /* no port info coming */
|
||||
}
|
||||
case 1:
|
||||
strcpy(namebuff, "PORT");
|
||||
snprintf(valuebuff, valuelen, "%u", ntohs(sa->sin6_port));
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif /* WITH_IP6 */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue