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>
23 #include <net/gen/ip_hdr.h>
24 #include <net/gen/icmp_hdr.h>
28 static ssize_t
_tcp_recvfrom(int sock
, void *__restrict buffer
, size_t length
,
29 int flags
, struct sockaddr
*__restrict address
,
30 socklen_t
*__restrict address_len
, nwio_tcpconf_t
*tcpconfp
);
31 static ssize_t
_udp_recvfrom(int sock
, void *__restrict buffer
, size_t length
,
32 int flags
, struct sockaddr
*__restrict address
,
33 socklen_t
*__restrict address_len
, nwio_udpopt_t
*udpoptp
);
34 static ssize_t
_uds_recvfrom_conn(int sock
, void *__restrict buffer
,
35 size_t length
, int flags
, struct sockaddr
*__restrict address
,
36 socklen_t
*__restrict address_len
, struct sockaddr_un
*uds_addr
);
37 static ssize_t
_uds_recvfrom_dgram(int sock
, void *__restrict buffer
,
38 size_t length
, int flags
, struct sockaddr
*__restrict address
,
39 socklen_t
*__restrict address_len
);
41 ssize_t
recvfrom(int sock
, void *__restrict buffer
, size_t length
,
42 int flags
, struct sockaddr
*__restrict address
,
43 socklen_t
*__restrict address_len
)
46 nwio_tcpconf_t tcpconf
;
48 struct sockaddr_un uds_addr
;
52 fprintf(stderr
, "recvfrom: for fd %d\n", sock
);
55 r
= ioctl(sock
, NWIOGTCPCONF
, &tcpconf
);
56 if (r
!= -1 || errno
!= ENOTTY
)
60 return _tcp_recvfrom(sock
, buffer
, length
, flags
,
61 address
, address_len
, &tcpconf
);
64 r
= ioctl(sock
, NWIOGUDPOPT
, &udpopt
);
65 if (r
!= -1 || errno
!= ENOTTY
)
69 return _udp_recvfrom(sock
, buffer
, length
, flags
,
70 address
, address_len
, &udpopt
);
73 r
= ioctl(sock
, NWIOGUDSSOTYPE
, &uds_sotype
);
74 if (r
!= -1 || errno
!= ENOTTY
)
81 if (uds_sotype
== SOCK_DGRAM
) {
82 return _uds_recvfrom_dgram(sock
, buffer
,
83 length
, flags
, address
, address_len
);
85 return _uds_recvfrom_conn(sock
, buffer
,
86 length
, flags
, address
, address_len
,
95 struct sockaddr_in sin
;
97 rd
= read(sock
, buffer
, length
);
101 assert(rd
>= sizeof(*ip_hdr
));
108 memset(&sin
, 0, sizeof(sin
));
109 sin
.sin_family
= AF_INET
;
110 sin
.sin_addr
.s_addr
= ip_hdr
->ih_src
;
111 sin
.sin_len
= sizeof(sin
);
113 if (len
> sizeof(sin
))
115 memcpy(address
, &sin
, len
);
116 *address_len
= sizeof(sin
);
123 fprintf(stderr
, "recvfrom: not implemented for fd %d\n", sock
);
130 static ssize_t
_tcp_recvfrom(int sock
, void *__restrict buffer
, size_t length
,
131 int flags
, struct sockaddr
*__restrict address
,
132 socklen_t
*__restrict address_len
, nwio_tcpconf_t
*tcpconfp
)
136 struct sockaddr_in sin
;
141 fprintf(stderr
, "recvfrom(tcp): flags not implemented\n");
147 r
= read(sock
, buffer
, length
);
149 if (r
>= 0 && address
!= NULL
)
151 sin
.sin_family
= AF_INET
;
152 sin
.sin_addr
.s_addr
= tcpconfp
->nwtc_remaddr
;
153 sin
.sin_port
= tcpconfp
->nwtc_remport
;
154 sin
.sin_len
= sizeof(sin
);
156 if (len
> sizeof(sin
))
158 memcpy(address
, &sin
, len
);
159 *address_len
= sizeof(sin
);
165 static ssize_t
_udp_recvfrom(int sock
, void *__restrict buffer
, size_t length
,
166 int flags
, struct sockaddr
*__restrict address
,
167 socklen_t
*__restrict address_len
, nwio_udpopt_t
*udpoptp
)
172 udp_io_hdr_t
*io_hdrp
;
173 struct sockaddr_in sin
;
178 fprintf(stderr
, "recvfrom(udp): flags not implemented\n");
184 if (udpoptp
->nwuo_flags
& NWUO_RWDATONLY
)
186 if (address
!= NULL
&&
187 (udpoptp
->nwuo_flags
& (NWUO_RA_SET
| NWUO_RP_SET
)) !=
188 (NWUO_RA_SET
| NWUO_RP_SET
))
193 "recvfrom(udp): RWDATONLY on unconnected socket\n");
199 r
= read(sock
, buffer
, length
);
205 sin
.sin_family
= AF_INET
;
206 sin
.sin_addr
.s_addr
= udpoptp
->nwuo_remaddr
;
207 sin
.sin_port
= udpoptp
->nwuo_remport
;
208 sin
.sin_len
= sizeof(sin
);
210 if (len
> sizeof(sin
))
212 memcpy(address
, &sin
, len
);
213 *address_len
= sizeof(sin
);
219 buflen
= sizeof(*io_hdrp
) + length
;
230 r
= read(sock
, buf
, buflen
);
235 fprintf(stderr
, "recvfrom(udp): read failed: %s\n",
237 fprintf(stderr
, "udp opt flags = 0x%x\n", udpoptp
->nwuo_flags
);
244 assert(r
>= sizeof(*io_hdrp
));
245 length
= r
-sizeof(*io_hdrp
);
248 memcpy(buffer
, &io_hdrp
[1], length
);
252 sin
.sin_family
= AF_INET
;
253 sin
.sin_addr
.s_addr
= io_hdrp
->uih_src_addr
;
254 sin
.sin_port
= io_hdrp
->uih_src_port
;
255 sin
.sin_len
= sizeof(sin
);
257 if (len
> sizeof(sin
))
259 memcpy(address
, &sin
, len
);
260 *address_len
= sizeof(sin
);
266 static ssize_t
_uds_recvfrom_conn(int sock
, void *__restrict buffer
,
267 size_t length
, int flags
, struct sockaddr
*__restrict address
,
268 socklen_t
*__restrict address_len
, struct sockaddr_un
*uds_addr
)
273 /* for connection oriented unix domain sockets (SOCK_STREAM /
280 fprintf(stderr
, "recvfrom(uds): flags not implemented\n");
286 r
= read(sock
, buffer
, length
);
288 if (r
>= 0 && address
!= NULL
)
292 if (len
> sizeof(struct sockaddr_un
))
293 len
= sizeof(struct sockaddr_un
);
294 memcpy(address
, uds_addr
, len
);
295 *address_len
= sizeof(struct sockaddr_un
);
301 static ssize_t
_uds_recvfrom_dgram(int sock
, void *__restrict buffer
,
302 size_t length
, int flags
, struct sockaddr
*__restrict address
,
303 socklen_t
*__restrict address_len
)
308 /* for connectionless unix domain sockets (SOCK_DGRAM) */
313 fprintf(stderr
, "recvfrom(uds): flags not implemented\n");
319 r
= read(sock
, buffer
, length
);
321 if (r
>= 0 && address
!= NULL
)
324 if (len
> sizeof(struct sockaddr_un
))
325 len
= sizeof(struct sockaddr_un
);
326 ioctl(sock
, NWIOGUDSFADDR
, address
);
327 *address_len
= sizeof(struct sockaddr_un
);