mirror of
https://repo.or.cz/socat.git
synced 2024-12-23 07:52:32 +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.
|
messages in LISTEN and CONNECT type sub processes.
|
||||||
Test: CHILDREN_SHUTUP
|
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:
|
Corrections:
|
||||||
When a sub process (EXEC, SYSTEM) terminated with exit code other than
|
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/
|
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 */
|
/* define if you have struct in6_pktinfo */
|
||||||
#undef 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 */
|
/* define if your struct ip has ip_hl; otherwise assume ip_vhl */
|
||||||
#undef HAVE_STRUCT_IP_IP_HL
|
#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
|
fi
|
||||||
AC_MSG_RESULT($sc_cv_struct_in6_pktinfo)
|
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
|
dnl check for ip_hl in struct ip
|
||||||
AC_MSG_CHECKING(for struct ip.ip_hl)
|
AC_MSG_CHECKING(for struct ip.ip_hl)
|
||||||
AC_CACHE_VAL(sc_cv_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))
|
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)))
|
label(OPTION_IFF_UP)dit(bf(tt(iff-up)))
|
||||||
Sets the TUN network interface status UP. Strongly recommended.
|
Sets the TUN network interface status UP. Strongly recommended.
|
||||||
label(OPTION_IFF_BROADCAST)dit(bf(tt(iff-broadcast)))
|
label(OPTION_IFF_BROADCAST)dit(bf(tt(iff-broadcast)))
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#include "xioopen.h"
|
#include "xioopen.h"
|
||||||
#include "xio-socket.h"
|
#include "xio-socket.h"
|
||||||
|
#include "xio-ascii.h"
|
||||||
|
|
||||||
#include "xio-interface.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 };
|
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
|
#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 };*/
|
/*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
|
#if LATER
|
||||||
const struct optdesc opt_route = { "route", NULL, OPT_ROUTE, GROUP_INTERFACE, PH_INIT, TYPE_STRING, OFUNC_SPEC };
|
const struct optdesc opt_route = { "route", NULL, OPT_ROUTE, GROUP_INTERFACE, PH_INIT, TYPE_STRING, OFUNC_SPEC };
|
||||||
#endif
|
#endif
|
||||||
|
@ -122,6 +126,23 @@ int _xioopen_interface(const char *ifname,
|
||||||
return 0;
|
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
|
static
|
||||||
int xioopen_interface(int argc, const char *argv[], struct opt *opts,
|
int xioopen_interface(int argc, const char *argv[], struct opt *opts,
|
||||||
int xioflags, xiofile_t *xxfd, groups_t groups,
|
int xioflags, xiofile_t *xxfd, groups_t groups,
|
||||||
|
@ -228,4 +249,69 @@ int _xiointerface_apply_iff(
|
||||||
return 0;
|
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 */
|
#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_portsel;
|
||||||
extern const struct optdesc opt_iff_automedia;
|
extern const struct optdesc opt_iff_automedia;
|
||||||
/*extern const struct optdesc opt_iff_dynamic;*/
|
/*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 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_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_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 _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) */
|
#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_OK on success
|
||||||
Returns STAT_WARNING if a buffer was too short and data truncated.
|
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(
|
||||||
char *typbuff, int typlen,
|
struct single *sfd,
|
||||||
char *nambuff, int namlen,
|
struct cmsghdr *cmsg,
|
||||||
char *envbuff, int envlen,
|
int *num,
|
||||||
char *valbuff, int vallen) {
|
char *typbuff, int typlen,
|
||||||
|
char *nambuff, int namlen,
|
||||||
|
char *envbuff, int envlen,
|
||||||
|
char *valbuff, int vallen)
|
||||||
|
{
|
||||||
int cmsgctr = 0;
|
int cmsgctr = 0;
|
||||||
const char *cmsgtype, *cmsgname = NULL, *cmsgenvn = NULL;
|
const char *cmsgtype, *cmsgname = NULL, *cmsgenvn = NULL;
|
||||||
size_t msglen;
|
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,
|
int family, int socktype, int protocol,
|
||||||
union sockaddr_union *sa, socklen_t *socklen,
|
union sockaddr_union *sa, socklen_t *socklen,
|
||||||
unsigned long res_opts0, unsigned long res_opts1);
|
unsigned long res_opts0, unsigned long res_opts1);
|
||||||
extern
|
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);
|
||||||
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 xiotype_ip_add_membership(char *token, const struct optname *ent, struct opt *opt);
|
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 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);
|
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
|
the respective len parameters specify the available space in the buffers
|
||||||
returns STAT_OK on success
|
returns STAT_OK on success
|
||||||
*/
|
*/
|
||||||
int xiolog_ancillary_ip6(struct cmsghdr *cmsg, int *num,
|
int xiolog_ancillary_ip6(
|
||||||
char *typbuff, int typlen,
|
struct single *xfd,
|
||||||
char *nambuff, int namlen,
|
struct cmsghdr *cmsg,
|
||||||
char *envbuff, int envlen,
|
int *num,
|
||||||
char *valbuff, int vallen) {
|
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 scratch1[42]; /* can hold an IPv6 address in ASCII */
|
||||||
char scratch2[32];
|
char scratch2[32];
|
||||||
size_t msglen;
|
size_t msglen;
|
||||||
|
|
|
@ -40,11 +40,7 @@ extern int xiorange_ip6andmask(struct xiorange *range);
|
||||||
extern
|
extern
|
||||||
int xiocheckrange_ip6(struct sockaddr_in6 *pa, struct xiorange *range);
|
int xiocheckrange_ip6(struct sockaddr_in6 *pa, struct xiorange *range);
|
||||||
extern
|
extern
|
||||||
int xiolog_ancillary_ip6(struct cmsghdr *cmsg, int *num,
|
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);
|
||||||
char *typbuff, int typlen,
|
|
||||||
char *nambuff, int namlen,
|
|
||||||
char *envbuff, int envlen,
|
|
||||||
char *valbuff, int vallen);
|
|
||||||
extern int
|
extern int
|
||||||
xiosetsockaddrenv_ip6(int idx, char *namebuff, size_t namelen,
|
xiosetsockaddrenv_ip6(int idx, char *namebuff, size_t namelen,
|
||||||
char *valuebuff, size_t valuelen,
|
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,
|
level = E_WARN; /* most users won't expect a problem here,
|
||||||
so Notice is too weak */
|
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) {
|
if (xfd->forever || --xfd->retry) {
|
||||||
Nanosleep(&xfd->intervall, NULL); continue;
|
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_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_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_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)
|
#if (WITH_UDP || WITH_TCP)
|
||||||
const struct optdesc opt_range = { "range", NULL, OPT_RANGE, GROUP_RANGE, PH_ACCEPT, TYPE_STRING, OFUNC_SPEC };
|
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 =
|
if ((pid =
|
||||||
xio_fork(false, level==E_ERROR?level:E_WARN,
|
xio_fork(false, level==E_ERROR?level:E_WARN,
|
||||||
xfd->para.socket.shutup))
|
xfd->shutup))
|
||||||
< 0) {
|
< 0) {
|
||||||
Close(xfd->fd);
|
Close(xfd->fd);
|
||||||
Sigprocmask(SIG_UNBLOCK, &mask_sigchld, NULL);
|
Sigprocmask(SIG_UNBLOCK, &mask_sigchld, NULL);
|
||||||
|
|
|
@ -409,7 +409,7 @@ static int
|
||||||
if (xfd->forever || xfd->retry) {
|
if (xfd->forever || xfd->retry) {
|
||||||
level = E_WARN;
|
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) {
|
if (xfd->forever || --xfd->retry) {
|
||||||
Nanosleep(&xfd->intervall, NULL); continue;
|
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) {
|
if (xfd->forever || xfd->retry) {
|
||||||
level = E_WARN;
|
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) {
|
if (xfd->forever || --xfd->retry) {
|
||||||
Nanosleep(&xfd->intervall, NULL); continue;
|
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);
|
groups_t groups);
|
||||||
|
|
||||||
static int
|
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 *typbuff, int typlen,
|
||||||
char *nambuff, int namlen,
|
char *nambuff, int namlen,
|
||||||
char *envbuff, int envlen,
|
char *envbuff, int envlen,
|
||||||
|
@ -713,7 +713,7 @@ int xioopen_socket_datagram(int argc, const char *argv[], struct opt *opts,
|
||||||
#endif /* WITH_GENERICSOCKET */
|
#endif /* WITH_GENERICSOCKET */
|
||||||
|
|
||||||
/* EINTR not handled specially */
|
/* EINTR not handled specially */
|
||||||
int xiogetpacketinfo(int fd)
|
int xiogetpacketinfo(struct single *sfd, int fd)
|
||||||
{
|
{
|
||||||
#if defined(MSG_ERRQUEUE)
|
#if defined(MSG_ERRQUEUE)
|
||||||
int _errno = errno;
|
int _errno = errno;
|
||||||
|
@ -748,7 +748,7 @@ int xiogetpacketinfo(int fd)
|
||||||
sockaddr_info(&pa->soa, palen, peername, sizeof(peername))/*,
|
sockaddr_info(&pa->soa, palen, peername, sizeof(peername))/*,
|
||||||
sockaddr_info(&la->soa, sockname, sizeof(sockname))*/);
|
sockaddr_info(&la->soa, sockname, sizeof(sockname))*/);
|
||||||
|
|
||||||
xiodopacketinfo(&msgh, true, true);
|
xiodopacketinfo(sfd, &msgh, true, true);
|
||||||
}
|
}
|
||||||
errno = _errno;
|
errno = _errno;
|
||||||
#endif /* defined(MSG_ERRQUEUE) */
|
#endif /* defined(MSG_ERRQUEUE) */
|
||||||
|
@ -898,7 +898,7 @@ int _xioopen_connect(struct single *xfd, union sockaddr_union *us, size_t uslen,
|
||||||
return STAT_RETRYLATER;
|
return STAT_RETRYLATER;
|
||||||
} else {
|
} else {
|
||||||
/* try to find details about error, especially from ICMP */
|
/* try to find details about error, especially from ICMP */
|
||||||
xiogetpacketinfo(xfd->fd);
|
xiogetpacketinfo(xfd, xfd->fd);
|
||||||
|
|
||||||
/* continue mainstream */
|
/* continue mainstream */
|
||||||
Msg4(level, "connect(%d, %s, "F_Zd"): %s",
|
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 */
|
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;
|
--xfd->retry;
|
||||||
if (xfd->forever || xfd->retry) {
|
if (xfd->forever || xfd->retry) {
|
||||||
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
|
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);
|
applyopts_named(us->un.sun_path, opts, PH_LATE);
|
||||||
}
|
}
|
||||||
#endif
|
#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) */
|
/* xfd->dtype = DATA_RECVFROM; *//* no, the caller must set this (ev _SKIPIP) */
|
||||||
Notice1("successfully prepared local socket %s",
|
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(&pa->soa, palen, peername, sizeof(peername))/*,
|
||||||
sockaddr_info(&la->soa, sockname, sizeof(sockname))*/);
|
sockaddr_info(&la->soa, sockname, sizeof(sockname))*/);
|
||||||
|
|
||||||
xiodopacketinfo(&msgh, true, true);
|
xiodopacketinfo(xfd, &msgh, true, true);
|
||||||
|
|
||||||
if (xiocheckpeer(xfd, pa, la) < 0) {
|
if (xiocheckpeer(xfd, pa, la) < 0) {
|
||||||
/* drop packet */
|
/* 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));
|
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[0]);
|
||||||
Close(trigger[1]);
|
Close(trigger[1]);
|
||||||
Close(xfd->fd);
|
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).
|
and logs the relevant information (E_DEBUG, E_INFO).
|
||||||
calls protocol/layer specific functions for handling the messages
|
calls protocol/layer specific functions for handling the messages
|
||||||
creates appropriate environment vars if withenv is set */
|
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)
|
#if defined(HAVE_STRUCT_CMSGHDR) && defined(CMSG_DATA)
|
||||||
struct cmsghdr *cmsg;
|
struct cmsghdr *cmsg;
|
||||||
|
|
||||||
|
@ -1490,14 +1495,14 @@ int xiodopacketinfo(struct msghdr *msgh, bool withlog, bool withenv) {
|
||||||
dependent */
|
dependent */
|
||||||
switch (cmsg->cmsg_level) {
|
switch (cmsg->cmsg_level) {
|
||||||
case SOL_SOCKET:
|
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,
|
nambuff, sizeof(nambuff)-1,
|
||||||
envbuff, sizeof(envbuff)-1,
|
envbuff, sizeof(envbuff)-1,
|
||||||
valbuff, sizeof(valbuff)-1);
|
valbuff, sizeof(valbuff)-1);
|
||||||
break;
|
break;
|
||||||
#if WITH_IP4 || WITH_IP6
|
#if WITH_IP4 || WITH_IP6
|
||||||
case SOL_IP:
|
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,
|
nambuff, sizeof(nambuff)-1,
|
||||||
envbuff, sizeof(envbuff)-1,
|
envbuff, sizeof(envbuff)-1,
|
||||||
valbuff, sizeof(valbuff)-1);
|
valbuff, sizeof(valbuff)-1);
|
||||||
|
@ -1505,12 +1510,20 @@ int xiodopacketinfo(struct msghdr *msgh, bool withlog, bool withenv) {
|
||||||
#endif /* WITH_IP4 || WITH_IP6 */
|
#endif /* WITH_IP4 || WITH_IP6 */
|
||||||
#if WITH_IP6
|
#if WITH_IP6
|
||||||
case SOL_IPV6:
|
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,
|
nambuff, sizeof(nambuff)-1,
|
||||||
envbuff, sizeof(envbuff)-1,
|
envbuff, sizeof(envbuff)-1,
|
||||||
valbuff, sizeof(valbuff)-1);
|
valbuff, sizeof(valbuff)-1);
|
||||||
break;
|
break;
|
||||||
#endif /* WITH_IP6 */
|
#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:
|
default:
|
||||||
num = 1;
|
num = 1;
|
||||||
snprintf(typbuff, sizeof(typbuff)-1, "LEVEL%u", cmsg->cmsg_level);
|
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_*
|
returns STAT_OK or other STAT_*
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
xiolog_ancillary_socket(struct cmsghdr *cmsg, int *num,
|
xiolog_ancillary_socket(
|
||||||
char *typbuff, int typlen,
|
struct single *sfd,
|
||||||
char *nambuff, int namlen,
|
struct cmsghdr *cmsg,
|
||||||
char *envbuff, int envlen,
|
int *num,
|
||||||
char *valbuff, int vallen) {
|
char *typbuff, int typlen,
|
||||||
|
char *nambuff, int namlen,
|
||||||
|
char *envbuff, int envlen,
|
||||||
|
char *valbuff, int vallen)
|
||||||
|
{
|
||||||
const char *cmsgtype, *cmsgname, *cmsgenvn;
|
const char *cmsgtype, *cmsgname, *cmsgenvn;
|
||||||
size_t msglen;
|
size_t msglen;
|
||||||
struct timeval *tv;
|
struct timeval *tv;
|
||||||
|
|
|
@ -116,8 +116,7 @@ int _xioopen_dgram_recv(struct single *xfd, int xioflags,
|
||||||
struct sockaddr *us, socklen_t uslen,
|
struct sockaddr *us, socklen_t uslen,
|
||||||
struct opt *opts, int pf, int socktype, int proto,
|
struct opt *opts, int pf, int socktype, int proto,
|
||||||
int level);
|
int level);
|
||||||
extern
|
extern int xiodopacketinfo(struct single *sfd, struct msghdr *msgh, bool withlog, bool withenv);
|
||||||
int xiodopacketinfo(struct msghdr *msgh, bool withlog, bool withenv);
|
|
||||||
extern
|
extern
|
||||||
int xiogetpacketsrc(int fd, struct msghdr *msgh, int flags);
|
int xiogetpacketsrc(int fd, struct msghdr *msgh, int flags);
|
||||||
extern
|
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,
|
level = E_WARN; /* most users won't expect a problem here,
|
||||||
so Notice is too weak */
|
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) {
|
if (xfd->forever || --xfd->retry) {
|
||||||
Nanosleep(&xfd->intervall, NULL);
|
Nanosleep(&xfd->intervall, NULL);
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -214,7 +214,7 @@ int _xioopen_ipdgram_listen(struct single *sfd,
|
||||||
sockaddr_info(&them->soa, themlen, infobuff, sizeof(infobuff)));
|
sockaddr_info(&them->soa, themlen, infobuff, sizeof(infobuff)));
|
||||||
|
|
||||||
if (dofork) {
|
if (dofork) {
|
||||||
pid = xio_fork(false, E_ERROR, sfd->para.socket.shutup);
|
pid = xio_fork(false, E_ERROR, sfd->shutup);
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
return STAT_RETRYLATER;
|
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 */
|
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;
|
--xfd->retry;
|
||||||
if (xfd->forever || xfd->retry) {
|
if (xfd->forever || xfd->retry) {
|
||||||
dropopts(opts, PH_ALL); opts = copyopts(opts0, GROUP_ALL);
|
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 (*sigchild)(struct single *); /* callback after sigchild */
|
||||||
int escape; /* escape character; -1 for no escape */
|
int escape; /* escape character; -1 for no escape */
|
||||||
bool actescape; /* escape character found in input data */
|
bool actescape; /* escape character found in input data */
|
||||||
|
int shutup; /* children-shutup option */
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
int fdout; /* use fd for output */
|
int fdout; /* use fd for output */
|
||||||
|
@ -224,8 +225,14 @@ typedef struct single {
|
||||||
#if _WITH_IP4 || _WITH_IP6
|
#if _WITH_IP4 || _WITH_IP6
|
||||||
struct para_ip ip;
|
struct para_ip ip;
|
||||||
#endif /* _WITH_IP4 || _WITH_IP6 */
|
#endif /* _WITH_IP4 || _WITH_IP6 */
|
||||||
int shutup;
|
#if HAVE_STRUCT_TPACKET_AUXDATA
|
||||||
/* up to here, keep consistent copy in openssl part !!! */
|
struct {
|
||||||
|
int packet_auxdata;
|
||||||
|
} ancill_flag;
|
||||||
|
#endif
|
||||||
|
#if HAVE_STRUCT_TPACKET_AUXDATA
|
||||||
|
struct tpacket_auxdata ancill_data_packet_auxdata;
|
||||||
|
#endif
|
||||||
#if WITH_UNIX
|
#if WITH_UNIX
|
||||||
struct {
|
struct {
|
||||||
bool tight;
|
bool tight;
|
||||||
|
@ -265,7 +272,6 @@ typedef struct single {
|
||||||
#if _WITH_IP4 || _WITH_IP6
|
#if _WITH_IP4 || _WITH_IP6
|
||||||
struct para_ip ip;
|
struct para_ip ip;
|
||||||
#endif /* _WITH_IP4 || _WITH_IP6 */
|
#endif /* _WITH_IP4 || _WITH_IP6 */
|
||||||
int shutup;
|
|
||||||
/* end of the para.socket structure copy */
|
/* end of the para.socket structure copy */
|
||||||
SSL_CTX* ctx; /* for freeing on close */
|
SSL_CTX* ctx; /* for freeing on close */
|
||||||
SSL *ssl;
|
SSL *ssl;
|
||||||
|
|
14
xioopts.c
14
xioopts.c
|
@ -1397,6 +1397,9 @@ const struct optname optionnames[] = {
|
||||||
IF_PROXY ("resolve", &opt_proxy_resolve)
|
IF_PROXY ("resolve", &opt_proxy_resolve)
|
||||||
#ifdef IP_RETOPTS
|
#ifdef IP_RETOPTS
|
||||||
IF_IP ("retopts", &opt_ip_retopts)
|
IF_IP ("retopts", &opt_ip_retopts)
|
||||||
|
#endif
|
||||||
|
#if WITH_INTERFACE && defined(PACKET_AUXDATA)
|
||||||
|
IF_SOCKET ("retrieve-vlan", &opt_retrieve_vlan)
|
||||||
#endif
|
#endif
|
||||||
IF_RETRY ("retry", &opt_retry)
|
IF_RETRY ("retry", &opt_retry)
|
||||||
IF_SOCKET ("reuseaddr", &opt_so_reuseaddr)
|
IF_SOCKET ("reuseaddr", &opt_so_reuseaddr)
|
||||||
|
@ -3710,6 +3713,17 @@ int applyopts(int fd, struct opt *opts, enum e_phase phase) {
|
||||||
}
|
}
|
||||||
break;
|
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",
|
default: Error1("applyopts(): option \"%s\" not implemented",
|
||||||
opt->desc->defname);
|
opt->desc->defname);
|
||||||
opt->desc = ODESC_ERROR; ++opt; continue;
|
opt->desc = ODESC_ERROR; ++opt; continue;
|
||||||
|
|
|
@ -614,6 +614,7 @@ enum e_optcode {
|
||||||
OPT_RES_RECURSE, /* resolver(3) */
|
OPT_RES_RECURSE, /* resolver(3) */
|
||||||
OPT_RES_STAYOPEN, /* resolver(3) */
|
OPT_RES_STAYOPEN, /* resolver(3) */
|
||||||
OPT_RES_USEVC, /* resolver(3) */
|
OPT_RES_USEVC, /* resolver(3) */
|
||||||
|
OPT_RETRIEVE_VLAN, /* Linux: get VLAN info on raw sockets per auxdata */
|
||||||
OPT_RETRY,
|
OPT_RETRY,
|
||||||
OPT_SANE, /* termios */
|
OPT_SANE, /* termios */
|
||||||
OPT_SCTP_MAXSEG,
|
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) */
|
#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",
|
Notice2("received packet with "F_Zu" bytes from %s",
|
||||||
bytes,
|
bytes,
|
||||||
sockaddr_info(&from.soa, fromlen, infobuff, sizeof(infobuff)));
|
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) ;
|
errno == EINTR) ;
|
||||||
if (rc < 0) return -1;
|
if (rc < 0) return -1;
|
||||||
|
|
||||||
xiodopacketinfo(&msgh, true, false);
|
xiodopacketinfo(pipe, &msgh, true, false);
|
||||||
if (xiocheckpeer(pipe, &from, &pipe->para.socket.la) < 0) {
|
if (xiocheckpeer(pipe, &from, &pipe->para.socket.la) < 0) {
|
||||||
Recvfrom(pipe->fd, buff, bufsiz, 0, &from.soa, &fromlen); /* drop */
|
Recvfrom(pipe->fd, buff, bufsiz, 0, &from.soa, &fromlen); /* drop */
|
||||||
errno = EAGAIN; return -1;
|
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) */
|
#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",
|
Notice2("received packet with "F_Zu" bytes from %s",
|
||||||
bytes,
|
bytes,
|
||||||
sockaddr_info(&from.soa, fromlen, infobuff, sizeof(infobuff)));
|
sockaddr_info(&from.soa, fromlen, infobuff, sizeof(infobuff)));
|
||||||
|
|
Loading…
Reference in a new issue