tools/llvm: Do not build with symbols
[minix3.git] / minix / net / lwip / raw_ip.c
blobc719653d2dd7b8367b9c0206d0cd62b8a6d16411
1 #include <stdlib.h>
3 #include <sys/ioc_net.h>
4 #include <net/gen/in.h>
5 #include <net/gen/ip_io.h>
7 #include <lwip/raw.h>
8 #include <lwip/ip_addr.h>
10 #include <minix/netsock.h>
11 #include "proto.h"
13 #define RAW_IP_BUF_SIZE (32 << 10)
15 #define sock_alloc_buf(s) debug_malloc(s)
16 #define sock_free_buf(x) debug_free(x)
18 struct raw_ip_recv_data {
19 ip_addr_t ip;
20 struct pbuf * pbuf;
23 #define raw_ip_recv_alloc() debug_malloc(sizeof(struct raw_ip_recv_data))
25 static void raw_ip_recv_free(void * data)
27 if (((struct raw_ip_recv_data *)data)->pbuf)
28 pbuf_free(((struct raw_ip_recv_data *)data)->pbuf);
29 debug_free(data);
33 static int raw_ip_op_open(struct socket * sock)
35 debug_print("socket num %ld", get_sock_num(sock));
37 if (!(sock->buf = sock_alloc_buf(RAW_IP_BUF_SIZE))) {
38 return ENOMEM;
40 sock->buf_size = RAW_IP_BUF_SIZE;
42 return OK;
45 static void raw_ip_close(struct socket * sock)
47 /* deque and free all enqueued data before closing */
48 sock_dequeue_data_all(sock, raw_ip_recv_free);
50 if (sock->pcb)
51 raw_remove(sock->pcb);
52 if (sock->buf)
53 sock_free_buf(sock->buf);
55 /* mark it as unused */
56 sock->ops = NULL;
59 static int raw_ip_op_close(struct socket * sock)
61 debug_print("socket num %ld", get_sock_num(sock));
63 raw_ip_close(sock);
65 return OK;
68 static int raw_ip_do_receive(struct sock_req *req,
69 struct pbuf *pbuf)
71 struct pbuf * p;
72 size_t rem_len = req->size;
73 unsigned int written = 0, hdr_sz = 0;
74 int err;
76 debug_print("user buffer size : %u\n", rem_len);
78 for (p = pbuf; p && rem_len; p = p->next) {
79 size_t cp_len;
81 cp_len = (rem_len < p->len) ? rem_len : p->len;
82 err = copy_to_user(req->endpt, p->payload, cp_len, req->grant,
83 hdr_sz + written);
85 if (err != OK)
86 return err;
88 written += cp_len;
89 rem_len -= cp_len;
92 debug_print("copied %d bytes\n", written + hdr_sz);
93 return written + hdr_sz;
96 static u8_t raw_ip_op_receive(void *arg,
97 __unused struct raw_pcb *pcb,
98 struct pbuf *pbuf,
99 ip_addr_t *addr)
101 struct socket * sock = (struct socket *) arg;
102 struct raw_ip_recv_data * data;
103 int ret;
105 debug_print("socket num : %ld addr : %x\n",
106 get_sock_num(sock), (unsigned int) addr->addr);
108 if (sock->flags & SOCK_FLG_OP_PENDING) {
109 /* we are resuming a suspended operation */
110 ret = raw_ip_do_receive(&sock->req, pbuf);
112 send_req_reply(&sock->req, ret);
113 sock->flags &= ~SOCK_FLG_OP_PENDING;
115 if (ret > 0) {
116 if (sock->usr_flags & NWIO_EXCL) {
117 pbuf_free(pbuf);
118 return 1;
119 } else
120 return 0;
124 /* Do not enqueue more data than allowed */
125 if (sock->recv_data_size > RAW_IP_BUF_SIZE)
126 return 0;
129 * nobody is waiting for the data or an error occured above, we enqueue
130 * the packet
132 if (!(data = raw_ip_recv_alloc())) {
133 return 0;
136 data->ip = *addr;
137 if (sock->usr_flags & NWIO_EXCL) {
138 data->pbuf = pbuf;
139 ret = 1;
140 } else {
141 /* we store a copy of this packet */
142 data->pbuf = pbuf_alloc(PBUF_RAW, pbuf->tot_len, PBUF_RAM);
143 if (data->pbuf == NULL) {
144 debug_print("LWIP : cannot allocated new pbuf\n");
145 raw_ip_recv_free(data);
146 return 0;
149 if (pbuf_copy(data->pbuf, pbuf) != ERR_OK) {
150 debug_print("LWIP : cannot copy pbuf\n");
151 raw_ip_recv_free(data);
152 return 0;
155 ret = 0;
159 * If we didn't managed to enqueue the packet we report it as not
160 * consumed
162 if (sock_enqueue_data(sock, data, data->pbuf->tot_len) != OK) {
163 raw_ip_recv_free(data);
164 ret = 0;
167 return ret;
170 static int raw_ip_op_read(struct socket * sock, struct sock_req * req, int blk)
172 debug_print("socket num %ld", get_sock_num(sock));
174 if (sock->pcb == NULL)
175 return EIO;
177 if (sock->recv_head) {
178 /* data available receive immeditely */
180 struct raw_ip_recv_data * data;
181 int ret;
183 data = (struct raw_ip_recv_data *) sock->recv_head->data;
185 ret = raw_ip_do_receive(req, data->pbuf);
187 if (ret > 0) {
188 sock_dequeue_data(sock);
189 sock->recv_data_size -= data->pbuf->tot_len;
190 raw_ip_recv_free(data);
192 return ret;
193 } else if (!blk)
194 return EAGAIN;
195 else {
196 /* store the request so we know how to reply */
197 sock->req = *req;
198 /* operation is being processes */
199 sock->flags |= SOCK_FLG_OP_PENDING;
201 debug_print("no data to read, suspending");
202 return EDONTREPLY;
206 static int raw_ip_op_write(struct socket * sock, struct sock_req * req,
207 __unused int blk)
209 int ret;
210 struct pbuf * pbuf;
211 struct ip_hdr * ip_hdr;
213 debug_print("socket num %ld data size %u",
214 get_sock_num(sock), req->size);
216 if (sock->pcb == NULL)
217 return EIO;
219 if (req->size > sock->buf_size)
220 return ENOMEM;
222 pbuf = pbuf_alloc(PBUF_LINK, req->size, PBUF_RAM);
223 if (!pbuf)
224 return ENOMEM;
226 if ((ret = copy_from_user(req->endpt, pbuf->payload, req->size,
227 req->grant, 0)) != OK) {
228 pbuf_free(pbuf);
229 return ret;
232 ip_hdr = (struct ip_hdr *) pbuf->payload;
233 if (pbuf_header(pbuf, -IP_HLEN)) {
234 pbuf_free(pbuf);
235 return EIO;
238 if ((ret = raw_sendto((struct raw_pcb *)sock->pcb, pbuf,
239 (ip_addr_t *) &ip_hdr->dest)) != OK) {
240 debug_print("raw_sendto failed %d", ret);
241 ret = EIO;
242 } else
243 ret = req->size;
246 pbuf_free(pbuf);
248 return ret;
251 static int raw_ip_set_opt(struct socket * sock, endpoint_t endpt,
252 cp_grant_id_t grant)
254 int err;
255 nwio_ipopt_t ipopt;
256 struct raw_pcb * pcb;
258 err = copy_from_user(endpt, &ipopt, sizeof(ipopt), grant, 0);
260 if (err != OK)
261 return err;
263 debug_print("ipopt.nwio_flags = 0x%x", ipopt.nwio_flags);
264 debug_print("ipopt.nwio_proto = 0x%x", ipopt.nwio_proto);
265 debug_print("ipopt.nwio_rem = 0x%x",
266 (unsigned int) ipopt.nwio_rem);
268 if (sock->pcb == NULL) {
269 if (!(pcb = raw_new(ipopt.nwio_proto))) {
270 raw_ip_close(sock);
271 return ENOMEM;
274 sock->pcb = pcb;
275 } else
276 pcb = (struct raw_pcb *) sock->pcb;
278 if (pcb->protocol != ipopt.nwio_proto) {
279 debug_print("conflicting ip socket protocols\n");
280 return EINVAL;
283 sock->usr_flags = ipopt.nwio_flags;
285 #if 0
286 if (raw_bind(pcb, (ip_addr_t *)&ipopt.nwio_rem) == ERR_USE) {
287 raw_ip_close(sock);
288 return EADDRINUSE;
290 #endif
292 /* register a receive hook */
293 raw_recv((struct raw_pcb *) sock->pcb, raw_ip_op_receive, sock);
295 return OK;
298 static int raw_ip_get_opt(struct socket * sock, endpoint_t endpt,
299 cp_grant_id_t grant)
301 nwio_ipopt_t ipopt;
302 struct raw_pcb * pcb = (struct raw_pcb *) sock->pcb;
304 assert(pcb);
306 ipopt.nwio_rem = pcb->remote_ip.addr;
307 ipopt.nwio_flags = sock->usr_flags;
309 return copy_to_user(endpt, &ipopt, sizeof(ipopt), grant, 0);
312 static int raw_ip_op_ioctl(struct socket * sock, struct sock_req * req,
313 __unused int blk)
315 int r;
317 debug_print("socket num %ld req %c %ld %ld",
318 get_sock_num(sock),
319 (unsigned char) (req->req >> 8),
320 req->req & 0xff,
321 _MINIX_IOCTL_SIZE(req->req));
323 switch (req->req) {
324 case NWIOSIPOPT:
325 r = raw_ip_set_opt(sock, req->endpt, req->grant);
326 break;
327 case NWIOGIPOPT:
328 r = raw_ip_get_opt(sock, req->endpt, req->grant);
329 break;
330 default:
332 * /dev/ip can be also accessed as a default device to be
333 * configured
335 r = nic_default_ioctl(req);
338 return r;
341 struct sock_ops sock_raw_ip_ops = {
342 .open = raw_ip_op_open,
343 .close = raw_ip_op_close,
344 .read = raw_ip_op_read,
345 .write = raw_ip_op_write,
346 .ioctl = raw_ip_op_ioctl,
347 .select = generic_op_select,
348 .select_reply = generic_op_select_reply