New option retrieve-vlan (experimental)

This commit is contained in:
Gerhard Rieger 2023-09-30 15:18:39 +02:00
parent 11d1e9e11f
commit b5640dd707
24 changed files with 273 additions and 55 deletions

View file

@ -57,6 +57,15 @@ Features:
messages in LISTEN and CONNECT type sub processes.
Test: CHILDREN_SHUTUP
New option retrieve-vlan for supporting VLANs in INTERFACE addresses:
Linux normally keeps VLAN tags in outgoing raw packets, but appears to
strip them from incoming packets and makes them available in
PACKET_AUXDATA ancillary messages only.
Up do version 1.7.4.5 Socat did not handle this situation, so the VLAN
tags where effectively stripped off incoming packets.
With this option Socat restores the VLAN tag.
Feature inspired by Zhao Dong.
Corrections:
When a sub process (EXEC, SYSTEM) terminated with exit code other than
0, its last sent data might have been lost depending on timing of read/

View file

@ -1 +1 @@
"1.7.4.5+vlans"
"1.7.4.5+"

View file

@ -430,6 +430,12 @@
/* define if you have struct in6_pktinfo */
#undef HAVE_STRUCT_IN6_PKTINFO
/* define if you have struct tpacket_auxdata */
#undef HAVE_STRUCT_TPACKET_AUXDATA
/* define if you have struct tpacket_auxdata and it has tp_vlan_tpid */
#undef HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TPID
/* define if your struct ip has ip_hl; otherwise assume ip_vhl */
#undef HAVE_STRUCT_IP_IP_HL

View file

