1 /* source: xio-rawip.c */
2 /* Copyright Gerhard Rieger and contributors (see file CHANGES) */
3 /* Published under the GNU General Public License V.2, see file COPYING */
5 /* this file contains the source for opening addresses of raw IP type */
7 #include "xiosysincludes.h"
9 #if (WITH_IP4 || WITH_IP6) && WITH_RAWIP
12 #include "xio-socket.h"
15 #include "xio-tcpwrap.h"
17 #include "xio-rawip.h"
20 static int xioopen_rawip_sendto(int argc
, const char *argv
[], struct opt
*opts
, int xioflags
, xiofile_t
*fd
, const struct addrdesc
*addrdesc
);
21 static int xioopen_rawip_datagram(int argc
, const char *argv
[], struct opt
*opts
, int xioflags
, xiofile_t
*fd
, const struct addrdesc
*addrdesc
);
22 static int xioopen_rawip_recvfrom(int argc
, const char *argv
[], struct opt
*opts
, int xioflags
, xiofile_t
*xfd
, const struct addrdesc
*addrdesc
);
23 static int xioopen_rawip_recv(int argc
, const char *argv
[], struct opt
*opts
, int xioflags
, xiofile_t
*xfd
, const struct addrdesc
*addrdesc
);
26 int _xioopen_rawip_sendto(const char *hostname
, const char *protname
,
27 struct opt
*opts
, int xioflags
,
28 xiofile_t
*xxfd
, groups_t groups
, int *pf
);
30 const struct addrdesc xioaddr_rawip_sendto
= { "IP-SENDTO", 1+XIO_RDWR
, xioopen_rawip_sendto
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_IP4
|GROUP_SOCK_IP6
, PF_UNSPEC
, 0, 0 HELP(":<host>:<protocol>") };
31 const struct addrdesc xioaddr_rawip_datagram
= { "IP-DATAGRAM", 1+XIO_RDWR
, xioopen_rawip_datagram
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_IP4
|GROUP_SOCK_IP6
|GROUP_RANGE
, PF_UNSPEC
, 0, 0 HELP(":<host>:<protocol>") };
32 const struct addrdesc xioaddr_rawip_recvfrom
= { "IP-RECVFROM", 1+XIO_RDWR
, xioopen_rawip_recvfrom
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_IP4
|GROUP_SOCK_IP6
|GROUP_CHILD
|GROUP_RANGE
, PF_UNSPEC
, SOCK_RAW
, 0 HELP(":<protocol>") };
33 const struct addrdesc xioaddr_rawip_recv
= { "IP-RECV", 1+XIO_RDONLY
, xioopen_rawip_recv
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_IP4
|GROUP_SOCK_IP6
|GROUP_RANGE
, PF_UNSPEC
, SOCK_RAW
, 0 HELP(":<protocol>") };
36 const struct addrdesc xioaddr_rawip4_sendto
= { "IP4-SENDTO", 1+XIO_RDWR
, xioopen_rawip_sendto
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_IP4
, PF_INET
, 0, 0 HELP(":<host>:<protocol>") };
37 const struct addrdesc xioaddr_rawip4_datagram
= { "IP4-DATAGRAM", 1+XIO_RDWR
, xioopen_rawip_datagram
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_IP4
|GROUP_RANGE
, PF_INET
, 0, 0 HELP(":<host>:<protocol>") };
38 const struct addrdesc xioaddr_rawip4_recvfrom
= { "IP4-RECVFROM", 1+XIO_RDWR
, xioopen_rawip_recvfrom
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_IP4
|GROUP_CHILD
|GROUP_RANGE
, PF_INET
, SOCK_RAW
, 0 HELP(":<protocol>") };
39 const struct addrdesc xioaddr_rawip4_recv
= { "IP4-RECV", 1+XIO_RDONLY
, xioopen_rawip_recv
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_IP4
|GROUP_RANGE
, PF_INET
, SOCK_RAW
, 0 HELP(":<protocol>") };
43 const struct addrdesc xioaddr_rawip6_sendto
= { "IP6-SENDTO", 1+XIO_RDWR
, xioopen_rawip_sendto
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_IP6
, PF_INET6
, 0, 0 HELP(":<host>:<protocol>") };
44 const struct addrdesc xioaddr_rawip6_datagram
= { "IP6-DATAGRAM", 1+XIO_RDWR
, xioopen_rawip_datagram
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_IP6
|GROUP_RANGE
, PF_INET6
, 0, 0 HELP(":<host>:<protocol>") };
45 const struct addrdesc xioaddr_rawip6_recvfrom
= { "IP6-RECVFROM", 1+XIO_RDWR
, xioopen_rawip_recvfrom
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_IP6
|GROUP_CHILD
|GROUP_RANGE
, PF_INET6
, SOCK_RAW
, 0 HELP(":<protocol>") };
46 const struct addrdesc xioaddr_rawip6_recv
= { "IP6-RECV", 1+XIO_RDONLY
, xioopen_rawip_recv
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_IP6
|GROUP_RANGE
, PF_INET6
, SOCK_RAW
, 0 HELP(":<protocol>") };
50 /* we expect the form: host:protocol */
51 /* struct sockaddr_in sa;*/
53 static int xioopen_rawip_sendto(
59 const struct addrdesc
*addrdesc
)
61 int pf
= addrdesc
->arg1
;
65 xio_syntax(argv
[0], 2, argc
-1, addrdesc
->syntax
);
69 xioinit_ip(&pf
, xioparms
.preferred_ip
);
70 if ((result
= _xioopen_rawip_sendto(argv
[1], argv
[2], opts
, xioflags
, xxfd
,
71 addrdesc
->groups
, &pf
)) != STAT_OK
) {
74 _xio_openlate(&xxfd
->stream
, opts
);
79 applies and consumes the following options:
80 PH_PASTSOCKET, PH_FD, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_CONNECTED, PH_LATE
82 OPT_PROTOCOL_FAMILY, OPT_BIND, OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_USER,
83 OPT_GROUP, OPT_CLOEXEC
86 int _xioopen_rawip_sendto(const char *hostname
, const char *protname
,
87 struct opt
*opts
, int xioflags
, xiofile_t
*xxfd
,
88 groups_t groups
, int *pf
) {
90 xiosingle_t
*sfd
= &xxfd
->stream
;
91 union sockaddr_union us
;
93 int feats
= 1; /* option bind supports only address, not port */
94 int socktype
= SOCK_RAW
;
96 bool needbind
= false;
99 if ((ipproto
= strtoul(protname
, &garbage
, 0)) >= 256) {
100 Error3("xioopen_rawip_sendto(\"%s:%s\",,): protocol number exceeds 255 (%u)",
101 hostname
, protname
, ipproto
);
103 } else if (*garbage
) {
104 Warn2("xioopen_rawip_sendto(\"%s:%s\",,): trailing garbage in protocol specification",
106 /*return STAT_NORETRY;*/
109 if (sfd
->howtoend
== END_UNSPEC
)
110 sfd
->howtoend
= END_SHUTDOWN
;
111 retropt_int(opts
, OPT_PROTOCOL_FAMILY
, pf
);
113 if (applyopts_single(sfd
, opts
, PH_INIT
) < 0) return -1;
114 applyopts(sfd
, -1, opts
, PH_INIT
);
116 sfd
->salen
= sizeof(sfd
->peersa
);
118 xioresolve(hostname
, NULL
, *pf
, socktype
, ipproto
,
119 &sfd
->peersa
, &sfd
->salen
,
120 sfd
->para
.socket
.ip
.ai_flags
))
124 if (*pf
== PF_UNSPEC
) {
125 *pf
= sfd
->peersa
.soa
.sa_family
;
128 uslen
= socket_init(*pf
, &us
);
130 sfd
->dtype
= XIODATA_RECVFROM_SKIPIP
;
132 if (retropt_bind(opts
, *pf
, socktype
, ipproto
, &us
.soa
, &uslen
, feats
,
133 sfd
->para
.socket
.ip
.ai_flags
)
138 _xioopen_dgram_sendto(needbind
?&us
:NULL
, uslen
,
139 opts
, xioflags
, sfd
, groups
, *pf
, socktype
, ipproto
, 0);
143 /* we expect the form: address:protocol */
144 static int xioopen_rawip_datagram(
150 const struct addrdesc
*addrdesc
)
152 xiosingle_t
*sfd
= &xxfd
->stream
;
153 int pf
= addrdesc
->arg1
;
158 xio_syntax(argv
[0], 2, argc
-1, addrdesc
->syntax
);
162 xioinit_ip(&pf
, xioparms
.preferred_ip
);
164 _xioopen_rawip_sendto(argv
[1], argv
[2], opts
, xioflags
, xxfd
,
165 addrdesc
->groups
, &pf
)) != STAT_OK
) {
169 sfd
->dtype
= XIOREAD_RECV
|XIOWRITE_SENDTO
;
171 sfd
->dtype
|= XIOREAD_RECV_SKIPIP
;
174 sfd
->para
.socket
.la
.soa
.sa_family
= sfd
->peersa
.soa
.sa_family
;
176 /* which reply packets will be accepted - determine by range option */
177 if (retropt_string(opts
, OPT_RANGE
, &rangename
) >= 0) {
178 if (xioparserange(rangename
, pf
, &sfd
->para
.socket
.range
,
179 sfd
->para
.socket
.ip
.ai_flags
)
184 sfd
->para
.socket
.dorange
= true;
185 sfd
->dtype
|= XIOREAD_RECV_CHECKRANGE
;
190 xio_retropt_tcpwrap(sfd
, opts
);
191 #endif /* WITH_LIBWRAP */
193 _xio_openlate(sfd
, opts
);
198 static int xioopen_rawip_recvfrom(
204 const struct addrdesc
*addrdesc
)
206 struct single
*sfd
= &xfd
->stream
;
207 const char *protname
= argv
[1];
208 int pf
= addrdesc
->arg1
;
209 int socktype
= addrdesc
->arg2
;
211 union sockaddr_union us
;
212 socklen_t uslen
= sizeof(us
);
214 bool needbind
= false;
218 xio_syntax(argv
[0], 1, argc
-1, addrdesc
->syntax
);
222 xioinit_ip(&pf
, xioparms
.default_ip
);
223 if ((ipproto
= strtoul(protname
, &garbage
, 0)) >= 256) {
224 Error2("xioopen_rawip_recvfrom(\"%s\",,): protocol number exceeds 255 (%u)",
227 } else if (*garbage
) {
228 Warn1("xioopen_rawip_recvfrom(\"%s\",,): trailing garbage in protocol specification",
230 /*return STAT_NORETRY;*/
232 if (sfd
->howtoend
== END_UNSPEC
)
233 sfd
->howtoend
= END_NONE
;
235 retropt_socket_pf(opts
, &pf
);
236 if (pf
== PF_UNSPEC
) {
237 #if WITH_IP4 && WITH_IP6
238 switch (xioparms
.default_ip
) {
239 case '4': pf
= PF_INET
; break;
240 case '6': pf
= PF_INET6
; break;
241 default: break; /* includes \0 */
250 if (retropt_bind(opts
, pf
, socktype
, ipproto
, &us
.soa
, &uslen
, 1,
251 sfd
->para
.socket
.ip
.ai_flags
)
256 sfd
->dtype
= XIODATA_RECVFROM_SKIPIP_ONE
;
258 _xioopen_dgram_recvfrom(sfd
, xioflags
, needbind
?&us
.soa
:NULL
,
259 uslen
, opts
, pf
, socktype
, ipproto
, E_ERROR
))
263 _xio_openlate(sfd
, opts
);
268 static int xioopen_rawip_recv(
274 const struct addrdesc
*addrdesc
)
276 const char *protname
= argv
[1];
277 int pf
= addrdesc
->arg1
;
278 int socktype
= addrdesc
->arg2
;
280 bool needbind
= false;
281 union sockaddr_union us
;
282 socklen_t uslen
= sizeof(us
);
287 xio_syntax(argv
[0], 1, argc
-1, addrdesc
->syntax
);
291 xioinit_ip(&pf
, xioparms
.default_ip
);
292 if ((ipproto
= strtoul(protname
, &garbage
, 0)) >= 256) {
293 Error2("xioopen_rawip_recv(\"%s\",,): protocol number exceeds 255 (%u)",
296 } else if (*garbage
) {
297 Warn1("xioopen_rawip_recv(\"%s\",,): trailing garbage in protocol specification",
299 /*return STAT_NORETRY;*/
302 retropt_socket_pf(opts
, &pf
);
303 if (pf
== PF_UNSPEC
) {
304 #if WITH_IP4 && WITH_IP6
305 pf
= xioparms
.default_ip
=='6'?PF_INET6
:PF_INET
;
313 if (retropt_bind(opts
, pf
, socktype
, ipproto
,
314 &/*us.soa*/xfd
->stream
.para
.socket
.la
.soa
, &uslen
, 1,
315 xfd
->stream
.para
.socket
.ip
.ai_flags
)
319 /* pf is required during xioread checks */
320 xfd
->stream
.para
.socket
.la
.soa
.sa_family
= pf
;
323 xfd
->stream
.dtype
= XIODATA_RECV_SKIPIP
;
325 _xioopen_dgram_recv(&xfd
->stream
, xioflags
,
326 needbind
?&/*us.soa*/xfd
->stream
.para
.socket
.la
.soa
:NULL
,
328 opts
, pf
, socktype
, ipproto
, E_ERROR
);
329 _xio_openlate(&xfd
->stream
, opts
);
333 #endif /* (WITH_IP4 || WITH_IP6) && WITH_RAWIP */