version 1.7.3.0
[socat.git] / xio-interface.c
blobd6e7f69f82fd3dcfc6ee7716c5d7164b95763f97
1 /* source: xio-interface.c */
2 /* Copyright Gerhard Rieger 2010 */
3 /* Published under the GNU General Public License V.2, see file COPYING */
5 /* this file contains the source for opening addresses of raw socket type */
7 #include "xiosysincludes.h"
9 #if WITH_INTERFACE
11 #include "xioopen.h"
12 #include "xio-socket.h"
14 #include "xio-interface.h"
17 static
18 int xioopen_interface(int argc, const char *argv[], struct opt *opts,
19 int xioflags, xiofile_t *xfd, unsigned groups, int pf,
20 int dummy2, int dummy3);
22 const struct addrdesc xioaddr_interface= { "interface", 3, xioopen_interface, GROUP_FD|GROUP_SOCKET, PF_PACKET, 0, 0 HELP(":<interface>") };
25 static
26 int _xioopen_interface(const char *ifname,
27 struct opt *opts, int xioflags, xiofile_t *xxfd,
28 unsigned groups, int pf) {
29 xiosingle_t *xfd = &xxfd->stream;
30 union sockaddr_union us = {{0}};
31 socklen_t uslen;
32 int socktype = SOCK_RAW;
33 unsigned int ifidx;
34 bool needbind = false;
35 char *bindstring = NULL;
36 struct sockaddr_ll sall = { 0 };
38 if (ifindex(ifname, &ifidx, -1) < 0) {
39 Error1("unknown interface \"%s\"", ifname);
40 ifidx = 0; /* desparate attempt to continue */
43 xfd->howtoend = END_SHUTDOWN;
44 retropt_int(opts, OPT_SO_TYPE, &socktype);
46 retropt_socket_pf(opts, &pf);
48 /* ...res_opts[] */
49 if (applyopts_single(xfd, opts, PH_INIT) < 0) return -1;
50 applyopts(-1, opts, PH_INIT);
52 xfd->salen = sizeof(xfd->peersa);
53 if (pf == PF_UNSPEC) {
54 pf = xfd->peersa.soa.sa_family;
57 xfd->dtype = XIODATA_RECVFROM_SKIPIP;
59 if (retropt_string(opts, OPT_BIND, &bindstring)) {
60 needbind = true;
62 /*!!! parse by ':' */
63 us.ll.sll_family = pf;
64 us.ll.sll_protocol = htons(ETH_P_ALL);
65 us.ll.sll_ifindex = ifidx;
66 uslen = sizeof(sall);
67 needbind = true;
68 xfd->peersa = (union sockaddr_union)us;
70 return
71 _xioopen_dgram_sendto(needbind?&us:NULL, uslen,
72 opts, xioflags, xfd, groups, pf, socktype, 0);
75 static
76 int xioopen_interface(int argc, const char *argv[], struct opt *opts,
77 int xioflags, xiofile_t *xxfd, unsigned groups,
78 int pf, int dummy2, int dummy3) {
79 xiosingle_t *xfd = &xxfd->stream;
80 int result;
82 if (argc != 2) {
83 Error2("%s: wrong number of parameters (%d instead of 1)",
84 argv[0], argc-1);
85 return STAT_NORETRY;
88 if ((result =
89 _xioopen_interface(argv[1], opts, xioflags, xxfd, groups, pf))
90 != STAT_OK) {
91 return result;
94 xfd->dtype = XIOREAD_RECV|XIOWRITE_SENDTO;
95 if (pf == PF_INET) {
96 xfd->dtype |= XIOREAD_RECV_SKIPIP;
99 xfd->para.socket.la.soa.sa_family = xfd->peersa.soa.sa_family;
101 _xio_openlate(xfd, opts);
102 return STAT_OK;
105 #endif /* WITH_INTERFACE */