@ -1477,6 +1477,29 @@ if test $sc_cv_struct_in6_pktinfo = yes; then
fi
AC_MSG_RESULT($sc_cv_struct_in6_pktinfo)
dnl check for struct tpacket_auxdata
AC_MSG_CHECKING(for struct tpacket_auxdata)
AC_CACHE_VAL(sc_cv_struct_tpacket_auxdata,
[AC_TRY_COMPILE([#include "sysincludes.h"],
[struct tpacket_auxdata s;],
[sc_cv_struct_tpacket_auxdata=yes],
[sc_cv_struct_tpacket_auxdata=no])])
if test $sc_cv_struct_tpacket_auxdata = yes; then
AC_DEFINE(HAVE_STRUCT_TPACKET_AUXDATA)
fi
AC_MSG_RESULT($sc_cv_struct_tpacket_auxdata)
AC_MSG_CHECKING(for tp_vlan_tpid in struct tpacket_auxdata)
AC_CACHE_VAL(sc_cv_struct_tpacket_auxdata_tp_vlan_tpid,
[AC_TRY_COMPILE([#include "sysincludes.h"],
[struct tpacket_auxdata s; s.tp_vlan_tpid=0],
[sc_cv_struct_tpacket_auxdata_tp_vlan_tpid=yes],
[sc_cv_struct_tpacket_auxdata_tp_vlan_tpid=no])])
if test $sc_cv_struct_tpacket_auxdata_tp_vlan_tpid = yes; then
AC_DEFINE(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TPID)
fi
AC_MSG_RESULT($sc_cv_struct_tpacket_auxdata)
dnl check for ip_hl in struct ip
AC_MSG_CHECKING(for struct ip.ip_hl)
AC_CACHE_VAL(sc_cv_struct_ip_ip_hl,

View file

@ -3004,9 +3004,20 @@ startdit()enddit()nl()
label(GROUP_INTERFACE)em(bf(INTERFACE option group))
Options that control Linux INTERFACE addresses.
These options may be applied to addresses link(INTERFACE)(ADDRESS_INTERFACE) and
link(TUN)(ADDRESS_TUN). These address types and options are currently only
implemented on Linux operating system.
Note regarding VLANs: On incoming packets the Linux kernel strips off the VLAN
tag before passing the data to the user space program on raw sockets. Special
measures are required to get the VLAN information, see NOEXPAND(packet(7)) PACKET_AUXDATA,
and to optionally insert the tag into the packet again, use option
link(retrieve-vlan)(OPTION_RETRIEVE_VLAN) when you need this.
label(OPTION_RETRIEVE_VLAN)dit(bf(tt(retrieve-vlan)))
On packets incoming on raw sockets, retrieve the VLAN information and insert
it into the packets for further processing (Linux)
startdit()
label(OPTION_IFF_UP)dit(bf(tt(iff-up)))
Sets the TUN network interface status UP. Strongly recommended.
label(OPTION_IFF_BROADCAST)dit(bf(tt(iff-broadcast)))

View file

@ -10,6 +10,7 @@
#include "xioopen.h"
#include "xio-socket.h"
#include "xio-ascii.h"
#include "xio-interface.h"
@ -45,6 +46,9 @@ const struct optdesc opt_iff_portsel = { "iff-portsel", "portsel", O
const struct optdesc opt_iff_automedia = { "iff-automedia", "automedia", OPT_IFF_AUTOMEDIA, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(para.interface.iff_opts), IFF_AUTOMEDIA };
#endif
/*const struct optdesc opt_iff_dynamic = { "iff-dynamic", "dynamic", OPT_IFF_DYNAMIC, GROUP_INTERFACE, PH_FD, TYPE_BOOL, OFUNC_OFFSET_MASKS, XIO_OFFSETOF(para.interface.iff_opts), XIO_SIZEOF(short), IFF_DYNAMIC };*/
#ifdef PACKET_AUXDATA
const struct optdesc opt_retrieve_vlan = { "retrieve-vlan", NULL, OPT_RETRIEVE_VLAN, GROUP_INTERFACE, PH_LATE, TYPE_INT, OFUNC_SPEC };
#endif
#if LATER
const struct optdesc opt_route = { "route", NULL, OPT_ROUTE, GROUP_INTERFACE, PH_INIT, TYPE_STRING, OFUNC_SPEC };
#endif
@ -122,6 +126,23 @@ int _xioopen_interface(const char *ifname,
return 0;
}
int _interface_setsockopt_auxdata(int fd, int auxdata) {
#ifdef PACKET_AUXDATA
/* Linux strips VLAN tag off incoming packets and makes it available per
ancillary data as auxdata. Apply option packet-auxdata if you want the
VLAN tag to be restored by Socat in the received packet */
if (auxdata) {
int rc;
rc = Setsockopt(fd, SOL_PACKET, PACKET_AUXDATA, &auxdata, sizeof(auxdata));
if (rc < 0) {
Error3("setsockopt(%d, SOL_PACKET, PACKET_AUXDATA, , {%d}): %s",
fd, auxdata, strerror(errno));
}
}
#endif /* defined(PACKET_AUXDATA) */
return 0;
}
static
int xioopen_interface(int argc, const char *argv[], struct opt *opts,
int xioflags, xiofile_t *xxfd, groups_t groups,
@ -228,4 +249,69 @@ int _xiointerface_apply_iff(
return 0;
}
#if HAVE_STRUCT_CMSGHDR && HAVE_STRUCT_TPACKET_AUXDATA
/* Converts the ancillary message in *cmsg into a form useable for further
processing. Knows the specifics of common message types.
On PACKET_AUXDATA it stored the ancillary data in the XFD.
For other types:
returns the number of resulting syntax elements in *num,
returns a sequence of \0 terminated type strings in *typbuff,
returns a sequence of \0 terminated name strings in *nambuff,
returns a sequence of \0 terminated value strings in *valbuff,
the respective len parameters specify the available space in the buffers
returns STAT_OK or other STAT_*
*/
int
xiolog_ancillary_packet(struct single *sfd,
struct cmsghdr *cmsg, int *num,
char *typbuff, int typlen,
char *nambuff, int namlen,
char *envbuff, int envlen,
char *valbuff, int vallen) {
#if LATER
const char *cmsgtype, *cmsgname, *cmsgenvn;
size_t msglen;
#endif
struct tpacket_auxdata *auxp;
int rc = STAT_OK;
*num = 0;
#if defined(CMSG_DATA)
#if LATER
msglen = cmsg->cmsg_len-((char *)CMSG_DATA(cmsg)-(char *)cmsg);
#endif
switch (cmsg->cmsg_type) {
#if HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TPID
case PACKET_AUXDATA:
#if LATER
cmsgname = "packet_auxdata";
cmsgtype = "auxdata";
cmsgenvn = "AUXDATA";
#endif
auxp = (struct tpacket_auxdata *)CMSG_DATA(cmsg);
Info8("%s(): Ancillary message: PACKET_AUXDATA: status="F_uint32_t", len="F_uint32_t", snaplen="F_uint32_t", mac="F_uint16_t", net="F_uint16_t", vlan_tci="F_uint16_t", vlan_tpid="F_uint16_t"", __func__, auxp->tp_status, auxp->tp_len, auxp->tp_snaplen, auxp->tp_mac, auxp->tp_net, auxp->tp_vlan_tci, auxp->tp_vlan_tpid);
sfd->para.socket.ancill_data_packet_auxdata = *auxp;
sfd->para.socket.ancill_flag.packet_auxdata = 1;
snprintf(typbuff, typlen, "PACKET.%u", cmsg->cmsg_type);
nambuff[0] = '\0'; strncat(nambuff, "vlan", namlen-1);
snprintf(strchr(valbuff, '\0')-1/*def \n*/, vallen-strlen(valbuff)+1, ", %d", auxp->tp_vlan_tci);
break;
#endif /* HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TPID */
default: /* binary data */
Warn1("xiolog_ancillary_packet(): INTERNAL: cmsg_type=%d not handled", cmsg->cmsg_type);
return rc;
}
return rc;
#else /* !defined(CMSG_DATA) */
return STAT_NORETRY;
#endif /* !defined(CMSG_DATA) */
}
#endif /* HAVE_STRUCT_CMSGHDR && HAVE_STRUCT_TPACKET_AUXDATA */
#endif /* _WITH_INTERFACE */

View file

@ -25,11 +25,13 @@ extern const struct optdesc opt_iff_multicast;
extern const struct optdesc opt_iff_portsel;
extern const struct optdesc opt_iff_automedia;
/*extern const struct optdesc opt_iff_dynamic;*/
extern const struct optdesc opt_retrieve_vlan;
extern int xiolog_ancillary_packet(struct single *sfd, struct cmsghdr *cmsg, int *num, char *typbuff, int typlen, char *nambuff, int namlen, char *envbuff, int envlen, char *valbuff, int vallen);
extern int _xiointerface_get_iff(int sockfd, const char *name, short *save_iff);
extern int _xiointerface_set_iff(int sockfd, const char *name, short new_iff);
extern int _xiointerface_apply_iff(int sockfd, const char *name, short iff_opts[2]);
extern int _interface_setsockopt_auxdata(int fd, int auxdata);
#endif /* !defined(__xio_interface_h_included) */

View file

@ -475,11 +475,15 @@ int xiogetaddrinfo(const char *node, const char *service,
Returns STAT_OK on success
Returns STAT_WARNING if a buffer was too short and data truncated.
*/
int xiolog_ancillary_ip(struct cmsghdr *cmsg, int *num,
int xiolog_ancillary_ip(
struct single *sfd,
struct cmsghdr *cmsg,
int *num,
char *typbuff, int typlen,
char *nambuff, int namlen,
char *envbuff, int envlen,
char *valbuff, int vallen) {
char *valbuff, int vallen)
{
int cmsgctr = 0;
const char *cmsgtype, *cmsgname = NULL, *cmsgenvn = NULL;
size_t msglen;

View file

@ -43,12 +43,7 @@ extern int xiogetaddrinfo(const char *node, const char *service,
int family, int socktype, int protocol,
union sockaddr_union *sa, socklen_t *socklen,
unsigned long res_opts0, unsigned long res_opts1);
extern
int xiolog_ancillary_ip(struct cmsghdr *cmsg, int *num,
char *typbuff, int typlen,
char *nambuff, int namlen,
char *envbuff, int envlen,
char *valbuff, int vallen);
extern int xiolog_ancillary_ip(struct single *sfd, struct cmsghdr *cmsg, int *num, char *typbuff, int typlen, char *nambuff, int namlen, char *envbuff, int envlen, char *valbuff, int vallen);
extern int xiotype_ip_add_membership(char *token, const struct optname *ent, struct opt *opt);
extern int xioapply_ip_add_membership(xiosingle_t *xfd, struct opt *opt);
extern int xiotype_ip_add_source_membership(char* token, const struct optname *ent, struct opt *opt);

View file

@ -252,11 +252,15 @@ int xiocheckrange_ip6(struct sockaddr_in6 *pa, struct xiorange *range) {
the respective len parameters specify the available space in the buffers
returns STAT_OK on success
*/
int xiolog_ancillary_ip6(struct cmsghdr *cmsg, int *num,
int xiolog_ancillary_ip6(
struct single *xfd,
struct cmsghdr *cmsg,
int *num,
char *typbuff, int typlen,
char *nambuff, int namlen,
char *envbuff, int envlen,
char *valbuff, int vallen) {
char *valbuff, int vallen)
{
char scratch1[42]; /* can hold an IPv6 address in ASCII */
char scratch2[32];
size_t msglen;

View file

@ -40,11 +40,7 @@ extern int xiorange_ip6andmask(struct xiorange *range);
extern
int xiocheckrange_ip6(struct sockaddr_in6 *pa, struct xiorange *range);
extern
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);
int xiolog_ancillary_ip6(struct single *sfd, struct cmsghdr *cmsg, int *num, char *typbuff, int typlen, char *nambuff, int namlen, char *envbuff, int envlen, char *valbuff, int vallen);
extern int
xiosetsockaddrenv_ip6(int idx, char *namebuff, size_t namelen,
char *valuebuff, size_t valuelen,

View file

@ -110,7 +110,7 @@ int xioopen_ipapp_connect(int argc, const char *argv[], struct opt *opts,
level = E_WARN; /* most users won't expect a problem here,
so Notice is too weak */
}
while ((pid = xio_fork(false, level, xfd->para.socket.shutup)) < 0) {
while ((pid = xio_fork(false, level, xfd->shutup)) < 0) {
if (xfd->forever || --xfd->retry) {
Nanosleep(&xfd->intervall, NULL); continue;
}

View file

@ -20,7 +20,7 @@
const struct optdesc opt_backlog = { "backlog", NULL, OPT_BACKLOG, GROUP_LISTEN, PH_LISTEN, TYPE_INT, OFUNC_SPEC };
const struct optdesc opt_fork = { "fork", NULL, OPT_FORK, GROUP_CHILD, PH_PASTACCEPT, TYPE_BOOL, OFUNC_SPEC };
const struct optdesc opt_max_children = { "max-children", NULL, OPT_MAX_CHILDREN, GROUP_CHILD, PH_PASTACCEPT, TYPE_INT, OFUNC_SPEC };
const struct optdesc opt_children_shutup = { "children-shutup", "child-shutup", OPT_CHILDREN_SHUTUP, GROUP_CHILD, PH_PASTACCEPT, TYPE_INT, OFUNC_OFFSET, XIO_OFFSETOF(para.socket.shutup) };
const struct optdesc opt_children_shutup = { "children-shutup", "child-shutup", OPT_CHILDREN_SHUTUP, GROUP_CHILD, PH_PASTACCEPT, TYPE_INT, OFUNC_OFFSET, XIO_OFFSETOF(shutup) };
/**/
#if (WITH_UDP || WITH_TCP)
const struct optdesc opt_range = { "range", NULL, OPT_RANGE, GROUP_RANGE, PH_ACCEPT, TYPE_STRING, OFUNC_SPEC };
@ -346,7 +346,7 @@ int _xioopen_listen(struct single *xfd, int xioflags, struct sockaddr *us, sockl
if ((pid =
xio_fork(false, level==E_ERROR?level:E_WARN,
xfd->para.socket.shutup))
xfd->shutup))
< 0) {
Close(xfd->fd);
Sigprocmask(SIG_UNBLOCK, &mask_sigchld, NULL);

View file

@ -409,7 +409,7 @@ static int
if (xfd->forever || xfd->retry) {
level = E_WARN;
}
while ((pid = xio_fork(false, level, xfd->para.socket.shutup)) < 0) {
while ((pid = xio_fork(false, level, xfd->shutup)) < 0) {
if (xfd->forever || --xfd->retry) {
Nanosleep(&xfd->intervall, NULL); continue;
}

View file

@ -199,7 +199,7 @@ static int xioopen_proxy_connect(int argc, const char *argv[], struct opt *opts,
if (xfd->forever || xfd->retry) {
level = E_WARN;
}
while ((pid = xio_fork(false, level, xfd->para.socket.shutup)) < 0) {
while ((pid = xio_fork(false, level, xfd->shutup)) < 0) {
if (xfd->forever || --xfd->retry) {
Nanosleep(&xfd->intervall, NULL); continue;
}

View file

@ -62,7 +62,7 @@ int _xioopen_socket_sendto(const char *pfname, const char *type,
groups_t groups);
static int
xiolog_ancillary_socket(struct cmsghdr *cmsg, int *num,
xiolog_ancillary_socket(struct single *sfd, struct cmsghdr *cmsg, int *num,
char *typbuff, int typlen,
char *nambuff, int namlen,
char *envbuff, int envlen,
@ -713,7 +713,7 @@ int xioopen_socket_datagram(int argc, const char *argv[], struct opt *opts,
#endif /* WITH_GENERICSOCKET */
/* EINTR not handled specially */
int xiogetpacketinfo(int fd)
int xiogetpacketinfo(struct single *sfd, int fd)
{
#if defined(MSG_ERRQUEUE)
int _errno = errno;
@ -748,7 +748,7 @@ int xiogetpacketinfo(int fd)
sockaddr_info(&pa->soa, palen, peername, sizeof(peername))/*,
sockaddr_info(&la->soa, sockname, sizeof(sockname))*/);
xiodopacketinfo(&msgh, true, true);
xiodopacketinfo(sfd, &msgh, true, true);
}
errno = _errno;
#endif /* defined(MSG_ERRQUEUE) */
@ -898,7 +898,7 @@ int _xioopen_connect(struct single *xfd, union sockaddr_union *us, size_t uslen,
return STAT_RETRYLATER;
} else {
/* try to find details about error, especially from ICMP */
xiogetpacketinfo(xfd->fd);
xiogetpacketinfo(xfd, xfd->fd);
/* continue mainstream */
Msg4(level, "connect(%d, %s, "F_Zd"): %s",
@ -994,7 +994,7 @@ int xioopen_connect(struct single *xfd, union sockaddr_union *us, size_t uslen,
so Notice is too weak */
}
while ((pid = xio_fork(false, level, xfd->para.socket.shutup)) < 0) {
while ((pid = xio_fork(false, level, xfd->shutup)) < 0) {
--xfd->retry;
if (xfd->forever || xfd->retry) {
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
@ -1079,7 +1079,7 @@ int _xioopen_dgram_sendto(/* them is already in xfd->peersa */
applyopts_named(us->un.sun_path, opts, PH_LATE);
}
#endif
/*applyopts(xfd->fd, opts, PH_LATE);*/
/*0 applyopts(xfd->fd, opts, PH_LATE); */
/* xfd->dtype = DATA_RECVFROM; *//* no, the caller must set this (ev _SKIPIP) */
Notice1("successfully prepared local socket %s",
@ -1260,7 +1260,7 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
sockaddr_info(&pa->soa, palen, peername, sizeof(peername))/*,
sockaddr_info(&la->soa, sockname, sizeof(sockname))*/);
xiodopacketinfo(&msgh, true, true);
xiodopacketinfo(xfd, &msgh, true, true);
if (xiocheckpeer(xfd, pa, la) < 0) {
/* drop packet */
@ -1289,7 +1289,7 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
Error1("socketpair(PF_UNIX, SOCK_STREAM, 0, ...): %s", strerror(errno));
}
if ((pid = xio_fork(false, level, xfd->para.socket.shutup)) < 0) {
if ((pid = xio_fork(false, level, xfd->shutup)) < 0) {
Close(trigger[0]);
Close(trigger[1]);
Close(xfd->fd);
@ -1461,7 +1461,12 @@ int xiogetancillary(int fd, struct msghdr *msgh, int flags) {
and logs the relevant information (E_DEBUG, E_INFO).
calls protocol/layer specific functions for handling the messages
creates appropriate environment vars if withenv is set */
int xiodopacketinfo(struct msghdr *msgh, bool withlog, bool withenv) {
int xiodopacketinfo(
struct single *sfd,
struct msghdr *msgh,
bool withlog,
bool withenv)
{
#if defined(HAVE_STRUCT_CMSGHDR) && defined(CMSG_DATA)
struct cmsghdr *cmsg;
@ -1490,14 +1495,14 @@ int xiodopacketinfo(struct msghdr *msgh, bool withlog, bool withenv) {
dependent */
switch (cmsg->cmsg_level) {
case SOL_SOCKET:
xiolog_ancillary_socket(cmsg, &num, typbuff, sizeof(typbuff)-1,
xiolog_ancillary_socket(sfd, cmsg, &num, typbuff, sizeof(typbuff)-1,
nambuff, sizeof(nambuff)-1,
envbuff, sizeof(envbuff)-1,
valbuff, sizeof(valbuff)-1);
break;
#if WITH_IP4 || WITH_IP6
case SOL_IP:
xiolog_ancillary_ip(cmsg, &num, typbuff, sizeof(typbuff)-1,
xiolog_ancillary_ip(sfd, cmsg, &num, typbuff, sizeof(typbuff)-1,
nambuff, sizeof(nambuff)-1,
envbuff, sizeof(envbuff)-1,
valbuff, sizeof(valbuff)-1);
@ -1505,12 +1510,20 @@ int xiodopacketinfo(struct msghdr *msgh, bool withlog, bool withenv) {
#endif /* WITH_IP4 || WITH_IP6 */
#if WITH_IP6
case SOL_IPV6:
xiolog_ancillary_ip6(cmsg, &num, typbuff, sizeof(typbuff)-1,
xiolog_ancillary_ip6(sfd, cmsg, &num, typbuff, sizeof(typbuff)-1,
nambuff, sizeof(nambuff)-1,
envbuff, sizeof(envbuff)-1,
valbuff, sizeof(valbuff)-1);
break;
#endif /* WITH_IP6 */
#if HAVE_STRUCT_CMSGHDR && HAVE_STRUCT_TPACKET_AUXDATA
case SOL_PACKET:
xiolog_ancillary_packet(sfd, cmsg, &num, typbuff, sizeof(typbuff)-1,
nambuff, sizeof(nambuff)-1,
envbuff, sizeof(envbuff)-1,
valbuff, sizeof(valbuff)-1);
break;
#endif /* HAVE_STRUCT_CMSGHDR && HAVE_STRUCT_TPACKET_AUXDATA */
default:
num = 1;
snprintf(typbuff, sizeof(typbuff)-1, "LEVEL%u", cmsg->cmsg_level);
@ -1680,11 +1693,15 @@ int xiocheckpeer(xiosingle_t *xfd,
returns STAT_OK or other STAT_*
*/
static int
xiolog_ancillary_socket(struct cmsghdr *cmsg, int *num,
xiolog_ancillary_socket(
struct single *sfd,
struct cmsghdr *cmsg,
int *num,
char *typbuff, int typlen,
char *nambuff, int namlen,
char *envbuff, int envlen,
char *valbuff, int vallen) {
char *valbuff, int vallen)
{
const char *cmsgtype, *cmsgname, *cmsgenvn;
size_t msglen;
struct timeval *tv;

View file

@ -116,8 +116,7 @@ int _xioopen_dgram_recv(struct single *xfd, int xioflags,
struct sockaddr *us, socklen_t uslen,
struct opt *opts, int pf, int socktype, int proto,
int level);
extern
int xiodopacketinfo(struct msghdr *msgh, bool withlog, bool withenv);
extern int xiodopacketinfo(struct single *sfd, struct msghdr *msgh, bool withlog, bool withenv);
extern
int xiogetpacketsrc(int fd, struct msghdr *msgh, int flags);
extern

View file

@ -175,7 +175,7 @@ static int xioopen_socks4_connect(int argc, const char *argv[], struct opt *opts
level = E_WARN; /* most users won't expect a problem here,
so Notice is too weak */
}
while ((pid = xio_fork(false, level, xfd->para.socket.shutup)) < 0) {
while ((pid = xio_fork(false, level, xfd->shutup)) < 0) {
if (xfd->forever || --xfd->retry) {
Nanosleep(&xfd->intervall, NULL);
continue;

View file

@ -214,7 +214,7 @@ int _xioopen_ipdgram_listen(struct single *sfd,
sockaddr_info(&them->soa, themlen, infobuff, sizeof(infobuff)));
if (dofork) {
pid = xio_fork(false, E_ERROR, sfd->para.socket.shutup);
pid = xio_fork(false, E_ERROR, sfd->shutup);
if (pid < 0) {
return STAT_RETRYLATER;
}

View file

@ -315,7 +315,7 @@ static int xioopen_unix_connect(int argc, const char *argv[], struct opt *opts,
so Notice is too weak */
}
while ((pid = xio_fork(false, level, xfd->para.socket.shutup)) < 0) {
while ((pid = xio_fork(false, level, xfd->shutup)) < 0) {
--xfd->retry;
if (xfd->forever || xfd->retry) {
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);

12
xio.h
View file

@ -206,6 +206,7 @@ typedef struct single {
int (*sigchild)(struct single *); /* callback after sigchild */
int escape; /* escape character; -1 for no escape */
bool actescape; /* escape character found in input data */
int shutup; /* children-shutup option */
union {
struct {
int fdout; /* use fd for output */
@ -224,8 +225,14 @@ typedef struct single {
#if _WITH_IP4 || _WITH_IP6
struct para_ip ip;
#endif /* _WITH_IP4 || _WITH_IP6 */
int shutup;
/* up to here, keep consistent copy in openssl part !!! */
#if HAVE_STRUCT_TPACKET_AUXDATA
struct {
int packet_auxdata;
} ancill_flag;
#endif
#if HAVE_STRUCT_TPACKET_AUXDATA
struct tpacket_auxdata ancill_data_packet_auxdata;
#endif
#if WITH_UNIX
struct {
bool tight;
@ -265,7 +272,6 @@ typedef struct single {
#if _WITH_IP4 || _WITH_IP6
struct para_ip ip;
#endif /* _WITH_IP4 || _WITH_IP6 */
int shutup;
/* end of the para.socket structure copy */
SSL_CTX* ctx; /* for freeing on close */
SSL *ssl;

View file

@ -1397,6 +1397,9 @@ const struct optname optionnames[] = {
IF_PROXY ("resolve", &opt_proxy_resolve)
#ifdef IP_RETOPTS
IF_IP ("retopts", &opt_ip_retopts)
#endif
#if WITH_INTERFACE && defined(PACKET_AUXDATA)
IF_SOCKET ("retrieve-vlan", &opt_retrieve_vlan)
#endif
IF_RETRY ("retry", &opt_retry)
IF_SOCKET ("reuseaddr", &opt_so_reuseaddr)
@ -3710,6 +3713,17 @@ int applyopts(int fd, struct opt *opts, enum e_phase phase) {
}
break;
#if _WITH_INTERFACE
case OPT_RETRIEVE_VLAN:
if (!xioparms.experimental) {
Warn("option retrieve-vlan is experimental");
}
if (_interface_setsockopt_auxdata(fd, 1) < 0) {
return -1;
}
break;
#endif /* _WITH_INTERFACE */
default: Error1("applyopts(): option \"%s\" not implemented",
opt->desc->defname);
opt->desc = ODESC_ERROR; ++opt; continue;

View file

@ -614,6 +614,7 @@ enum e_optcode {
OPT_RES_RECURSE, /* resolver(3) */
OPT_RES_STAYOPEN, /* resolver(3) */
OPT_RES_USEVC, /* resolver(3) */
OPT_RETRIEVE_VLAN, /* Linux: get VLAN info on raw sockets per auxdata */
OPT_RETRY,
OPT_SANE, /* termios */
OPT_SCTP_MAXSEG,

View file

@ -198,6 +198,28 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
}
#endif /* defined(PF_PACKET) && !defined(PACKET_IGNORE_OUTGOING) && defined(PACKET_OUTGOING) */
#if defined(PF_PACKET) && HAVE_STRUCT_TPACKET_AUXDATA
if (from.soa.sa_family == PF_PACKET) {
Debug3("xioread(FD=%d, ...): auxdata: flag=%d, vlan-id=%d",
pipe->fd, pipe->para.socket.ancill_flag.packet_auxdata,
pipe->para.socket.ancill_data_packet_auxdata.tp_vlan_tci);
if (pipe->para.socket.ancill_flag.packet_auxdata &&
pipe->para.socket.ancill_data_packet_auxdata.tp_vlan_tci != 0) {
int offs = 12; /* packet type id in Ethernet header */
Debug1("xioread(%d, ...): restoring VLAN id from auxdata->tp_vlan_tci",
pipe->fd);
if (bytes+4 > bufsiz) {
Error("buffer too small to restore VLAN id");
}
memmove((char *)buff+offs+4, (char *)buff+offs, bytes-offs);
((unsigned short *)((char *)buff+offs))[0] = htons(ETH_P_8021Q);
((unsigned short *)((char *)buff+offs))[1] =
htons(pipe->para.socket.ancill_data_packet_auxdata.tp_vlan_tci);
bytes += 4;
}
}
#endif /* defined(PF_PACKET && HAVE_STRUCT_TPACKET_AUXDATA */
Notice2("received packet with "F_Zu" bytes from %s",
bytes,
sockaddr_info(&from.soa, fromlen, infobuff, sizeof(infobuff)));
@ -384,7 +406,7 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
errno == EINTR) ;
if (rc < 0) return -1;
xiodopacketinfo(&msgh, true, false);
xiodopacketinfo(pipe, &msgh, true, false);
if (xiocheckpeer(pipe, &from, &pipe->para.socket.la) < 0) {
Recvfrom(pipe->fd, buff, bufsiz, 0, &from.soa, &fromlen); /* drop */
errno = EAGAIN; return -1;
@ -420,6 +442,29 @@ ssize_t xioread(xiofile_t *file, void *buff, size_t bufsiz) {
}
#endif /* defined(PF_PACKET) && !defined(PACKET_IGNORE_OUTGOING) && defined(PACKET_OUTGOING) */
#if defined(PF_PACKET) && HAVE_STRUCT_TPACKET_AUXDATA
if (from.soa.sa_family == PF_PACKET) {
Debug3("xioread(%d, ...): auxdata: flag=%d, vlan-id=%d",
pipe->fd, pipe->para.socket.ancill_flag.packet_auxdata,
pipe->para.socket.ancill_data_packet_auxdata.tp_vlan_tci);
if (pipe->para.socket.ancill_flag.packet_auxdata &&
pipe->para.socket.ancill_data_packet_auxdata.tp_vlan_tci &&
pipe->para.socket.ancill_data_packet_auxdata.tp_net >= 2) {
Debug2("xioread(%d, ...): restoring VLAN id %d", pipe->fd, pipe->para.socket.ancill_data_packet_auxdata.tp_vlan_tci);
int offs = pipe->para.socket.ancill_data_packet_auxdata.tp_net - 2;
if (bytes+4 > bufsiz) {
Error("buffer too small to restore VLAN id");
}
Debug3("xioread(): memmove(%p, %p, "F_Zu")", (char *)buff+offs+4, (char *)buff+offs, bytes-offs);
memmove((char *)buff+offs+4, (char *)buff+offs, bytes-offs);
((unsigned short *)((char *)buff+offs))[0] = htons(ETH_P_8021Q);
((unsigned short *)((char *)buff+offs))[1] =
htons(pipe->para.socket.ancill_data_packet_auxdata.tp_vlan_tci);
bytes += 4;
}
}
#endif /* defined(PF_PACKET) &&& HAVE_STRUCT_TPACKET_AUXDATA */
Notice2("received packet with "F_Zu" bytes from %s",
bytes,
sockaddr_info(&from.soa, fromlen, infobuff, sizeof(infobuff)));