. service tells you which device it couldn't stat
[minix3.git] / lib / ip / recvfrom.c
blob7f54de7ed72867f0fcb68285a43903cfa6d69a43
1 #undef NDEBUG
3 #include <assert.h>
4 #include <errno.h>
5 #include <stdlib.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <unistd.h>
9 #include <sys/ioctl.h>
10 #include <sys/socket.h>
11 #include <netinet/in.h>
13 #include <net/gen/in.h>
14 #include <net/gen/udp.h>
15 #include <net/gen/udp_hdr.h>
16 #include <net/gen/udp_io.h>
18 #define DEBUG 0
20 static ssize_t _udp_recvfrom(int socket, void *_RESTRICT buffer, size_t length,
21 int flags, struct sockaddr *_RESTRICT address,
22 socklen_t *_RESTRICT address_len, nwio_udpopt_t *udpoptp);
24 ssize_t recvfrom(int socket, void *_RESTRICT buffer, size_t length,
25 int flags, struct sockaddr *_RESTRICT address,
26 socklen_t *_RESTRICT address_len)
28 int r;
29 nwio_udpopt_t udpopt;
31 fprintf(stderr, "recvfrom: for fd %d\n", socket);
33 r= ioctl(socket, NWIOGUDPOPT, &udpopt);
34 if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
36 if (r == -1)
37 return r;
38 return _udp_recvfrom(socket, buffer, length, flags,
39 address, address_len, &udpopt);
42 #if DEBUG
43 fprintf(stderr, "recvfrom: not implemented for fd %d\n", socket);
44 #endif
45 errno= ENOSYS;
46 assert(0);
47 return -1;
50 static ssize_t _udp_recvfrom(int socket, void *_RESTRICT buffer, size_t length,
51 int flags, struct sockaddr *_RESTRICT address,
52 socklen_t *_RESTRICT address_len, nwio_udpopt_t *udpoptp)
54 int r, t_errno;
55 size_t buflen, len;
56 void *buf;
57 struct sockaddr_in *sinp;
58 udp_io_hdr_t *io_hdrp;
59 struct sockaddr_in sin;
61 if (flags)
63 #if DEBUG
64 fprintf(stderr, "recvfrom(udp): flags not implemented\n");
65 #endif
66 errno= ENOSYS;
67 return -1;
70 if (udpoptp->nwuo_flags & NWUO_RWDATONLY)
72 #if DEBUG
73 fprintf(stderr,
74 "recvfrom(udp): NWUO_RWDATONLY not implemented\n");
75 #endif
76 errno= ENOSYS;
77 return -1;
80 buflen= sizeof(*io_hdrp) + length;
81 if (buflen < length)
83 /* Overflow */
84 errno= EMSGSIZE;
85 return -1;
87 buf= malloc(buflen);
88 if (buf == NULL)
89 return -1;
91 r= read(socket, buf, buflen);
92 if (r == -1)
94 t_errno= errno;
95 #if DEBUG
96 fprintf(stderr, "recvfrom(udp): read failed: %s\n",
97 strerror(errno));
98 fprintf(stderr, "udp opt flags = 0x%x\n", udpoptp->nwuo_flags);
99 #endif
100 free(buf);
101 errno= t_errno;
102 return -1;
105 assert(r >= sizeof(*io_hdrp));
106 length= r-sizeof(*io_hdrp);
108 io_hdrp= buf;
109 memcpy(buffer, &io_hdrp[1], length);
111 if (address != NULL)
113 sin.sin_family= AF_INET;
114 sin.sin_addr.s_addr= io_hdrp->uih_src_addr;
115 sin.sin_port= io_hdrp->uih_src_port;
116 len= *address_len;
117 if (len > sizeof(sin))
118 len= sizeof(sin);
119 memcpy(address, &sin, len);
120 *address_len= sizeof(sin);
122 free(buf);
123 return length;