12 #include <sys/ioctl.h>
13 #include <sys/socket.h>
14 #include <netinet/in.h>
16 #include <net/gen/in.h>
17 #include <net/gen/tcp.h>
18 #include <net/gen/tcp_io.h>
19 #include <net/gen/udp.h>
20 #include <net/gen/udp_hdr.h>
21 #include <net/gen/udp_io.h>
25 static ssize_t
_tcp_recvfrom(int sock
, void *__restrict buffer
, size_t length
,
26 int flags
, struct sockaddr
*__restrict address
,
27 socklen_t
*__restrict address_len
, nwio_tcpconf_t
*tcpconfp
);
28 static ssize_t
_udp_recvfrom(int sock
, void *__restrict buffer
, size_t length
,
29 int flags
, struct sockaddr
*__restrict address
,
30 socklen_t
*__restrict address_len
, nwio_udpopt_t
*udpoptp
);
31 static ssize_t
_uds_recvfrom_conn(int sock
, void *__restrict buffer
,
32 size_t length
, int flags
, struct sockaddr
*__restrict address
,
33 socklen_t
*__restrict address_len
, struct sockaddr_un
*uds_addr
);
34 static ssize_t
_uds_recvfrom_dgram(int sock
, void *__restrict buffer
,
35 size_t length
, int flags
, struct sockaddr
*__restrict address
,
36 socklen_t
*__restrict address_len
);
38 ssize_t
recvfrom(int sock
, void *__restrict buffer
, size_t length
,
39 int flags
, struct sockaddr
*__restrict address
,
40 socklen_t
*__restrict address_len
)
43 nwio_tcpconf_t tcpconf
;
45 struct sockaddr_un uds_addr
;
49 fprintf(stderr
, "recvfrom: for fd %d\n", sock
);
52 r
= ioctl(sock
, NWIOGTCPCONF
, &tcpconf
);
53 if (r
!= -1 || (errno
!= ENOTTY
&& errno
!= EBADIOCTL
))
57 return _tcp_recvfrom(sock
, buffer
, length
, flags
,
58 address
, address_len
, &tcpconf
);
61 r
= ioctl(sock
, NWIOGUDPOPT
, &udpopt
);
62 if (r
!= -1 || (errno
!= ENOTTY
&& errno
!= EBADIOCTL
))
66 return _udp_recvfrom(sock
, buffer
, length
, flags
,
67 address
, address_len
, &udpopt
);
70 r
= ioctl(sock
, NWIOGUDSSOTYPE
, &uds_sotype
);
71 if (r
!= -1 || (errno
!= ENOTTY
&& errno
!= EBADIOCTL
))
78 if (uds_sotype
== SOCK_DGRAM
) {
79 return _uds_recvfrom_dgram(sock
, buffer
,
80 length
, flags
, address
, address_len
);
82 return _uds_recvfrom_conn(sock
, buffer
,
83 length
, flags
, address
, address_len
,
89 fprintf(stderr
, "recvfrom: not implemented for fd %d\n", sock
);
96 static ssize_t
_tcp_recvfrom(int sock
, void *__restrict buffer
, size_t length
,
97 int flags
, struct sockaddr
*__restrict address
,
98 socklen_t
*__restrict address_len
, nwio_tcpconf_t
*tcpconfp
)
102 struct sockaddr_in sin
;
107 fprintf(stderr
, "recvfrom(tcp): flags not implemented\n");
113 r
= read(sock
, buffer
, length
);
115 if (r
>= 0 && address
!= NULL
)
117 sin
.sin_family
= AF_INET
;
118 sin
.sin_addr
.s_addr
= tcpconfp
->nwtc_remaddr
;
119 sin
.sin_port
= tcpconfp
->nwtc_remport
;
121 if (len
> sizeof(sin
))
123 memcpy(address
, &sin
, len
);
124 *address_len
= sizeof(sin
);
130 static ssize_t
_udp_recvfrom(int sock
, void *__restrict buffer
, size_t length
,
131 int flags
, struct sockaddr
*__restrict address
,
132 socklen_t
*__restrict address_len
, nwio_udpopt_t
*udpoptp
)
137 udp_io_hdr_t
*io_hdrp
;
138 struct sockaddr_in sin
;
143 fprintf(stderr
, "recvfrom(udp): flags not implemented\n");
149 if (udpoptp
->nwuo_flags
& NWUO_RWDATONLY
)
151 if (address
!= NULL
&&
152 (udpoptp
->nwuo_flags
& (NWUO_RA_SET
| NWUO_RP_SET
)) !=
153 (NWUO_RA_SET
| NWUO_RP_SET
))
158 "recvfrom(udp): RWDATONLY on unconnected socket\n");
164 r
= read(sock
, buffer
, length
);
170 sin
.sin_family
= AF_INET
;
171 sin
.sin_addr
.s_addr
= udpoptp
->nwuo_remaddr
;
172 sin
.sin_port
= udpoptp
->nwuo_remport
;
174 if (len
> sizeof(sin
))
176 memcpy(address
, &sin
, len
);
177 *address_len
= sizeof(sin
);
183 buflen
= sizeof(*io_hdrp
) + length
;
194 r
= read(sock
, buf
, buflen
);
199 fprintf(stderr
, "recvfrom(udp): read failed: %s\n",
201 fprintf(stderr
, "udp opt flags = 0x%x\n", udpoptp
->nwuo_flags
);
208 assert(r
>= sizeof(*io_hdrp
));
209 length
= r
-sizeof(*io_hdrp
);
212 memcpy(buffer
, &io_hdrp
[1], length
);
216 sin
.sin_family
= AF_INET
;
217 sin
.sin_addr
.s_addr
= io_hdrp
->uih_src_addr
;
218 sin
.sin_port
= io_hdrp
->uih_src_port
;
220 if (len
> sizeof(sin
))
222 memcpy(address
, &sin
, len
);
223 *address_len
= sizeof(sin
);
229 static ssize_t
_uds_recvfrom_conn(int sock
, void *__restrict buffer
,
230 size_t length
, int flags
, struct sockaddr
*__restrict address
,
231 socklen_t
*__restrict address_len
, struct sockaddr_un
*uds_addr
)
236 /* for connection oriented unix domain sockets (SOCK_STREAM /
243 fprintf(stderr
, "recvfrom(uds): flags not implemented\n");
249 r
= read(sock
, buffer
, length
);
251 if (r
>= 0 && address
!= NULL
)
255 if (len
> sizeof(struct sockaddr_un
))
256 len
= sizeof(struct sockaddr_un
);
257 memcpy(address
, uds_addr
, len
);
258 *address_len
= sizeof(struct sockaddr_un
);
264 static ssize_t
_uds_recvfrom_dgram(int sock
, void *__restrict buffer
,
265 size_t length
, int flags
, struct sockaddr
*__restrict address
,
266 socklen_t
*__restrict address_len
)
271 /* for connectionless unix domain sockets (SOCK_DGRAM) */
276 fprintf(stderr
, "recvfrom(uds): flags not implemented\n");
282 r
= read(sock
, buffer
, length
);
284 if (r
>= 0 && address
!= NULL
)
287 if (len
> sizeof(struct sockaddr_un
))
288 len
= sizeof(struct sockaddr_un
);
289 ioctl(sock
, NWIOGUDSFADDR
, address
);
290 *address_len
= sizeof(struct sockaddr_un
);