1 /* source: xio-rawip.c */
2 /* Copyright Gerhard Rieger 2001-2008 */
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"
21 int xioopen_rawip_sendto(int argc
, const char *argv
[], struct opt
*opts
,
22 int xioflags
, xiofile_t
*fd
, unsigned groups
, int pf
,
23 int dummy2
, int dummy3
);
25 int xioopen_rawip_datagram(int argc
, const char *argv
[], struct opt
*opts
,
26 int xioflags
, xiofile_t
*fd
, unsigned groups
, int pf
,
27 int dummy2
, int dummy3
);
29 int xioopen_rawip_recvfrom(int argc
, const char *argv
[], struct opt
*opts
,
30 int xioflags
, xiofile_t
*xfd
, unsigned groups
,
31 int pf
, int socktype
, int dummy3
);
33 int xioopen_rawip_recv(int argc
, const char *argv
[], struct opt
*opts
,
34 int xioflags
, xiofile_t
*xfd
, unsigned groups
,
35 int pf
, int socktype
, int ipproto
);
38 int _xioopen_rawip_sendto(const char *hostname
, const char *protname
,
39 struct opt
*opts
, int xioflags
,
40 xiofile_t
*xxfd
, unsigned groups
, int *pf
);
42 const struct addrdesc addr_rawip_sendto
= { "ip-sendto", 3, xioopen_rawip_sendto
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_IP4
|GROUP_SOCK_IP6
, PF_UNSPEC
, 0, 0 HELP(":<host>:<protocol>") };
43 const struct addrdesc addr_rawip_datagram
= { "ip-datagram", 3, xioopen_rawip_datagram
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_IP4
|GROUP_SOCK_IP6
|GROUP_RANGE
, PF_UNSPEC
, 0, 0 HELP(":<host>:<protocol>") };
44 const struct addrdesc addr_rawip_recvfrom
= { "ip-recvfrom", 3, xioopen_rawip_recvfrom
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_IP4
|GROUP_SOCK_IP6
|GROUP_CHILD
|GROUP_RANGE
, PF_UNSPEC
, SOCK_RAW
, 0 HELP(":<protocol>") };
45 const struct addrdesc addr_rawip_recv
= { "ip-recv", 1, xioopen_rawip_recv
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_IP4
|GROUP_SOCK_IP6
|GROUP_RANGE
, PF_UNSPEC
, SOCK_RAW
, 0 HELP(":<protocol>") };
48 const struct addrdesc addr_rawip4_sendto
= { "ip4-sendto", 3, xioopen_rawip_sendto
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_IP4
, PF_INET
, 0, 0 HELP(":<host>:<protocol>") };
49 const struct addrdesc addr_rawip4_datagram
= { "ip4-datagram", 3, xioopen_rawip_datagram
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_IP4
|GROUP_RANGE
, PF_INET
, 0, 0 HELP(":<host>:<protocol>") };
50 const struct addrdesc addr_rawip4_recvfrom
= { "ip4-recvfrom", 3, xioopen_rawip_recvfrom
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_IP4
|GROUP_CHILD
|GROUP_RANGE
, PF_INET
, SOCK_RAW
, 0 HELP(":<protocol>") };
51 const struct addrdesc addr_rawip4_recv
= { "ip4-recv", 1, xioopen_rawip_recv
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_IP4
|GROUP_RANGE
, PF_INET
, SOCK_RAW
, 0 HELP(":<protocol>") };
55 const struct addrdesc addr_rawip6_sendto
= { "ip6-sendto", 3, xioopen_rawip_sendto
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_IP6
, PF_INET6
, 0, 0 HELP(":<host>:<protocol>") };
56 const struct addrdesc addr_rawip6_datagram
= { "ip6-datagram", 3, xioopen_rawip_datagram
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_IP6
|GROUP_RANGE
, PF_INET6
, 0, 0 HELP(":<host>:<protocol>") };
57 const struct addrdesc addr_rawip6_recvfrom
= { "ip6-recvfrom", 3, xioopen_rawip_recvfrom
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_IP6
|GROUP_CHILD
|GROUP_RANGE
, PF_INET6
, SOCK_RAW
, 0 HELP(":<protocol>") };
58 const struct addrdesc addr_rawip6_recv
= { "ip6-recv", 1, xioopen_rawip_recv
, GROUP_FD
|GROUP_SOCKET
|GROUP_SOCK_IP6
|GROUP_RANGE
, PF_INET6
, SOCK_RAW
, 0 HELP(":<protocol>") };
62 /* we expect the form: host:protocol */
63 /* struct sockaddr_in sa;*/
66 int xioopen_rawip_sendto(int argc
, const char *argv
[], struct opt
*opts
,
67 int xioflags
, xiofile_t
*xxfd
, unsigned groups
,
68 int pf
, int dummy2
, int dummy3
) {
72 Error2("%s: wrong number of parameters (%d instead of 2)",
76 if ((result
= _xioopen_rawip_sendto(argv
[1], argv
[2], opts
, xioflags
, xxfd
,
77 groups
, &pf
)) != STAT_OK
) {
80 _xio_openlate(&xxfd
->stream
, opts
);
85 applies and consumes the following options:
86 PH_PASTSOCKET, PH_FD, PH_PREBIND, PH_BIND, PH_PASTBIND, PH_CONNECTED, PH_LATE
88 OPT_PROTOCOL_FAMILY, OPT_BIND, OPT_SO_TYPE, OPT_SO_PROTOTYPE, OPT_USER,
89 OPT_GROUP, OPT_CLOEXEC
92 int _xioopen_rawip_sendto(const char *hostname
, const char *protname
,
93 struct opt
*opts
, int xioflags
, xiofile_t
*xxfd
,
94 unsigned groups
, int *pf
) {
96 xiosingle_t
*xfd
= &xxfd
->stream
;
97 union sockaddr_union us
;
99 int feats
= 1; /* option bind supports only address, not port */
100 int socktype
= SOCK_RAW
;
102 bool needbind
= false;
105 if ((ipproto
= strtoul(protname
, &garbage
, 0)) >= 256) {
106 Error3("xioopen_rawip_sendto(\"%s:%s\",,): protocol number exceeds 255 (%u)",
107 hostname
, protname
, ipproto
);
109 } else if (*garbage
) {
110 Warn2("xioopen_rawip_sendto(\"%s:%s\",,): trailing garbage in protocol specification",
112 /*return STAT_NORETRY;*/
115 xfd
->howtoend
= END_SHUTDOWN
;
116 retropt_int(opts
, OPT_PROTOCOL_FAMILY
, pf
);
119 if (applyopts_single(xfd
, opts
, PH_INIT
) < 0) return -1;
120 applyopts(-1, opts
, PH_INIT
);
122 xfd
->salen
= sizeof(xfd
->peersa
);
124 xiogetaddrinfo(hostname
, NULL
, *pf
, socktype
, ipproto
,
125 &xfd
->peersa
, &xfd
->salen
,
126 xfd
->para
.socket
.ip
.res_opts
[0],
127 xfd
->para
.socket
.ip
.res_opts
[1]))
131 if (*pf
== PF_UNSPEC
) {
132 *pf
= xfd
->peersa
.soa
.sa_family
;
135 uslen
= socket_init(*pf
, &us
);
137 xfd
->dtype
= XIODATA_RECVFROM_SKIPIP
;
139 if (retropt_bind(opts
, *pf
, socktype
, ipproto
, &us
.soa
, &uslen
, feats
,
140 xfd
->para
.socket
.ip
.res_opts
[0],
141 xfd
->para
.socket
.ip
.res_opts
[1]) != STAT_NOACTION
) {
145 _xioopen_dgram_sendto(needbind
?&us
:NULL
, uslen
,
146 opts
, xioflags
, xfd
, groups
, *pf
, socktype
, ipproto
);
150 /* we expect the form: address:protocol */
152 int xioopen_rawip_datagram(int argc
, const char *argv
[], struct opt
*opts
,
153 int xioflags
, xiofile_t
*xxfd
, unsigned groups
,
154 int pf
, int dummy2
, int dummy3
) {
155 xiosingle_t
*xfd
= &xxfd
->stream
;
160 Error2("%s: wrong number of parameters (%d instead of 2)",
165 _xioopen_rawip_sendto(argv
[1], argv
[2], opts
, xioflags
, xxfd
,
166 groups
, &pf
)) != STAT_OK
) {
170 xfd
->dtype
= XIOREAD_RECV
|XIOWRITE_SENDTO
;
172 xfd
->dtype
|= XIOREAD_RECV_SKIPIP
;
175 xfd
->para
.socket
.la
.soa
.sa_family
= xfd
->peersa
.soa
.sa_family
;
177 /* which reply packets will be accepted - determine by range option */
178 if (retropt_string(opts
, OPT_RANGE
, &rangename
) >= 0) {
179 if (xioparserange(rangename
, pf
, &xfd
->para
.socket
.range
) < 0) {
183 xfd
->para
.socket
.dorange
= true;
184 xfd
->dtype
|= XIOREAD_RECV_CHECKRANGE
;
189 xio_retropt_tcpwrap(xfd
, opts
);
190 #endif /* WITH_LIBWRAP */
192 _xio_openlate(xfd
, opts
);
198 int xioopen_rawip_recvfrom(int argc
, const char *argv
[], struct opt
*opts
,
199 int xioflags
, xiofile_t
*xfd
, unsigned groups
,
200 int pf
, int socktype
, int dummy3
) {
201 const char *protname
= argv
[1];
203 union sockaddr_union us
;
204 socklen_t uslen
= sizeof(us
);
206 bool needbind
= false;
210 Error2("%s: wrong number of parameters (%d instead of 1)",
215 if ((ipproto
= strtoul(protname
, &garbage
, 0)) >= 256) {
216 Error2("xioopen_rawip_recvfrom(\"%s\",,): protocol number exceeds 255 (%u)",
219 } else if (*garbage
) {
220 Warn1("xioopen_rawip_recvfrom(\"%s\",,): trailing garbage in protocol specification",
222 /*return STAT_NORETRY;*/
224 xfd
->stream
.howtoend
= END_NONE
;
226 retropt_socket_pf(opts
, &pf
);
227 if (pf
== PF_UNSPEC
) {
228 #if WITH_IP4 && WITH_IP6
229 pf
= xioopts
.default_ip
=='6'?PF_INET6
:PF_INET
;
237 if (retropt_bind(opts
, pf
, socktype
, ipproto
, &us
.soa
, &uslen
, 1,
238 xfd
->stream
.para
.socket
.ip
.res_opts
[0],
239 xfd
->stream
.para
.socket
.ip
.res_opts
[1]) != STAT_NOACTION
) {
243 xfd
->stream
.dtype
= XIODATA_RECVFROM_SKIPIP_ONE
;
245 _xioopen_dgram_recvfrom(&xfd
->stream
, xioflags
, needbind
?&us
.soa
:NULL
,
246 uslen
, opts
, pf
, socktype
, ipproto
, E_ERROR
))
250 _xio_openlate(&xfd
->stream
, opts
);
256 int xioopen_rawip_recv(int argc
, const char *argv
[], struct opt
*opts
,
257 int xioflags
, xiofile_t
*xfd
, unsigned groups
,
258 int pf
, int socktype
, int dummy3
) {
259 const char *protname
= argv
[1];
261 bool needbind
= false;
262 union sockaddr_union us
;
263 socklen_t uslen
= sizeof(us
);
268 Error2("%s: wrong number of parameters (%d instead of 1)",
273 if ((ipproto
= strtoul(protname
, &garbage
, 0)) >= 256) {
274 Error2("xioopen_rawip_recv(\"%s\",,): protocol number exceeds 255 (%u)",
277 } else if (*garbage
) {
278 Warn1("xioopen_rawip_recv(\"%s\",,): trailing garbage in protocol specification",
280 /*return STAT_NORETRY;*/
283 retropt_socket_pf(opts
, &pf
);
284 if (pf
== PF_UNSPEC
) {
285 #if WITH_IP4 && WITH_IP6
286 pf
= xioopts
.default_ip
=='6'?PF_INET6
:PF_INET
;
294 if (retropt_bind(opts
, pf
, socktype
, ipproto
,
295 &/*us.soa*/xfd
->stream
.para
.socket
.la
.soa
, &uslen
, 1,
296 xfd
->stream
.para
.socket
.ip
.res_opts
[0],
297 xfd
->stream
.para
.socket
.ip
.res_opts
[1]) ==
301 /* pf is required during xioread checks */
302 xfd
->stream
.para
.socket
.la
.soa
.sa_family
= pf
;
305 xfd
->stream
.dtype
= XIODATA_RECV_SKIPIP
;
307 _xioopen_dgram_recv(&xfd
->stream
, xioflags
,
308 needbind
?&/*us.soa*/xfd
->stream
.para
.socket
.la
.soa
:NULL
,
310 opts
, pf
, socktype
, ipproto
, E_ERROR
);
311 _xio_openlate(&xfd
->stream
, opts
);
315 #endif /* (WITH_IP4 || WITH_IP6) && WITH_RAWIP */