source: trunk/minix/lib/ip/recvfrom.c@ 21

Last change on this file since 21 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 2.5 KB
RevLine 
[9]1#undef NDEBUG
2
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>
12
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>
17
18#define DEBUG 0
19
20static 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);
23
24ssize_t recvfrom(int socket, void *_RESTRICT buffer, size_t length,
25 int flags, struct sockaddr *_RESTRICT address,
26 socklen_t *_RESTRICT address_len)
27{
28 int r;
29 nwio_udpopt_t udpopt;
30
31 fprintf(stderr, "recvfrom: for fd %d\n", socket);
32
33 r= ioctl(socket, NWIOGUDPOPT, &udpopt);
34 if (r != -1 || (errno != ENOTTY && errno != EBADIOCTL))
35 {
36 if (r == -1)
37 return r;
38 return _udp_recvfrom(socket, buffer, length, flags,
39 address, address_len, &udpopt);
40 }
41
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;
48}
49
50static 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)
53{
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;
60
61 if (flags)
62 {
63#if DEBUG
64 fprintf(stderr, "recvfrom(udp): flags not implemented\n");
65#endif
66 errno= ENOSYS;
67 return -1;
68 }
69
70 if (udpoptp->nwuo_flags & NWUO_RWDATONLY)
71 {
72#if DEBUG
73 fprintf(stderr,
74 "recvfrom(udp): NWUO_RWDATONLY not implemented\n");
75#endif
76 errno= ENOSYS;
77 return -1;
78 }
79
80 buflen= sizeof(*io_hdrp) + length;
81 if (buflen < length)
82 {
83 /* Overflow */
84 errno= EMSGSIZE;
85 return -1;
86 }
87 buf= malloc(buflen);
88 if (buf == NULL)
89 return -1;
90
91 r= read(socket, buf, buflen);
92 if (r == -1)
93 {
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;
103 }
104
105 assert(r >= sizeof(*io_hdrp));
106 length= r-sizeof(*io_hdrp);
107
108 io_hdrp= buf;
109 memcpy(buffer, &io_hdrp[1], length);
110
111 if (address != NULL)
112 {
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);
121 }
122 free(buf);
123 return length;
124}
125
Note: See TracBrowser for help on using the repository browser.