mirror of
https://repo.or.cz/socat.git
synced 2024-12-22 15:32:35 +00:00
New option retrieve-vlan (experimental)
This commit is contained in:
parent
11d1e9e11f
commit
b5640dd707
24 changed files with 273 additions and 55 deletions
9
CHANGES
9
CHANGES
|
@ -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/
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
"1.7.4.5+vlans"
|
||||
"1.7.4.5+"
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
23
configure.ac
23
configure.ac
|
@ -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,
|
||||
|
|
15
doc/socat.yo
15
doc/socat.yo
|
@ -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)))
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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) */
|
||||
|
|
14
xio-ip.c
14
xio-ip.c
|
@ -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,
|
||||
char *typbuff, int typlen,
|
||||
char *nambuff, int namlen,
|
||||
char *envbuff, int envlen,
|
||||
char *valbuff, int vallen) {
|
||||
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)
|
||||
{
|
||||
int cmsgctr = 0;
|
||||
const char *cmsgtype, *cmsgname = NULL, *cmsgenvn = NULL;
|
||||
size_t msglen;
|
||||
|
|
7
xio-ip.h
7
xio-ip.h
|
@ -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);
|
||||
|
|
14
xio-ip6.c
14
xio-ip6.c
|
@ -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,
|
||||
char *typbuff, int typlen,
|
||||
char *nambuff, int namlen,
|
||||
char *envbuff, int envlen,
|
||||
char *valbuff, int vallen) {
|
||||
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 scratch1[42]; /* can hold an IPv6 address in ASCII */
|
||||
char scratch2[32];
|
||||
size_t msglen;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
51
xio-socket.c
51
xio-socket.c
|
@ -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,
|
||||
char *typbuff, int typlen,
|
||||
char *nambuff, int namlen,
|
||||
char *envbuff, int envlen,
|
||||
char *valbuff, int vallen) {
|
||||
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)
|
||||
{
|
||||
const char *cmsgtype, *cmsgname, *cmsgenvn;
|
||||
size_t msglen;
|
||||
struct timeval *tv;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
12
xio.h
|
@ -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;
|
||||
|
|
14
xioopts.c
14
xioopts.c
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
47
xioread.c
47
xioread.c
|
@ -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)));
|
||||
|
|
Loading…
Reference in a new issue