iso9660fs: initialize buffer cache
[minix.git] / servers / inet / generic / udp.c
blob9a4021845d3aa112211714171fdd1fd30eae06e7
1 /*
2 udp.c
4 Copyright 1995 Philip Homburg
5 */
7 #include "inet.h"
8 #include "type.h"
10 #include "assert.h"
11 #include "buf.h"
12 #include "clock.h"
13 #include "icmp_lib.h"
14 #include "io.h"
15 #include "ip.h"
16 #include "sr.h"
17 #include "udp.h"
18 #include "udp_int.h"
20 THIS_FILE
22 static void read_ip_packets ARGS(( udp_port_t *udp_port ));
23 static void udp_buffree ARGS(( int priority ));
24 #ifdef BUF_CONSISTENCY_CHECK
25 static void udp_bufcheck ARGS(( void ));
26 #endif
27 static void udp_main ARGS(( udp_port_t *udp_port ));
28 static int udp_select ARGS(( int fd, unsigned operations ));
29 static acc_t *udp_get_data ARGS(( int fd, size_t offset, size_t count,
30 int for_ioctl ));
31 static int udp_put_data ARGS(( int fd, size_t offset, acc_t *data,
32 int for_ioctl ));
33 static int udp_peek ARGS(( udp_fd_t * ));
34 static int udp_sel_read ARGS(( udp_fd_t * ));
35 static void udp_restart_write_port ARGS(( udp_port_t *udp_port ));
36 static void udp_ip_arrived ARGS(( int port, acc_t *pack, size_t pack_size ));
37 static void reply_thr_put ARGS(( udp_fd_t *udp_fd, int reply,
38 int for_ioctl ));
39 static void reply_thr_get ARGS(( udp_fd_t *udp_fd, int reply,
40 int for_ioctl ));
41 static int udp_setopt ARGS(( udp_fd_t *udp_fd ));
42 static udpport_t find_unused_port ARGS(( int fd ));
43 static int is_unused_port ARGS(( udpport_t port ));
44 static int udp_packet2user ARGS(( udp_fd_t *udp_fd ));
45 static void restart_write_fd ARGS(( udp_fd_t *udp_fd ));
46 static u16_t pack_oneCsum ARGS(( acc_t *pack ));
47 static void udp_rd_enqueue ARGS(( udp_fd_t *udp_fd, acc_t *pack,
48 clock_t exp_tim ));
49 static void hash_fd ARGS(( udp_fd_t *udp_fd ));
50 static void unhash_fd ARGS(( udp_fd_t *udp_fd ));
52 udp_port_t *udp_port_table;
53 udp_fd_t udp_fd_table[UDP_FD_NR];
55 void udp_prep()
57 udp_port_table= alloc(udp_conf_nr * sizeof(udp_port_table[0]));
60 void udp_init()
62 udp_fd_t *udp_fd;
63 udp_port_t *udp_port;
64 int i, j, ifno;
66 assert (BUF_S >= sizeof(struct nwio_ipopt));
67 assert (BUF_S >= sizeof(struct nwio_ipconf));
68 assert (BUF_S >= sizeof(struct nwio_udpopt));
69 assert (BUF_S >= sizeof(struct udp_io_hdr));
70 assert (UDP_HDR_SIZE == sizeof(udp_hdr_t));
71 assert (UDP_IO_HDR_SIZE == sizeof(udp_io_hdr_t));
73 for (i= 0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++, udp_fd++)
75 udp_fd->uf_flags= UFF_EMPTY;
76 udp_fd->uf_rdbuf_head= NULL;
79 #ifndef BUF_CONSISTENCY_CHECK
80 bf_logon(udp_buffree);
81 #else
82 bf_logon(udp_buffree, udp_bufcheck);
83 #endif
85 for (i= 0, udp_port= udp_port_table; i<udp_conf_nr; i++, udp_port++)
87 udp_port->up_ipdev= udp_conf[i].uc_port;
89 udp_port->up_flags= UPF_EMPTY;
90 udp_port->up_state= UPS_EMPTY;
91 udp_port->up_next_fd= udp_fd_table;
92 udp_port->up_write_fd= NULL;
93 udp_port->up_wr_pack= NULL;
94 udp_port->up_port_any= NULL;
95 for (j= 0; j<UDP_PORT_HASH_NR; j++)
96 udp_port->up_port_hash[j]= NULL;
98 ifno= ip_conf[udp_port->up_ipdev].ic_ifno;
99 sr_add_minor(if2minor(ifno, UDP_DEV_OFF),
100 i, udp_open, udp_close, udp_read,
101 udp_write, udp_ioctl, udp_cancel, udp_select);
103 udp_main(udp_port);
107 int udp_open (port, srfd, get_userdata, put_userdata, put_pkt,
108 select_res)
109 int port;
110 int srfd;
111 get_userdata_t get_userdata;
112 put_userdata_t put_userdata;
113 put_pkt_t put_pkt;
114 select_res_t select_res;
116 int i;
117 udp_fd_t *udp_fd;
119 for (i= 0; i<UDP_FD_NR && (udp_fd_table[i].uf_flags & UFF_INUSE);
120 i++);
122 if (i>= UDP_FD_NR)
124 DBLOCK(1, printf("out of fds\n"));
125 return EAGAIN;
128 udp_fd= &udp_fd_table[i];
130 udp_fd->uf_flags= UFF_INUSE;
131 udp_fd->uf_port= &udp_port_table[port];
132 udp_fd->uf_srfd= srfd;
133 udp_fd->uf_udpopt.nwuo_flags= UDP_DEF_OPT;
134 udp_fd->uf_get_userdata= get_userdata;
135 udp_fd->uf_put_userdata= put_userdata;
136 udp_fd->uf_select_res= select_res;
137 assert(udp_fd->uf_rdbuf_head == NULL);
138 udp_fd->uf_port_next= NULL;
140 return i;
144 int udp_ioctl (fd, req)
145 int fd;
146 ioreq_t req;
148 udp_fd_t *udp_fd;
149 udp_port_t *udp_port;
150 nwio_udpopt_t *udp_opt;
151 acc_t *opt_acc;
152 int result;
154 udp_fd= &udp_fd_table[fd];
156 assert (udp_fd->uf_flags & UFF_INUSE);
158 udp_port= udp_fd->uf_port;
159 udp_fd->uf_flags |= UFF_IOCTL_IP;
160 udp_fd->uf_ioreq= req;
162 if (udp_port->up_state != UPS_MAIN)
163 return NW_SUSPEND;
165 switch(req)
167 case NWIOSUDPOPT:
168 result= udp_setopt(udp_fd);
169 break;
170 case NWIOGUDPOPT:
171 opt_acc= bf_memreq(sizeof(*udp_opt));
172 assert (opt_acc->acc_length == sizeof(*udp_opt));
173 udp_opt= (nwio_udpopt_t *)ptr2acc_data(opt_acc);
175 *udp_opt= udp_fd->uf_udpopt;
176 udp_opt->nwuo_locaddr= udp_fd->uf_port->up_ipaddr;
177 result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd, 0, opt_acc,
178 TRUE);
179 if (result == NW_OK)
180 reply_thr_put(udp_fd, NW_OK, TRUE);
181 break;
182 case NWIOUDPPEEK:
183 result= udp_peek(udp_fd);
184 break;
185 default:
186 reply_thr_get(udp_fd, EBADIOCTL, TRUE);
187 result= NW_OK;
188 break;
190 if (result != NW_SUSPEND)
191 udp_fd->uf_flags &= ~UFF_IOCTL_IP;
192 return result;
195 int udp_read (fd, count)
196 int fd;
197 size_t count;
199 udp_fd_t *udp_fd;
200 acc_t *tmp_acc, *next_acc;
202 udp_fd= &udp_fd_table[fd];
203 if (!(udp_fd->uf_flags & UFF_OPTSET))
205 reply_thr_put(udp_fd, EBADMODE, FALSE);
206 return NW_OK;
209 udp_fd->uf_rd_count= count;
211 if (udp_fd->uf_rdbuf_head)
213 if (get_time() <= udp_fd->uf_exp_tim)
214 return udp_packet2user (udp_fd);
215 tmp_acc= udp_fd->uf_rdbuf_head;
216 while (tmp_acc)
218 next_acc= tmp_acc->acc_ext_link;
219 bf_afree(tmp_acc);
220 tmp_acc= next_acc;
222 udp_fd->uf_rdbuf_head= NULL;
224 udp_fd->uf_flags |= UFF_READ_IP;
225 return NW_SUSPEND;
228 static void udp_main(udp_port)
229 udp_port_t *udp_port;
231 udp_fd_t *udp_fd;
232 int result, i;
234 switch (udp_port->up_state)
236 case UPS_EMPTY:
237 udp_port->up_state= UPS_SETPROTO;
239 udp_port->up_ipfd= ip_open(udp_port->up_ipdev,
240 udp_port->up_ipdev, udp_get_data, udp_put_data,
241 udp_ip_arrived, 0 /* no select_res */);
242 if (udp_port->up_ipfd < 0)
244 udp_port->up_state= UPS_ERROR;
245 DBLOCK(1, printf("%s, %d: unable to open ip port\n",
246 __FILE__, __LINE__));
247 return;
250 result= ip_ioctl(udp_port->up_ipfd, NWIOSIPOPT);
251 if (result == NW_SUSPEND)
252 udp_port->up_flags |= UPF_SUSPEND;
253 if (result<0)
255 return;
257 if (udp_port->up_state != UPS_GETCONF)
258 return;
259 /* drops through */
260 case UPS_GETCONF:
261 udp_port->up_flags &= ~UPF_SUSPEND;
263 result= ip_ioctl(udp_port->up_ipfd, NWIOGIPCONF);
264 if (result == NW_SUSPEND)
265 udp_port->up_flags |= UPF_SUSPEND;
266 if (result<0)
268 return;
270 if (udp_port->up_state != UPS_MAIN)
271 return;
272 /* drops through */
273 case UPS_MAIN:
274 udp_port->up_flags &= ~UPF_SUSPEND;
276 for (i= 0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++, udp_fd++)
278 if (!(udp_fd->uf_flags & UFF_INUSE))
279 continue;
280 if (udp_fd->uf_port != udp_port)
281 continue;
282 if (udp_fd->uf_flags & UFF_IOCTL_IP)
283 udp_ioctl(i, udp_fd->uf_ioreq);
285 read_ip_packets(udp_port);
286 return;
287 default:
288 DBLOCK(1, printf("udp_port_table[%d].up_state= %d\n",
289 udp_port->up_ipdev, udp_port->up_state));
290 ip_panic(( "unknown state" ));
291 break;
295 static int udp_select(fd, operations)
296 int fd;
297 unsigned operations;
299 unsigned resops;
300 udp_fd_t *udp_fd;
302 udp_fd= &udp_fd_table[fd];
303 assert (udp_fd->uf_flags & UFF_INUSE);
305 resops= 0;
307 if (operations & SR_SELECT_READ)
309 if (udp_sel_read(udp_fd))
310 resops |= SR_SELECT_READ;
311 else if (!(operations & SR_SELECT_POLL))
312 udp_fd->uf_flags |= UFF_SEL_READ;
314 if (operations & SR_SELECT_WRITE)
316 /* Should handle special case when the interface is down */
317 resops |= SR_SELECT_WRITE;
319 if (operations & SR_SELECT_EXCEPTION)
321 printf("udp_select: not implemented for exceptions\n");
323 return resops;
326 static acc_t *udp_get_data (port, offset, count, for_ioctl)
327 int port;
328 size_t offset;
329 size_t count;
330 int for_ioctl;
332 udp_port_t *udp_port;
333 udp_fd_t *udp_fd;
334 int result;
336 udp_port= &udp_port_table[port];
338 switch(udp_port->up_state)
340 case UPS_SETPROTO:
341 assert (for_ioctl);
342 if (!count)
344 result= (int)offset;
345 if (result<0)
347 udp_port->up_state= UPS_ERROR;
348 break;
350 udp_port->up_state= UPS_GETCONF;
351 if (udp_port->up_flags & UPF_SUSPEND)
352 udp_main(udp_port);
353 return NULL;
355 else
357 struct nwio_ipopt *ipopt;
358 acc_t *acc;
360 assert (!offset);
361 assert (count == sizeof(*ipopt));
363 acc= bf_memreq(sizeof(*ipopt));
364 ipopt= (struct nwio_ipopt *)ptr2acc_data(acc);
365 ipopt->nwio_flags= NWIO_COPY | NWIO_EN_LOC |
366 NWIO_EN_BROAD | NWIO_REMANY | NWIO_PROTOSPEC |
367 NWIO_HDR_O_ANY | NWIO_RWDATALL;
368 ipopt->nwio_proto= IPPROTO_UDP;
369 return acc;
371 case UPS_MAIN:
372 assert (!for_ioctl);
373 assert (udp_port->up_flags & UPF_WRITE_IP);
374 if (!count)
376 result= (int)offset;
377 assert (udp_port->up_wr_pack);
378 bf_afree(udp_port->up_wr_pack);
379 udp_port->up_wr_pack= 0;
380 if (udp_port->up_flags & UPF_WRITE_SP)
382 if (udp_port->up_write_fd)
384 udp_fd= udp_port->up_write_fd;
385 udp_port->up_write_fd= NULL;
386 udp_fd->uf_flags &= ~UFF_WRITE_IP;
387 reply_thr_get(udp_fd, result, FALSE);
389 udp_port->up_flags &= ~(UPF_WRITE_SP |
390 UPF_WRITE_IP);
391 if (udp_port->up_flags & UPF_MORE2WRITE)
393 udp_restart_write_port(udp_port);
396 else
397 udp_port->up_flags &= ~UPF_WRITE_IP;
399 else
401 return bf_cut (udp_port->up_wr_pack, offset, count);
403 break;
404 default:
405 printf("udp_get_data(%d, 0x%x, 0x%x) called but up_state= 0x%x\n",
406 port, offset, count, udp_port->up_state);
407 break;
409 return NULL;
412 static int udp_put_data (fd, offset, data, for_ioctl)
413 int fd;
414 size_t offset;
415 acc_t *data;
416 int for_ioctl;
418 udp_port_t *udp_port;
419 int result;
421 udp_port= &udp_port_table[fd];
423 switch (udp_port->up_state)
425 case UPS_GETCONF:
426 if (!data)
428 result= (int)offset;
429 if (result<0)
431 udp_port->up_state= UPS_ERROR;
432 return NW_OK;
434 udp_port->up_state= UPS_MAIN;
435 if (udp_port->up_flags & UPF_SUSPEND)
436 udp_main(udp_port);
438 else
440 struct nwio_ipconf *ipconf;
442 data= bf_packIffLess(data, sizeof(*ipconf));
443 ipconf= (struct nwio_ipconf *)ptr2acc_data(data);
444 assert (ipconf->nwic_flags & NWIC_IPADDR_SET);
445 udp_port->up_ipaddr= ipconf->nwic_ipaddr;
446 bf_afree(data);
448 break;
449 case UPS_MAIN:
450 assert(0);
452 assert (udp_port->up_flags & UPF_READ_IP);
453 if (!data)
455 result= (int)offset;
456 compare (result, >=, 0);
457 if (udp_port->up_flags & UPF_READ_SP)
459 udp_port->up_flags &= ~(UPF_READ_SP|
460 UPF_READ_IP);
461 read_ip_packets(udp_port);
463 else
464 udp_port->up_flags &= ~UPF_READ_IP;
466 else
468 assert (!offset); /* This isn't a valid assertion but ip sends only
469 * whole datagrams up */
470 udp_ip_arrived(fd, data, bf_bufsize(data));
472 break;
473 default:
474 ip_panic((
475 "udp_put_data(%d, 0x%x, %p) called but up_state= 0x%x\n",
476 fd, offset, data, udp_port->up_state ));
478 return NW_OK;
481 static int udp_setopt(udp_fd)
482 udp_fd_t *udp_fd;
484 udp_fd_t *fd_ptr;
485 nwio_udpopt_t oldopt, newopt;
486 acc_t *data;
487 unsigned int new_en_flags, new_di_flags, old_en_flags, old_di_flags,
488 all_flags, flags;
489 unsigned long new_flags;
490 int i;
492 data= (*udp_fd->uf_get_userdata)(udp_fd->uf_srfd, 0,
493 sizeof(nwio_udpopt_t), TRUE);
495 if (!data)
496 return EFAULT;
498 data= bf_packIffLess(data, sizeof(nwio_udpopt_t));
499 assert (data->acc_length == sizeof(nwio_udpopt_t));
501 newopt= *(nwio_udpopt_t *)ptr2acc_data(data);
502 bf_afree(data);
503 oldopt= udp_fd->uf_udpopt;
505 old_en_flags= oldopt.nwuo_flags & 0xffff;
506 old_di_flags= (oldopt.nwuo_flags >> 16) & 0xffff;
508 new_en_flags= newopt.nwuo_flags & 0xffff;
509 new_di_flags= (newopt.nwuo_flags >> 16) & 0xffff;
511 if (new_en_flags & new_di_flags)
513 DBLOCK(1, printf("returning EBADMODE\n"));
515 reply_thr_get(udp_fd, EBADMODE, TRUE);
516 return NW_OK;
519 /* NWUO_ACC_MASK */
520 if (new_di_flags & NWUO_ACC_MASK)
522 DBLOCK(1, printf("returning EBADMODE\n"));
524 reply_thr_get(udp_fd, EBADMODE, TRUE);
525 return NW_OK;
526 /* access modes can't be disabled */
529 if (!(new_en_flags & NWUO_ACC_MASK))
530 new_en_flags |= (old_en_flags & NWUO_ACC_MASK);
532 /* NWUO_LOCPORT_MASK */
533 if (new_di_flags & NWUO_LOCPORT_MASK)
535 DBLOCK(1, printf("returning EBADMODE\n"));
537 reply_thr_get(udp_fd, EBADMODE, TRUE);
538 return NW_OK;
539 /* the loc ports can't be disabled */
541 if (!(new_en_flags & NWUO_LOCPORT_MASK))
543 new_en_flags |= (old_en_flags & NWUO_LOCPORT_MASK);
544 newopt.nwuo_locport= oldopt.nwuo_locport;
546 else if ((new_en_flags & NWUO_LOCPORT_MASK) == NWUO_LP_SEL)
548 newopt.nwuo_locport= find_unused_port(udp_fd-udp_fd_table);
550 else if ((new_en_flags & NWUO_LOCPORT_MASK) == NWUO_LP_SET)
552 if (!newopt.nwuo_locport)
554 DBLOCK(1, printf("returning EBADMODE\n"));
556 reply_thr_get(udp_fd, EBADMODE, TRUE);
557 return NW_OK;
561 /* NWUO_LOCADDR_MASK */
562 if (!((new_en_flags | new_di_flags) & NWUO_LOCADDR_MASK))
564 new_en_flags |= (old_en_flags & NWUO_LOCADDR_MASK);
565 new_di_flags |= (old_di_flags & NWUO_LOCADDR_MASK);
568 /* NWUO_BROAD_MASK */
569 if (!((new_en_flags | new_di_flags) & NWUO_BROAD_MASK))
571 new_en_flags |= (old_en_flags & NWUO_BROAD_MASK);
572 new_di_flags |= (old_di_flags & NWUO_BROAD_MASK);
575 /* NWUO_REMPORT_MASK */
576 if (!((new_en_flags | new_di_flags) & NWUO_REMPORT_MASK))
578 new_en_flags |= (old_en_flags & NWUO_REMPORT_MASK);
579 new_di_flags |= (old_di_flags & NWUO_REMPORT_MASK);
580 newopt.nwuo_remport= oldopt.nwuo_remport;
583 /* NWUO_REMADDR_MASK */
584 if (!((new_en_flags | new_di_flags) & NWUO_REMADDR_MASK))
586 new_en_flags |= (old_en_flags & NWUO_REMADDR_MASK);
587 new_di_flags |= (old_di_flags & NWUO_REMADDR_MASK);
588 newopt.nwuo_remaddr= oldopt.nwuo_remaddr;
591 /* NWUO_RW_MASK */
592 if (!((new_en_flags | new_di_flags) & NWUO_RW_MASK))
594 new_en_flags |= (old_en_flags & NWUO_RW_MASK);
595 new_di_flags |= (old_di_flags & NWUO_RW_MASK);
598 /* NWUO_IPOPT_MASK */
599 if (!((new_en_flags | new_di_flags) & NWUO_IPOPT_MASK))
601 new_en_flags |= (old_en_flags & NWUO_IPOPT_MASK);
602 new_di_flags |= (old_di_flags & NWUO_IPOPT_MASK);
605 new_flags= ((unsigned long)new_di_flags << 16) | new_en_flags;
606 if ((new_flags & NWUO_RWDATONLY) &&
607 ((new_flags & NWUO_LOCPORT_MASK) == NWUO_LP_ANY ||
608 (new_flags & (NWUO_RP_ANY|NWUO_RA_ANY|NWUO_EN_IPOPT))))
610 DBLOCK(1, printf("returning EBADMODE\n"));
612 reply_thr_get(udp_fd, EBADMODE, TRUE);
613 return NW_OK;
616 /* Check the access modes */
617 if ((new_flags & NWUO_LOCPORT_MASK) == NWUO_LP_SEL ||
618 (new_flags & NWUO_LOCPORT_MASK) == NWUO_LP_SET)
620 for (i= 0, fd_ptr= udp_fd_table; i<UDP_FD_NR; i++, fd_ptr++)
622 if (fd_ptr == udp_fd)
623 continue;
624 if (!(fd_ptr->uf_flags & UFF_INUSE))
625 continue;
626 if (fd_ptr->uf_port != udp_fd->uf_port)
627 continue;
628 flags= fd_ptr->uf_udpopt.nwuo_flags;
629 if ((flags & NWUO_LOCPORT_MASK) != NWUO_LP_SEL &&
630 (flags & NWUO_LOCPORT_MASK) != NWUO_LP_SET)
631 continue;
632 if (fd_ptr->uf_udpopt.nwuo_locport !=
633 newopt.nwuo_locport)
635 continue;
637 if ((flags & NWUO_ACC_MASK) !=
638 (new_flags & NWUO_ACC_MASK))
640 DBLOCK(1, printf(
641 "address inuse: new fd= %d, old_fd= %d, port= %u\n",
642 udp_fd-udp_fd_table,
643 fd_ptr-udp_fd_table,
644 newopt.nwuo_locport));
646 reply_thr_get(udp_fd, EADDRINUSE, TRUE);
647 return NW_OK;
652 if (udp_fd->uf_flags & UFF_OPTSET)
653 unhash_fd(udp_fd);
655 newopt.nwuo_flags= new_flags;
656 udp_fd->uf_udpopt= newopt;
658 all_flags= new_en_flags | new_di_flags;
659 if ((all_flags & NWUO_ACC_MASK) && (all_flags & NWUO_LOCPORT_MASK) &&
660 (all_flags & NWUO_LOCADDR_MASK) &&
661 (all_flags & NWUO_BROAD_MASK) &&
662 (all_flags & NWUO_REMPORT_MASK) &&
663 (all_flags & NWUO_REMADDR_MASK) &&
664 (all_flags & NWUO_RW_MASK) &&
665 (all_flags & NWUO_IPOPT_MASK))
666 udp_fd->uf_flags |= UFF_OPTSET;
667 else
669 udp_fd->uf_flags &= ~UFF_OPTSET;
672 if (udp_fd->uf_flags & UFF_OPTSET)
673 hash_fd(udp_fd);
675 reply_thr_get(udp_fd, NW_OK, TRUE);
676 return NW_OK;
679 static udpport_t find_unused_port(int fd)
681 udpport_t port, nw_port;
683 for (port= 0x8000+fd; port < 0xffff-UDP_FD_NR; port+= UDP_FD_NR)
685 nw_port= htons(port);
686 if (is_unused_port(nw_port))
687 return nw_port;
689 for (port= 0x8000; port < 0xffff; port++)
691 nw_port= htons(port);
692 if (is_unused_port(nw_port))
693 return nw_port;
695 ip_panic(( "unable to find unused port (shouldn't occur)" ));
696 return 0;
700 reply_thr_put
703 static void reply_thr_put(udp_fd, reply, for_ioctl)
704 udp_fd_t *udp_fd;
705 int reply;
706 int for_ioctl;
708 int result;
710 result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd, reply,
711 (acc_t *)0, for_ioctl);
712 assert(result == NW_OK);
716 reply_thr_get
719 static void reply_thr_get(udp_fd, reply, for_ioctl)
720 udp_fd_t *udp_fd;
721 int reply;
722 int for_ioctl;
724 acc_t *result;
725 result= (*udp_fd->uf_get_userdata)(udp_fd->uf_srfd, reply,
726 (size_t)0, for_ioctl);
727 assert (!result);
730 static int is_unused_port(udpport_t port)
732 int i;
733 udp_fd_t *udp_fd;
735 for (i= 0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++,
736 udp_fd++)
738 if (!(udp_fd->uf_flags & UFF_OPTSET))
739 continue;
740 if (udp_fd->uf_udpopt.nwuo_locport == port)
741 return FALSE;
743 return TRUE;
746 static void read_ip_packets(udp_port)
747 udp_port_t *udp_port;
749 int result;
753 udp_port->up_flags |= UPF_READ_IP;
754 result= ip_read(udp_port->up_ipfd, UDP_MAX_DATAGRAM);
755 if (result == NW_SUSPEND)
757 udp_port->up_flags |= UPF_READ_SP;
758 return;
760 assert(result == NW_OK);
761 udp_port->up_flags &= ~UPF_READ_IP;
762 } while(!(udp_port->up_flags & UPF_READ_IP));
766 static int udp_peek (udp_fd)
767 udp_fd_t *udp_fd;
769 acc_t *pack, *tmp_acc, *next_acc;
770 int result;
772 if (!(udp_fd->uf_flags & UFF_OPTSET))
774 udp_fd->uf_flags &= ~UFF_IOCTL_IP;
775 reply_thr_put(udp_fd, EBADMODE, TRUE);
776 return NW_OK;
779 if (udp_fd->uf_rdbuf_head)
781 if (get_time() <= udp_fd->uf_exp_tim)
783 pack= bf_cut(udp_fd->uf_rdbuf_head, 0,
784 sizeof(udp_io_hdr_t));
785 result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd,
786 (size_t)0, pack, TRUE);
788 udp_fd->uf_flags &= ~UFF_IOCTL_IP;
789 result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd,
790 result, (acc_t *)0, TRUE);
791 assert (result == 0);
792 return result;
794 tmp_acc= udp_fd->uf_rdbuf_head;
795 while (tmp_acc)
797 next_acc= tmp_acc->acc_ext_link;
798 bf_afree(tmp_acc);
799 tmp_acc= next_acc;
801 udp_fd->uf_rdbuf_head= NULL;
803 udp_fd->uf_flags |= UFF_PEEK_IP;
804 return NW_SUSPEND;
807 static int udp_sel_read (udp_fd_t *udp_fd)
809 acc_t *tmp_acc, *next_acc;
811 if (!(udp_fd->uf_flags & UFF_OPTSET))
812 return 1; /* Read will not block */
814 if (udp_fd->uf_rdbuf_head)
816 if (get_time() <= udp_fd->uf_exp_tim)
817 return 1;
819 tmp_acc= udp_fd->uf_rdbuf_head;
820 while (tmp_acc)
822 next_acc= tmp_acc->acc_ext_link;
823 bf_afree(tmp_acc);
824 tmp_acc= next_acc;
826 udp_fd->uf_rdbuf_head= NULL;
828 return 0;
831 static int udp_packet2user (udp_fd)
832 udp_fd_t *udp_fd;
834 acc_t *pack, *tmp_pack;
835 udp_io_hdr_t *hdr;
836 int result, hdr_len;
837 size_t size, transf_size;
839 pack= udp_fd->uf_rdbuf_head;
840 udp_fd->uf_rdbuf_head= pack->acc_ext_link;
842 size= bf_bufsize (pack);
844 if (udp_fd->uf_udpopt.nwuo_flags & NWUO_RWDATONLY)
847 pack= bf_packIffLess (pack, UDP_IO_HDR_SIZE);
848 assert (pack->acc_length >= UDP_IO_HDR_SIZE);
850 hdr= (udp_io_hdr_t *)ptr2acc_data(pack);
851 #if CONF_UDP_IO_NW_BYTE_ORDER
852 hdr_len= UDP_IO_HDR_SIZE+NTOHS(hdr->uih_ip_opt_len);
853 #else
854 hdr_len= UDP_IO_HDR_SIZE+hdr->uih_ip_opt_len;
855 #endif
857 assert (size>= hdr_len);
858 size -= hdr_len;
859 tmp_pack= bf_cut(pack, hdr_len, size);
860 bf_afree(pack);
861 pack= tmp_pack;
864 if (size>udp_fd->uf_rd_count)
866 tmp_pack= bf_cut (pack, 0, udp_fd->uf_rd_count);
867 bf_afree(pack);
868 pack= tmp_pack;
869 transf_size= udp_fd->uf_rd_count;
871 else
872 transf_size= size;
874 result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd,
875 (size_t)0, pack, FALSE);
877 if (result >= 0) {
878 if (size > transf_size)
879 result= EPACKSIZE;
880 else
881 result= transf_size;
884 udp_fd->uf_flags &= ~UFF_READ_IP;
885 result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd, result,
886 (acc_t *)0, FALSE);
887 assert (result == 0);
889 return result;
892 static void udp_ip_arrived(port, pack, pack_size)
893 int port;
894 acc_t *pack;
895 size_t pack_size;
897 udp_port_t *udp_port;
898 udp_fd_t *udp_fd, *share_fd;
899 acc_t *ip_hdr_acc, *udp_acc, *ipopt_pack, *no_ipopt_pack, *tmp_acc;
900 ip_hdr_t *ip_hdr;
901 udp_hdr_t *udp_hdr;
902 udp_io_hdr_t *udp_io_hdr;
903 size_t ip_hdr_size, udp_size, data_size, opt_size;
904 ipaddr_t src_addr, dst_addr, ipaddr;
905 udpport_t src_port, dst_port;
906 u8_t u16[2];
907 u16_t chksum;
908 unsigned long dst_type, flags;
909 clock_t exp_tim;
910 int i, delivered, hash;
912 udp_port= &udp_port_table[port];
914 ip_hdr_acc= bf_cut(pack, 0, IP_MIN_HDR_SIZE);
915 ip_hdr_acc= bf_packIffLess(ip_hdr_acc, IP_MIN_HDR_SIZE);
916 ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_hdr_acc);
917 ip_hdr_size= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
918 if (ip_hdr_size != IP_MIN_HDR_SIZE)
920 bf_afree(ip_hdr_acc);
921 ip_hdr_acc= bf_cut(pack, 0, ip_hdr_size);
922 ip_hdr_acc= bf_packIffLess(ip_hdr_acc, ip_hdr_size);
923 ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_hdr_acc);
926 pack_size -= ip_hdr_size;
927 if (pack_size < UDP_HDR_SIZE)
929 if (pack_size == 0 && ip_hdr->ih_proto == 0)
931 /* IP layer reports new IP address */
932 ipaddr= ip_hdr->ih_src;
933 udp_port->up_ipaddr= ipaddr;
934 DBLOCK(1, printf("udp_ip_arrived: using address ");
935 writeIpAddr(ipaddr); printf("\n"));
937 else
938 DBLOCK(1, printf("packet too small\n"));
940 bf_afree(ip_hdr_acc);
941 bf_afree(pack);
942 return;
945 udp_acc= bf_delhead(pack, ip_hdr_size);
946 pack= NULL;
949 udp_acc= bf_packIffLess(udp_acc, UDP_HDR_SIZE);
950 udp_hdr= (udp_hdr_t *)ptr2acc_data(udp_acc);
951 udp_size= ntohs(udp_hdr->uh_length);
952 if (udp_size > pack_size)
954 DBLOCK(1, printf("packet too large\n"));
956 bf_afree(ip_hdr_acc);
957 bf_afree(udp_acc);
958 return;
961 src_addr= ip_hdr->ih_src;
962 dst_addr= ip_hdr->ih_dst;
964 if (udp_hdr->uh_chksum)
966 u16[0]= 0;
967 u16[1]= ip_hdr->ih_proto;
968 chksum= pack_oneCsum(udp_acc);
969 chksum= oneC_sum(chksum, (u16_t *)&src_addr, sizeof(ipaddr_t));
970 chksum= oneC_sum(chksum, (u16_t *)&dst_addr, sizeof(ipaddr_t));
971 chksum= oneC_sum(chksum, (u16_t *)u16, sizeof(u16));
972 chksum= oneC_sum(chksum, (u16_t *)&udp_hdr->uh_length,
973 sizeof(udp_hdr->uh_length));
974 if (~chksum & 0xffff)
976 DBLOCK(1, printf("checksum error in udp packet\n");
977 printf("src ip_addr= ");
978 writeIpAddr(src_addr);
979 printf(" dst ip_addr= ");
980 writeIpAddr(dst_addr);
981 printf("\n");
982 printf("packet chksum= 0x%x, sum= 0x%x\n",
983 udp_hdr->uh_chksum, chksum));
985 bf_afree(ip_hdr_acc);
986 bf_afree(udp_acc);
987 return;
991 exp_tim= get_time() + UDP_READ_EXP_TIME;
992 src_port= udp_hdr->uh_src_port;
993 dst_port= udp_hdr->uh_dst_port;
995 /* Send an ICMP port unreachable if the packet could not be
996 * delivered.
998 delivered= 0;
1000 if (dst_addr == udp_port->up_ipaddr)
1001 dst_type= NWUO_EN_LOC;
1002 else
1004 dst_type= NWUO_EN_BROAD;
1006 /* Don't send ICMP error packets for broadcast packets */
1007 delivered= 1;
1010 DBLOCK(0x20, printf("udp: got packet from ");
1011 writeIpAddr(src_addr);
1012 printf(".%u to ", ntohs(src_port));
1013 writeIpAddr(dst_addr);
1014 printf(".%u\n", ntohs(dst_port)));
1016 no_ipopt_pack= bf_memreq(UDP_IO_HDR_SIZE);
1017 udp_io_hdr= (udp_io_hdr_t *)ptr2acc_data(no_ipopt_pack);
1018 udp_io_hdr->uih_src_addr= src_addr;
1019 udp_io_hdr->uih_dst_addr= dst_addr;
1020 udp_io_hdr->uih_src_port= src_port;
1021 udp_io_hdr->uih_dst_port= dst_port;
1022 data_size = udp_size-UDP_HDR_SIZE;
1023 #if CONF_UDP_IO_NW_BYTE_ORDER
1024 udp_io_hdr->uih_ip_opt_len= HTONS(0);
1025 udp_io_hdr->uih_data_len= htons(data_size);
1026 #else
1027 udp_io_hdr->uih_ip_opt_len= 0;
1028 udp_io_hdr->uih_data_len= data_size;
1029 #endif
1030 no_ipopt_pack->acc_next= bf_cut(udp_acc, UDP_HDR_SIZE, data_size);
1032 if (ip_hdr_size == IP_MIN_HDR_SIZE)
1034 ipopt_pack= no_ipopt_pack;
1035 ipopt_pack->acc_linkC++;
1037 else
1039 ipopt_pack= bf_memreq(UDP_IO_HDR_SIZE);
1040 *(udp_io_hdr_t *)ptr2acc_data(ipopt_pack)= *udp_io_hdr;
1041 udp_io_hdr= (udp_io_hdr_t *)ptr2acc_data(ipopt_pack);
1042 opt_size = ip_hdr_size-IP_MIN_HDR_SIZE;
1043 #if CONF_UDP_IO_NW_BYTE_ORDER
1044 udp_io_hdr->uih_ip_opt_len= htons(opt_size);
1045 #else
1046 udp_io_hdr->uih_ip_opt_len= opt_size;
1047 #endif
1048 tmp_acc= bf_cut(ip_hdr_acc, (size_t)IP_MIN_HDR_SIZE, opt_size);
1049 assert(tmp_acc->acc_linkC == 1);
1050 assert(tmp_acc->acc_next == NULL);
1051 ipopt_pack->acc_next= tmp_acc;
1053 tmp_acc->acc_next= no_ipopt_pack->acc_next;
1054 if (tmp_acc->acc_next)
1055 tmp_acc->acc_next->acc_linkC++;
1058 hash= dst_port;
1059 hash ^= (hash >> 8);
1060 hash &= (UDP_PORT_HASH_NR-1);
1062 for (i= 0; i<2; i++)
1064 share_fd= NULL;
1066 udp_fd= (i == 0) ? udp_port->up_port_any :
1067 udp_port->up_port_hash[hash];
1068 for (; udp_fd; udp_fd= udp_fd->uf_port_next)
1070 if (i && udp_fd->uf_udpopt.nwuo_locport != dst_port)
1071 continue;
1073 assert(udp_fd->uf_flags & UFF_INUSE);
1074 assert(udp_fd->uf_flags & UFF_OPTSET);
1076 if (udp_fd->uf_port != udp_port)
1077 continue;
1079 flags= udp_fd->uf_udpopt.nwuo_flags;
1080 if (!(flags & dst_type))
1081 continue;
1083 if ((flags & NWUO_RP_SET) &&
1084 udp_fd->uf_udpopt.nwuo_remport != src_port)
1086 continue;
1089 if ((flags & NWUO_RA_SET) &&
1090 udp_fd->uf_udpopt.nwuo_remaddr != src_addr)
1092 continue;
1095 if (i)
1097 /* Packet is considdered to be delivered */
1098 delivered= 1;
1101 if ((flags & NWUO_ACC_MASK) == NWUO_SHARED &&
1102 (!share_fd || !udp_fd->uf_rdbuf_head))
1104 share_fd= udp_fd;
1105 continue;
1108 if (flags & NWUO_EN_IPOPT)
1109 pack= ipopt_pack;
1110 else
1111 pack= no_ipopt_pack;
1113 pack->acc_linkC++;
1114 udp_rd_enqueue(udp_fd, pack, exp_tim);
1115 if (udp_fd->uf_flags & UFF_READ_IP)
1116 udp_packet2user(udp_fd);
1119 if (share_fd)
1121 flags= share_fd->uf_udpopt.nwuo_flags;
1122 if (flags & NWUO_EN_IPOPT)
1123 pack= ipopt_pack;
1124 else
1125 pack= no_ipopt_pack;
1127 pack->acc_linkC++;
1128 udp_rd_enqueue(share_fd, pack, exp_tim);
1129 if (share_fd->uf_flags & UFF_READ_IP)
1130 udp_packet2user(share_fd);
1134 if (ipopt_pack)
1135 bf_afree(ipopt_pack);
1136 if (no_ipopt_pack)
1137 bf_afree(no_ipopt_pack);
1139 if (!delivered)
1141 DBLOCK(0x2, printf("udp: could not deliver packet from ");
1142 writeIpAddr(src_addr);
1143 printf(".%u to ", ntohs(src_port));
1144 writeIpAddr(dst_addr);
1145 printf(".%u\n", ntohs(dst_port)));
1147 pack= bf_append(ip_hdr_acc, udp_acc);
1148 ip_hdr_acc= NULL;
1149 udp_acc= NULL;
1150 icmp_snd_unreachable(udp_port->up_ipdev, pack,
1151 ICMP_PORT_UNRCH);
1152 return;
1155 assert (ip_hdr_acc);
1156 bf_afree(ip_hdr_acc);
1157 assert (udp_acc);
1158 bf_afree(udp_acc);
1161 void udp_close(fd)
1162 int fd;
1164 udp_fd_t *udp_fd;
1165 acc_t *tmp_acc, *next_acc;
1167 udp_fd= &udp_fd_table[fd];
1169 assert (udp_fd->uf_flags & UFF_INUSE);
1171 if (udp_fd->uf_flags & UFF_OPTSET)
1172 unhash_fd(udp_fd);
1174 udp_fd->uf_flags= UFF_EMPTY;
1175 tmp_acc= udp_fd->uf_rdbuf_head;
1176 while (tmp_acc)
1178 next_acc= tmp_acc->acc_ext_link;
1179 bf_afree(tmp_acc);
1180 tmp_acc= next_acc;
1182 udp_fd->uf_rdbuf_head= NULL;
1185 int udp_write(int fd, size_t count)
1187 udp_fd_t *udp_fd;
1189 udp_fd= &udp_fd_table[fd];
1191 if (!(udp_fd->uf_flags & UFF_OPTSET))
1193 reply_thr_get (udp_fd, EBADMODE, FALSE);
1194 return NW_OK;
1197 assert (!(udp_fd->uf_flags & UFF_WRITE_IP));
1199 udp_fd->uf_wr_count= count;
1201 udp_fd->uf_flags |= UFF_WRITE_IP;
1203 restart_write_fd(udp_fd);
1205 if (udp_fd->uf_flags & UFF_WRITE_IP)
1207 DBLOCK(1, printf("replying NW_SUSPEND\n"));
1209 return NW_SUSPEND;
1211 else
1213 return NW_OK;
1217 static void restart_write_fd(udp_fd)
1218 udp_fd_t *udp_fd;
1220 udp_port_t *udp_port;
1221 acc_t *pack, *ip_hdr_pack, *udp_hdr_pack, *ip_opt_pack, *user_data;
1222 udp_hdr_t *udp_hdr;
1223 udp_io_hdr_t *udp_io_hdr;
1224 ip_hdr_t *ip_hdr;
1225 size_t ip_opt_size, user_data_size;
1226 unsigned long flags;
1227 u16_t chksum;
1228 u8_t u16[2];
1229 int result;
1231 udp_port= udp_fd->uf_port;
1233 if (udp_port->up_flags & UPF_WRITE_IP)
1235 udp_port->up_flags |= UPF_MORE2WRITE;
1236 return;
1239 assert (udp_fd->uf_flags & UFF_WRITE_IP);
1240 udp_fd->uf_flags &= ~UFF_WRITE_IP;
1242 assert (!udp_port->up_wr_pack);
1244 pack= (*udp_fd->uf_get_userdata)(udp_fd->uf_srfd, 0,
1245 udp_fd->uf_wr_count, FALSE);
1246 if (!pack)
1248 udp_fd->uf_flags &= ~UFF_WRITE_IP;
1249 reply_thr_get (udp_fd, EFAULT, FALSE);
1250 return;
1253 flags= udp_fd->uf_udpopt.nwuo_flags;
1255 ip_hdr_pack= bf_memreq(IP_MIN_HDR_SIZE);
1256 ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_hdr_pack);
1258 udp_hdr_pack= bf_memreq(UDP_HDR_SIZE);
1259 udp_hdr= (udp_hdr_t *)ptr2acc_data(udp_hdr_pack);
1261 if (flags & NWUO_RWDATALL)
1263 pack= bf_packIffLess(pack, UDP_IO_HDR_SIZE);
1264 udp_io_hdr= (udp_io_hdr_t *)ptr2acc_data(pack);
1265 #if CONF_UDP_IO_NW_BYTE_ORDER
1266 ip_opt_size= ntohs(udp_io_hdr->uih_ip_opt_len);
1267 #else
1268 ip_opt_size= udp_io_hdr->uih_ip_opt_len;
1269 #endif
1270 if (UDP_IO_HDR_SIZE+ip_opt_size>udp_fd->uf_wr_count)
1272 bf_afree(ip_hdr_pack);
1273 bf_afree(udp_hdr_pack);
1274 bf_afree(pack);
1275 reply_thr_get (udp_fd, EINVAL, FALSE);
1276 return;
1278 if (ip_opt_size & 3)
1280 bf_afree(ip_hdr_pack);
1281 bf_afree(udp_hdr_pack);
1282 bf_afree(pack);
1283 reply_thr_get (udp_fd, EFAULT, FALSE);
1284 return;
1286 if (ip_opt_size)
1287 ip_opt_pack= bf_cut(pack, UDP_IO_HDR_SIZE, ip_opt_size);
1288 else
1289 ip_opt_pack= 0;
1290 user_data_size= udp_fd->uf_wr_count-UDP_IO_HDR_SIZE-
1291 ip_opt_size;
1292 user_data= bf_cut(pack, UDP_IO_HDR_SIZE+ip_opt_size,
1293 user_data_size);
1294 bf_afree(pack);
1296 else
1298 udp_io_hdr= 0;
1299 ip_opt_size= 0;
1300 user_data_size= udp_fd->uf_wr_count;
1301 ip_opt_pack= 0;
1302 user_data= pack;
1305 ip_hdr->ih_vers_ihl= (IP_MIN_HDR_SIZE+ip_opt_size) >> 2;
1306 ip_hdr->ih_tos= UDP_TOS;
1307 ip_hdr->ih_flags_fragoff= HTONS(UDP_IP_FLAGS);
1308 ip_hdr->ih_ttl= IP_DEF_TTL;
1309 ip_hdr->ih_proto= IPPROTO_UDP;
1310 if (flags & NWUO_RA_SET)
1312 ip_hdr->ih_dst= udp_fd->uf_udpopt.nwuo_remaddr;
1314 else
1316 assert (udp_io_hdr);
1317 ip_hdr->ih_dst= udp_io_hdr->uih_dst_addr;
1320 if ((flags & NWUO_LOCPORT_MASK) != NWUO_LP_ANY)
1321 udp_hdr->uh_src_port= udp_fd->uf_udpopt.nwuo_locport;
1322 else
1324 assert (udp_io_hdr);
1325 udp_hdr->uh_src_port= udp_io_hdr->uih_src_port;
1328 if (flags & NWUO_RP_SET)
1329 udp_hdr->uh_dst_port= udp_fd->uf_udpopt.nwuo_remport;
1330 else
1332 assert (udp_io_hdr);
1333 udp_hdr->uh_dst_port= udp_io_hdr->uih_dst_port;
1336 udp_hdr->uh_length= htons(UDP_HDR_SIZE+user_data_size);
1337 udp_hdr->uh_chksum= 0;
1339 udp_hdr_pack->acc_next= user_data;
1340 chksum= pack_oneCsum(udp_hdr_pack);
1341 chksum= oneC_sum(chksum, (u16_t *)&udp_fd->uf_port->up_ipaddr,
1342 sizeof(ipaddr_t));
1343 chksum= oneC_sum(chksum, (u16_t *)&ip_hdr->ih_dst, sizeof(ipaddr_t));
1344 u16[0]= 0;
1345 u16[1]= IPPROTO_UDP;
1346 chksum= oneC_sum(chksum, (u16_t *)u16, sizeof(u16));
1347 chksum= oneC_sum(chksum, (u16_t *)&udp_hdr->uh_length, sizeof(u16_t));
1348 if (~chksum)
1349 chksum= ~chksum;
1350 udp_hdr->uh_chksum= chksum;
1352 if (ip_opt_pack)
1354 ip_opt_pack= bf_packIffLess(ip_opt_pack, ip_opt_size);
1355 ip_opt_pack->acc_next= udp_hdr_pack;
1356 udp_hdr_pack= ip_opt_pack;
1358 ip_hdr_pack->acc_next= udp_hdr_pack;
1360 assert (!udp_port->up_wr_pack);
1361 assert (!(udp_port->up_flags & UPF_WRITE_IP));
1363 udp_port->up_wr_pack= ip_hdr_pack;
1364 udp_port->up_flags |= UPF_WRITE_IP;
1365 result= ip_write(udp_port->up_ipfd, bf_bufsize(ip_hdr_pack));
1366 if (result == NW_SUSPEND)
1368 udp_port->up_flags |= UPF_WRITE_SP;
1369 udp_fd->uf_flags |= UFF_WRITE_IP;
1370 udp_port->up_write_fd= udp_fd;
1372 else if (result<0)
1373 reply_thr_get(udp_fd, result, FALSE);
1374 else
1375 reply_thr_get (udp_fd, udp_fd->uf_wr_count, FALSE);
1378 static u16_t pack_oneCsum(pack)
1379 acc_t *pack;
1381 u16_t prev;
1382 int odd_byte;
1383 char *data_ptr;
1384 int length;
1385 char byte_buf[2];
1387 assert (pack);
1389 prev= 0;
1391 odd_byte= FALSE;
1392 for (; pack; pack= pack->acc_next)
1395 data_ptr= ptr2acc_data(pack);
1396 length= pack->acc_length;
1398 if (!length)
1399 continue;
1400 if (odd_byte)
1402 byte_buf[1]= *data_ptr;
1403 prev= oneC_sum(prev, (u16_t *)byte_buf, 2);
1404 data_ptr++;
1405 length--;
1406 odd_byte= FALSE;
1408 if (length & 1)
1410 odd_byte= TRUE;
1411 length--;
1412 byte_buf[0]= data_ptr[length];
1414 if (!length)
1415 continue;
1416 prev= oneC_sum (prev, (u16_t *)data_ptr, length);
1418 if (odd_byte)
1420 byte_buf[1]= 0;
1421 prev= oneC_sum (prev, (u16_t *)byte_buf, 1);
1423 return prev;
1426 static void udp_restart_write_port(udp_port )
1427 udp_port_t *udp_port;
1429 udp_fd_t *udp_fd;
1430 int i;
1432 assert (!udp_port->up_wr_pack);
1433 assert (!(udp_port->up_flags & (UPF_WRITE_IP|UPF_WRITE_SP)));
1435 while (udp_port->up_flags & UPF_MORE2WRITE)
1437 udp_port->up_flags &= ~UPF_MORE2WRITE;
1439 for (i= 0, udp_fd= udp_port->up_next_fd; i<UDP_FD_NR;
1440 i++, udp_fd++)
1442 if (udp_fd == &udp_fd_table[UDP_FD_NR])
1443 udp_fd= udp_fd_table;
1445 if (!(udp_fd->uf_flags & UFF_INUSE))
1446 continue;
1447 if (!(udp_fd->uf_flags & UFF_WRITE_IP))
1448 continue;
1449 if (udp_fd->uf_port != udp_port)
1450 continue;
1451 restart_write_fd(udp_fd);
1452 if (udp_port->up_flags & UPF_WRITE_IP)
1454 udp_port->up_next_fd= udp_fd+1;
1455 udp_port->up_flags |= UPF_MORE2WRITE;
1456 return;
1462 int udp_cancel(fd, which_operation)
1463 int fd;
1464 int which_operation;
1466 udp_fd_t *udp_fd;
1468 DBLOCK(0x10, printf("udp_cancel(%d, %d)\n", fd, which_operation));
1470 udp_fd= &udp_fd_table[fd];
1472 switch (which_operation)
1474 case SR_CANCEL_READ:
1475 assert (udp_fd->uf_flags & UFF_READ_IP);
1476 udp_fd->uf_flags &= ~UFF_READ_IP;
1477 reply_thr_put(udp_fd, EINTR, FALSE);
1478 break;
1479 case SR_CANCEL_WRITE:
1480 assert (udp_fd->uf_flags & UFF_WRITE_IP);
1481 udp_fd->uf_flags &= ~UFF_WRITE_IP;
1482 if (udp_fd->uf_port->up_write_fd == udp_fd)
1483 udp_fd->uf_port->up_write_fd= NULL;
1484 reply_thr_get(udp_fd, EINTR, FALSE);
1485 break;
1486 case SR_CANCEL_IOCTL:
1487 assert (udp_fd->uf_flags & UFF_IOCTL_IP);
1488 udp_fd->uf_flags &= ~UFF_IOCTL_IP;
1489 udp_fd->uf_flags &= ~UFF_PEEK_IP;
1490 reply_thr_get(udp_fd, EINTR, TRUE);
1491 break;
1492 default:
1493 ip_panic(( "got unknown cancel request" ));
1495 return NW_OK;
1498 static void udp_buffree (priority)
1499 int priority;
1501 int i;
1502 udp_fd_t *udp_fd;
1503 acc_t *tmp_acc;
1505 if (priority == UDP_PRI_FDBUFS_EXTRA)
1507 for (i=0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++, udp_fd++)
1509 while (udp_fd->uf_rdbuf_head &&
1510 udp_fd->uf_rdbuf_head->acc_ext_link)
1512 tmp_acc= udp_fd->uf_rdbuf_head;
1513 udp_fd->uf_rdbuf_head= tmp_acc->acc_ext_link;
1514 bf_afree(tmp_acc);
1519 if (priority == UDP_PRI_FDBUFS)
1521 for (i=0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++, udp_fd++)
1523 while (udp_fd->uf_rdbuf_head)
1525 tmp_acc= udp_fd->uf_rdbuf_head;
1526 udp_fd->uf_rdbuf_head= tmp_acc->acc_ext_link;
1527 bf_afree(tmp_acc);
1533 static void udp_rd_enqueue(udp_fd, pack, exp_tim)
1534 udp_fd_t *udp_fd;
1535 acc_t *pack;
1536 clock_t exp_tim;
1538 acc_t *tmp_acc;
1539 int result;
1541 if (pack->acc_linkC != 1)
1543 tmp_acc= bf_dupacc(pack);
1544 bf_afree(pack);
1545 pack= tmp_acc;
1547 pack->acc_ext_link= NULL;
1548 if (udp_fd->uf_rdbuf_head == NULL)
1550 udp_fd->uf_exp_tim= exp_tim;
1551 udp_fd->uf_rdbuf_head= pack;
1553 else
1554 udp_fd->uf_rdbuf_tail->acc_ext_link= pack;
1555 udp_fd->uf_rdbuf_tail= pack;
1557 if (udp_fd->uf_flags & UFF_PEEK_IP)
1559 pack= bf_cut(udp_fd->uf_rdbuf_head, 0,
1560 sizeof(udp_io_hdr_t));
1561 result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd,
1562 (size_t)0, pack, TRUE);
1564 udp_fd->uf_flags &= ~UFF_IOCTL_IP;
1565 udp_fd->uf_flags &= ~UFF_PEEK_IP;
1566 result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd,
1567 result, (acc_t *)0, TRUE);
1568 assert (result == 0);
1571 if (udp_fd->uf_flags & UFF_SEL_READ)
1573 udp_fd->uf_flags &= ~UFF_SEL_READ;
1574 if (udp_fd->uf_select_res)
1575 udp_fd->uf_select_res(udp_fd->uf_srfd, SR_SELECT_READ);
1576 else
1577 printf("udp_rd_enqueue: no select_res\n");
1581 static void hash_fd(udp_fd)
1582 udp_fd_t *udp_fd;
1584 udp_port_t *udp_port;
1585 int hash;
1587 udp_port= udp_fd->uf_port;
1588 if ((udp_fd->uf_udpopt.nwuo_flags & NWUO_LOCPORT_MASK) ==
1589 NWUO_LP_ANY)
1591 udp_fd->uf_port_next= udp_port->up_port_any;
1592 udp_port->up_port_any= udp_fd;
1594 else
1596 hash= udp_fd->uf_udpopt.nwuo_locport;
1597 hash ^= (hash >> 8);
1598 hash &= (UDP_PORT_HASH_NR-1);
1600 udp_fd->uf_port_next= udp_port->up_port_hash[hash];
1601 udp_port->up_port_hash[hash]= udp_fd;
1605 static void unhash_fd(udp_fd)
1606 udp_fd_t *udp_fd;
1608 udp_port_t *udp_port;
1609 udp_fd_t *prev, *curr, **udp_fd_p;
1610 int hash;
1612 udp_port= udp_fd->uf_port;
1613 if ((udp_fd->uf_udpopt.nwuo_flags & NWUO_LOCPORT_MASK) ==
1614 NWUO_LP_ANY)
1616 udp_fd_p= &udp_port->up_port_any;
1618 else
1620 hash= udp_fd->uf_udpopt.nwuo_locport;
1621 hash ^= (hash >> 8);
1622 hash &= (UDP_PORT_HASH_NR-1);
1624 udp_fd_p= &udp_port->up_port_hash[hash];
1626 for (prev= NULL, curr= *udp_fd_p; curr;
1627 prev= curr, curr= curr->uf_port_next)
1629 if (curr == udp_fd)
1630 break;
1632 assert(curr);
1633 if (prev)
1634 prev->uf_port_next= curr->uf_port_next;
1635 else
1636 *udp_fd_p= curr->uf_port_next;
1639 #ifdef BUF_CONSISTENCY_CHECK
1640 static void udp_bufcheck()
1642 int i;
1643 udp_port_t *udp_port;
1644 udp_fd_t *udp_fd;
1645 acc_t *tmp_acc;
1647 for (i= 0, udp_port= udp_port_table; i<udp_conf_nr; i++, udp_port++)
1649 if (udp_port->up_wr_pack)
1650 bf_check_acc(udp_port->up_wr_pack);
1653 for (i= 0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++, udp_fd++)
1655 for (tmp_acc= udp_fd->uf_rdbuf_head; tmp_acc;
1656 tmp_acc= tmp_acc->acc_ext_link)
1658 bf_check_acc(tmp_acc);
1662 #endif
1665 * $PchId: udp.c,v 1.25 2005/06/28 14:14:44 philip Exp $