mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 15:32:35 +00:00
New option ip-add-source-membership
This commit is contained in:
parent
13ac417410
commit
583e14d7fa
10 changed files with 195 additions and 2 deletions
3
CHANGES
3
CHANGES
|
@ -155,6 +155,9 @@ New features:
|
|||
Test: ACCEPTTIMEOUT
|
||||
Proposed by Roland
|
||||
|
||||
New option ip-add-source-membership
|
||||
Feature inspired by Brian (b f31415)
|
||||
|
||||
####################### V 1.7.3.4:
|
||||
|
||||
Corrections:
|
||||
|
|
|
@ -379,6 +379,9 @@
|
|||
/* Define if you have struct ipv6_mreq */
|
||||
#undef HAVE_STRUCT_IPV6_MREQ
|
||||
|
||||
/* Define if you have struct ip_mreq_source */
|
||||
#undef HAVE_STRUCT_IP_MREQ_SOURCE
|
||||
|
||||
/* Define if you have struct ifreq */
|
||||
#undef HAVE_STRUCT_IFREQ
|
||||
|
||||
|
|
13
configure.ac
13
configure.ac
|
@ -1176,6 +1176,19 @@ if test $sc_cv_struct_ipv6_mreq = yes; then
|
|||
fi
|
||||
AC_MSG_RESULT($sc_cv_struct_ipv6_mreq)
|
||||
|
||||
# struct ip_mreq_source (for multicasting options)
|
||||
AC_MSG_CHECKING(for struct ip_mreq_source)
|
||||
AC_CACHE_VAL(sc_cv_struct_ip_mreq_source,
|
||||
[AC_TRY_COMPILE([#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/ip.h>],[struct ip_mreq_source s;],
|
||||
[sc_cv_struct_ip_mreq_source=yes],
|
||||
[sc_cv_struct_ip_mreq_source=no])])
|
||||
if test $sc_cv_struct_ip_mreq_source = yes; then
|
||||
AC_DEFINE(HAVE_STRUCT_IP_MREQ_SOURCE)
|
||||
fi
|
||||
AC_MSG_RESULT($sc_cv_struct_ip_mreqn)
|
||||
|
||||
|
||||
# struct ifreq (for network interfaces)
|
||||
AC_MSG_CHECKING(for struct ifreq)
|
||||
|
|
|
@ -394,6 +394,7 @@ label(ADDRESS_IP_DATAGRAM)dit(bf(tt(IP-DATAGRAM:<address>:<protocol>)))
|
|||
link(ip-multicast-ttl)(OPTION_IP_MULTICAST_TTL),
|
||||
link(ip-multicast-if)(OPTION_IP_MULTICAST_IF),
|
||||
link(ip-add-membership)(OPTION_IP_ADD_MEMBERSHIP),
|
||||
link(ip-add-source-membership)(OPTION_IP_ADD_SOURCE_MEMBERSHIP),
|
||||
link(ttl)(OPTION_TTL),
|
||||
link(tos)(OPTION_TOS),
|
||||
link(pf)(OPTION_PROTOCOL_FAMILY)nl()
|
||||
|
@ -1101,6 +1102,7 @@ label(ADDRESS_UDP_DATAGRAM)dit(bf(tt(UDP-DATAGRAM:<address>:<port>)))
|
|||
link(ip-multicast-ttl)(OPTION_IP_MULTICAST_TTL),
|
||||
link(ip-multicast-if)(OPTION_IP_MULTICAST_IF),
|
||||
link(ip-add-membership)(OPTION_IP_ADD_MEMBERSHIP),
|
||||
link(ip-add-source-membership)(OPTION_IP_ADD_SOURCE_MEMBERSHIP),
|
||||
link(ttl)(OPTION_TTL),
|
||||
link(tos)(OPTION_TOS),
|
||||
link(sourceport)(OPTION_SOURCEPORT),
|
||||
|
@ -2108,6 +2110,11 @@ dit(bf(tt(ip-add-membership=<multicast-address:interface-address:interface-index
|
|||
provide tt(struct mreqn) (Linux).nl()
|
||||
The indices of active network interfaces can be shown using the utility
|
||||
procan().
|
||||
label(OPTION_IP_ADD_SOURCE_MEMBERSHIP)
|
||||
dit(bf(tt(ip-add-source-membership=<multicast-address:interface-address:source-address>)))
|
||||
Makes the socket member of the specified multicast group for the specified
|
||||
source, i.e. only multicast traffic from this address is to be delivered.
|
||||
This is currently only implemented for IPv4.nl()
|
||||
label(OPTION_IP_MULTICAST_IF)
|
||||
dit(bf(tt(ip-multicast-if=<hostname>)))
|
||||
Specifies hostname or address of the network interface to be used for
|
||||
|
|
128
xio-ip.c
128
xio-ip.c
|
@ -14,6 +14,7 @@
|
|||
#include "xio-socket.h"
|
||||
#include "xio-ip.h"
|
||||
#include "xio-ip6.h"
|
||||
#include "nestlex.h"
|
||||
|
||||
|
||||
#if WITH_IP4 || WITH_IP6
|
||||
|
@ -70,6 +71,9 @@ const struct optdesc opt_ip_pktoptions = { "ip-pktoptions", "pktopts", OPT_IP_PK
|
|||
#ifdef IP_ADD_MEMBERSHIP
|
||||
const struct optdesc opt_ip_add_membership = { "ip-add-membership", "membership",OPT_IP_ADD_MEMBERSHIP, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_IP_MREQN, OFUNC_SOCKOPT, SOL_IP, IP_ADD_MEMBERSHIP };
|
||||
#endif
|
||||
#ifdef IP_ADD_SOURCE_MEMBERSHIP
|
||||
const struct optdesc opt_ip_add_source_membership = { "ip-add-source-membership", "source-membership",OPT_IP_ADD_SOURCE_MEMBERSHIP, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_IP_MREQ_SOURCE, OFUNC_SOCKOPT, SOL_IP, IP_ADD_SOURCE_MEMBERSHIP };
|
||||
#endif
|
||||
#ifdef IP_RECVDSTADDR
|
||||
const struct optdesc opt_ip_recvdstaddr = { "ip-recvdstaddr", "recvdstaddr",OPT_IP_RECVDSTADDR, GROUP_SOCK_IP, PH_PASTSOCKET, TYPE_INT, OFUNC_SOCKOPT, SOL_IP, IP_RECVDSTADDR };
|
||||
#endif
|
||||
|
@ -581,4 +585,128 @@ int xiolog_ancillary_ip(struct cmsghdr *cmsg, int *num,
|
|||
}
|
||||
#endif /* defined(HAVE_STRUCT_CMSGHDR) && defined(CMSG_DATA) */
|
||||
|
||||
|
||||
#if HAVE_STRUCT_IP_MREQ_SOURCE
|
||||
int xiotype_ip_add_source_membership(char *token, const struct optname *ent, struct opt *opt) {
|
||||
/* we do not resolve the addresses here because we do not yet know
|
||||
if we are coping with an IPv4 or IPv6 socat address */
|
||||
const char *ends[] = { ":", NULL };
|
||||
const char *nests[] = { "[","]", NULL };
|
||||
char buff[512], *buffp=buff; size_t bufspc = sizeof(buff)-1;
|
||||
char *tokp = token;
|
||||
int parsres;
|
||||
|
||||
/* parse first IP address, expect ':' */
|
||||
parsres =
|
||||
nestlex((const char **)&tokp, &buffp, &bufspc,
|
||||
ends, NULL, NULL, nests,
|
||||
true, false, false);
|
||||
if (parsres < 0) {
|
||||
Error1("option too long: \"%s\"", token);
|
||||
return -1;
|
||||
} else if (parsres > 0) {
|
||||
Error1("syntax error in \"%s\"", token);
|
||||
return -1;
|
||||
}
|
||||
if (*tokp != ':') {
|
||||
Error1("syntax in option %s: missing ':'", token);
|
||||
}
|
||||
*buffp++ = '\0';
|
||||
opt->value.u_ip_mreq_source.mcaddr = strdup(buff); /*!!! NULL */
|
||||
|
||||
++tokp;
|
||||
/* parse second IP address, expect ':' or '\0'' */
|
||||
buffp = buff;
|
||||
/*! result= */
|
||||
parsres =
|
||||
nestlex((const char **)&tokp, &buffp, &bufspc,
|
||||
ends, NULL, NULL, nests,
|
||||
true, false, false);
|
||||
if (parsres < 0) {
|
||||
Error1("option too long: \"%s\"", token);
|
||||
return -1;
|
||||
} else if (parsres > 0) {
|
||||
Error1("syntax error in \"%s\"", token);
|
||||
return -1;
|
||||
}
|
||||
if (*tokp != ':') {
|
||||
Error1("syntax in option %s: missing ':'", token);
|
||||
}
|
||||
*buffp++ = '\0';
|
||||
opt->value.u_ip_mreq_source.ifaddr = strdup(buff); /*!!! NULL */
|
||||
|
||||
++tokp;
|
||||
/* parse third IP address, expect ':' or '\0'' */
|
||||
buffp = buff;
|
||||
/*! result= */
|
||||
parsres =
|
||||
nestlex((const char **)&tokp, &buffp, &bufspc,
|
||||
ends, NULL, NULL, nests,
|
||||
true, false, false);
|
||||
if (parsres < 0) {
|
||||
Error1("option too long: \"%s\"", token);
|
||||
return -1;
|
||||
} else if (parsres > 0) {
|
||||
Error1("syntax error in \"%s\"", token);
|
||||
return -1;
|
||||
}
|
||||
if (*tokp) {
|
||||
Error1("syntax in option %s: trailing cruft", token);
|
||||
}
|
||||
*buffp++ = '\0';
|
||||
opt->value.u_ip_mreq_source.srcaddr = strdup(buff); /*!!! NULL */
|
||||
|
||||
Info4("setting option \"%s\" to {0x%08x,0x%08x,0x08x}",
|
||||
ent->desc->defname,
|
||||
opt->value.u_ip_mreq_source.mcaddr,
|
||||
opt->value.u_ip_mreq_source.ifaddr,
|
||||
opt->value.u_ip_mreq_source.srcaddr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xioapply_ip_add_source_membership(struct single *xfd, struct opt *opt) {
|
||||
struct ip_mreq_source ip4_mreq_src = {{0}};
|
||||
/* IPv6 not supported - seems to have different handling */
|
||||
union sockaddr_union sockaddr1;
|
||||
socklen_t socklen1 = sizeof(sockaddr1.ip4);
|
||||
union sockaddr_union sockaddr2;
|
||||
socklen_t socklen2 = sizeof(sockaddr2.ip4);
|
||||
union sockaddr_union sockaddr3;
|
||||
socklen_t socklen3 = sizeof(sockaddr3.ip4);
|
||||
|
||||
/* first parameter is always multicast address */
|
||||
/*! result */
|
||||
xiogetaddrinfo(opt->value.u_ip_mreq_source.mcaddr, NULL,
|
||||
xfd->para.socket.la.soa.sa_family,
|
||||
SOCK_DGRAM, IPPROTO_IP,
|
||||
&sockaddr1, &socklen1, 0, 0);
|
||||
ip4_mreq_src.imr_multiaddr = sockaddr1.ip4.sin_addr;
|
||||
/* second parameter is interface address */
|
||||
xiogetaddrinfo(opt->value.u_ip_mreq_source.ifaddr, NULL,
|
||||
xfd->para.socket.la.soa.sa_family,
|
||||
SOCK_DGRAM, IPPROTO_IP,
|
||||
&sockaddr2, &socklen2, 0, 0);
|
||||
ip4_mreq_src.imr_interface = sockaddr2.ip4.sin_addr;
|
||||
/* third parameter is source address */
|
||||
xiogetaddrinfo(opt->value.u_ip_mreq_source.srcaddr, NULL,
|
||||
xfd->para.socket.la.soa.sa_family,
|
||||
SOCK_DGRAM, IPPROTO_IP,
|
||||
&sockaddr3, &socklen3, 0, 0);
|
||||
ip4_mreq_src.imr_sourceaddr = sockaddr3.ip4.sin_addr;
|
||||
if (Setsockopt(xfd->fd, opt->desc->major, opt->desc->minor,
|
||||
&ip4_mreq_src, sizeof(ip4_mreq_src)) < 0) {
|
||||
Error8("setsockopt(%d, %d, %d, {0x%08x,0x%08x,0x%08x}, "F_Zu"): %s",
|
||||
xfd->fd, opt->desc->major, opt->desc->minor,
|
||||
ip4_mreq_src.imr_multiaddr,
|
||||
ip4_mreq_src.imr_interface,
|
||||
ip4_mreq_src.imr_sourceaddr,
|
||||
sizeof(struct ip_mreq_source),
|
||||
strerror(errno));
|
||||
opt->desc = ODESC_ERROR;
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* HAVE_STRUCT_IP_MREQ_SOURCE */
|
||||
|
||||
#endif /* _WITH_IP4 || _WITH_IP6 */
|
||||
|
|
3
xio-ip.h
3
xio-ip.h
|
@ -24,6 +24,7 @@ extern const struct optdesc opt_ip_multicast_loop;
|
|||
extern const struct optdesc opt_ip_multicast_if;
|
||||
extern const struct optdesc opt_ip_pktoptions;
|
||||
extern const struct optdesc opt_ip_add_membership;
|
||||
extern const struct optdesc opt_ip_add_source_membership;
|
||||
extern const struct optdesc opt_ip_recvdstaddr;
|
||||
extern const struct optdesc opt_ip_recvif;
|
||||
extern const struct optdesc opt_ip_transparent;
|
||||
|
@ -48,5 +49,7 @@ int xiolog_ancillary_ip(struct cmsghdr *cmsg, int *num,
|
|||
char *nambuff, int namlen,
|
||||
char *envbuff, int envlen,
|
||||
char *valbuff, int vallen);
|
||||
extern int xiotype_ip_add_source_membership(char* token, const struct optname *ent, struct opt *opt);
|
||||
extern int xioapply_ip_add_source_membership(struct single *xfd, struct opt *opt);
|
||||
|
||||
#endif /* !defined(__xio_ip_h_included) */
|
||||
|
|
7
xio.h
7
xio.h
|
@ -354,6 +354,13 @@ union integral {
|
|||
#endif
|
||||
} u_ip_mreq;
|
||||
#endif
|
||||
#if HAVE_STRUCT_IP_MREQ_SOURCE
|
||||
struct {
|
||||
char *mcaddr;
|
||||
char *ifaddr; /* address, interface */
|
||||
char *srcaddr; /* source address */
|
||||
} u_ip_mreq_source;
|
||||
#endif
|
||||
#if WITH_IP4
|
||||
struct in_addr u_ip4addr;
|
||||
#endif
|
||||
|
|
|
@ -21,6 +21,7 @@ static const char *optiontypenames[] = {
|
|||
"DOUBLE", "STRING-NULL", "LONG-LONG", "OFF_T",
|
||||
"OFF64_T", "INT:INT", "INT:INTP", "INT:BIN",
|
||||
"INT:STRING", "INT:INT:INT", "INT:INT:BIN", "INT:INT:STRING",
|
||||
"INT:INT:GENERIC",
|
||||
"IP4NAME",
|
||||
|
||||
#if HAVE_STRUCT_LINGER
|
||||
|
@ -31,6 +32,10 @@ static const char *optiontypenames[] = {
|
|||
#elif HAVE_STRUCT_IP_MREQ
|
||||
"STRUCT-IP_MREQ",
|
||||
#endif
|
||||
#if HAVE_STRUCT_IP_MREQ_SOURCE
|
||||
"IP-MREQ-SOURCE",
|
||||
#endif
|
||||
"GENERIC",
|
||||
} ;
|
||||
|
||||
|
||||
|
|
22
xioopts.c
22
xioopts.c
|
@ -7,6 +7,7 @@
|
|||
#include "xiosysincludes.h"
|
||||
#include "xioopen.h"
|
||||
#include "xio-unix.h"
|
||||
#include "xio-ip.h"
|
||||
|
||||
#include "xiomodes.h"
|
||||
#include "xiolockfile.h"
|
||||
|
@ -156,6 +157,9 @@ const struct optname optionnames[] = {
|
|||
#endif /* SO_ACCEPTCONN */
|
||||
#ifdef IP_ADD_MEMBERSHIP
|
||||
IF_IP ("add-membership", &opt_ip_add_membership)
|
||||
#endif
|
||||
#ifdef IP_ADD_SOURCE_MEMBERSHIP
|
||||
IF_IP ("add-source-membership", &opt_ip_add_source_membership)
|
||||
#endif
|
||||
IF_TUN ("allmulti", &opt_iff_allmulti)
|
||||
#if WITH_LIBWRAP && defined(HAVE_HOSTS_ALLOW_TABLE)
|
||||
|
@ -668,6 +672,9 @@ const struct optname optionnames[] = {
|
|||
#ifdef IP_ADD_MEMBERSHIP
|
||||
IF_IP ("ip-add-membership", &opt_ip_add_membership)
|
||||
#endif
|
||||
#ifdef IP_ADD_SOURCE_MEMBERSHIP
|
||||
IF_IP ("ip-add-source-membership", &opt_ip_add_source_membership)
|
||||
#endif
|
||||
#ifdef IP_FREEBIND
|
||||
IF_IP ("ip-freebind", &opt_ip_freebind)
|
||||
#endif
|
||||
|
@ -1547,6 +1554,9 @@ const struct optname optionnames[] = {
|
|||
IF_SOCKS4 ("socksport", &opt_socksport)
|
||||
IF_SOCKS4 ("socksuser", &opt_socksuser)
|
||||
IF_SOCKET ("socktype", &opt_so_type)
|
||||
#ifdef IP_ADD_SOURCE_MEMBERSHIP
|
||||
IF_IP ("source-membership", &opt_ip_add_source_membership)
|
||||
#endif
|
||||
IF_IPAPP ("sourceport", &opt_sourceport)
|
||||
IF_IPAPP ("sp", &opt_sourceport)
|
||||
IF_TERMIOS("start", &opt_vstart)
|
||||
|
@ -2488,6 +2498,10 @@ int parseopts_table(const char **a, unsigned int groups, struct opt **opts,
|
|||
break;
|
||||
#endif /* defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN) */
|
||||
|
||||
case TYPE_IP_MREQ_SOURCE:
|
||||
xiotype_ip_add_source_membership(token, ent, opt);
|
||||
break;
|
||||
|
||||
#if WITH_IP4
|
||||
case TYPE_IP4NAME:
|
||||
{
|
||||
|
@ -4057,7 +4071,13 @@ mc:addr
|
|||
break;
|
||||
#endif /* WITH_IP4 && (defined(HAVE_STRUCT_IP_MREQ) || defined (HAVE_STRUCT_IP_MREQN)) */
|
||||
|
||||
|
||||
#if WITH_IP4 && defined(HAVE_STRUCT_IP_MREQ_SOURCE) && defined(IP_ADD_SOURCE_MEMBERSHIP)
|
||||
case OPT_IP_ADD_SOURCE_MEMBERSHIP:
|
||||
if (xioapply_ip_add_source_membership(xfd, opt) < 0) {
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
#endif /* WITH_IP4 && defined(HAVE_STRUCT_IP_MREQ_SOURCE) && defined(IP_ADD_SOURCE_MEMBERSHIP) */
|
||||
|
||||
#if WITH_IP6 && defined(HAVE_STRUCT_IPV6_MREQ)
|
||||
case OPT_IPV6_JOIN_GROUP:
|
||||
|
|
|
@ -73,8 +73,11 @@ enum e_types {
|
|||
#if HAVE_STRUCT_IP_MREQ || HAVE_STRUCT_IP_MREQN
|
||||
TYPE_IP_MREQN, /* for struct ip_mreq or struct ip_mreqn */
|
||||
#endif
|
||||
#if HAVE_STRUCT_IP_MREQ_SOURCE
|
||||
TYPE_IP_MREQ_SOURCE, /* for struct ip_mreq_source */
|
||||
#endif
|
||||
|
||||
TYPE_GENERIC, /* type is determined from (text) data provided */
|
||||
TYPE_GENERIC, /* type is determined from (text) data provided (dalan syntax) */
|
||||
} ;
|
||||
|
||||
enum e_func {
|
||||
|
@ -380,6 +383,7 @@ enum e_optcode {
|
|||
OPT_IOCTL_STRING, /* generic ioctl with integer value (pointed to) */
|
||||
OPT_IOCTL_VOID, /* generic ioctl without value */
|
||||
OPT_IP_ADD_MEMBERSHIP,
|
||||
OPT_IP_ADD_SOURCE_MEMBERSHIP,
|
||||
#ifdef IP_HDRINCL
|
||||
OPT_IP_HDRINCL,
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue