00001
00002
00003
00004
00005
00006
00007 #include "inet.h"
00008 #include "type.h"
00009
00010 #include "assert.h"
00011 #include "buf.h"
00012 #include "clock.h"
00013 #include "icmp_lib.h"
00014 #include "io.h"
00015 #include "ip.h"
00016 #include "sr.h"
00017 #include "udp.h"
00018 #include "udp_int.h"
00019
00020 THIS_FILE
00021
00022 FORWARD void read_ip_packets ARGS(( udp_port_t *udp_port ));
00023 FORWARD void udp_buffree ARGS(( int priority ));
00024 #ifdef BUF_CONSISTENCY_CHECK
00025 FORWARD void udp_bufcheck ARGS(( void ));
00026 #endif
00027 FORWARD void udp_main ARGS(( udp_port_t *udp_port ));
00028 FORWARD int udp_select ARGS(( int fd, unsigned operations ));
00029 FORWARD acc_t *udp_get_data ARGS(( int fd, size_t offset, size_t count,
00030 int for_ioctl ));
00031 FORWARD int udp_put_data ARGS(( int fd, size_t offset, acc_t *data,
00032 int for_ioctl ));
00033 FORWARD int udp_peek ARGS(( udp_fd_t * ));
00034 FORWARD int udp_sel_read ARGS(( udp_fd_t * ));
00035 FORWARD void udp_restart_write_port ARGS(( udp_port_t *udp_port ));
00036 FORWARD void udp_ip_arrived ARGS(( int port, acc_t *pack, size_t pack_size ));
00037 FORWARD void reply_thr_put ARGS(( udp_fd_t *udp_fd, int reply,
00038 int for_ioctl ));
00039 FORWARD void reply_thr_get ARGS(( udp_fd_t *udp_fd, int reply,
00040 int for_ioctl ));
00041 FORWARD int udp_setopt ARGS(( udp_fd_t *udp_fd ));
00042 FORWARD udpport_t find_unused_port ARGS(( int fd ));
00043 FORWARD int is_unused_port ARGS(( Udpport_t port ));
00044 FORWARD int udp_packet2user ARGS(( udp_fd_t *udp_fd ));
00045 FORWARD void restart_write_fd ARGS(( udp_fd_t *udp_fd ));
00046 FORWARD u16_t pack_oneCsum ARGS(( acc_t *pack ));
00047 FORWARD void udp_rd_enqueue ARGS(( udp_fd_t *udp_fd, acc_t *pack,
00048 clock_t exp_tim ));
00049 FORWARD void hash_fd ARGS(( udp_fd_t *udp_fd ));
00050 FORWARD void unhash_fd ARGS(( udp_fd_t *udp_fd ));
00051
00052 PUBLIC udp_port_t *udp_port_table;
00053 PUBLIC udp_fd_t udp_fd_table[UDP_FD_NR];
00054
00055 PUBLIC void udp_prep()
00056 {
00057 udp_port_table= alloc(udp_conf_nr * sizeof(udp_port_table[0]));
00058 }
00059
00060 PUBLIC void udp_init()
00061 {
00062 udp_fd_t *udp_fd;
00063 udp_port_t *udp_port;
00064 int i, j, ifno;
00065
00066 assert (BUF_S >= sizeof(struct nwio_ipopt));
00067 assert (BUF_S >= sizeof(struct nwio_ipconf));
00068 assert (BUF_S >= sizeof(struct nwio_udpopt));
00069 assert (BUF_S >= sizeof(struct udp_io_hdr));
00070 assert (UDP_HDR_SIZE == sizeof(udp_hdr_t));
00071 assert (UDP_IO_HDR_SIZE == sizeof(udp_io_hdr_t));
00072
00073 for (i= 0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++, udp_fd++)
00074 {
00075 udp_fd->uf_flags= UFF_EMPTY;
00076 udp_fd->uf_rdbuf_head= NULL;
00077 }
00078
00079 #ifndef BUF_CONSISTENCY_CHECK
00080 bf_logon(udp_buffree);
00081 #else
00082 bf_logon(udp_buffree, udp_bufcheck);
00083 #endif
00084
00085 for (i= 0, udp_port= udp_port_table; i<udp_conf_nr; i++, udp_port++)
00086 {
00087 udp_port->up_ipdev= udp_conf[i].uc_port;
00088
00089 udp_port->up_flags= UPF_EMPTY;
00090 udp_port->up_state= UPS_EMPTY;
00091 udp_port->up_next_fd= udp_fd_table;
00092 udp_port->up_write_fd= NULL;
00093 udp_port->up_wr_pack= NULL;
00094 udp_port->up_port_any= NULL;
00095 for (j= 0; j<UDP_PORT_HASH_NR; j++)
00096 udp_port->up_port_hash[j]= NULL;
00097
00098 ifno= ip_conf[udp_port->up_ipdev].ic_ifno;
00099 sr_add_minor(if2minor(ifno, UDP_DEV_OFF),
00100 i, udp_open, udp_close, udp_read,
00101 udp_write, udp_ioctl, udp_cancel, udp_select);
00102
00103 udp_main(udp_port);
00104 }
00105 }
00106
00107 PUBLIC int udp_open (port, srfd, get_userdata, put_userdata, put_pkt,
00108 select_res)
00109 int port;
00110 int srfd;
00111 get_userdata_t get_userdata;
00112 put_userdata_t put_userdata;
00113 put_pkt_t put_pkt;
00114 select_res_t select_res;
00115 {
00116 int i;
00117 udp_fd_t *udp_fd;
00118
00119 for (i= 0; i<UDP_FD_NR && (udp_fd_table[i].uf_flags & UFF_INUSE);
00120 i++);
00121
00122 if (i>= UDP_FD_NR)
00123 {
00124 DBLOCK(1, printf("out of fds\n"));
00125 return EAGAIN;
00126 }
00127
00128 udp_fd= &udp_fd_table[i];
00129
00130 udp_fd->uf_flags= UFF_INUSE;
00131 udp_fd->uf_port= &udp_port_table[port];
00132 udp_fd->uf_srfd= srfd;
00133 udp_fd->uf_udpopt.nwuo_flags= UDP_DEF_OPT;
00134 udp_fd->uf_get_userdata= get_userdata;
00135 udp_fd->uf_put_userdata= put_userdata;
00136 udp_fd->uf_select_res= select_res;
00137 assert(udp_fd->uf_rdbuf_head == NULL);
00138 udp_fd->uf_port_next= NULL;
00139
00140 return i;
00141
00142 }
00143
00144 PUBLIC int udp_ioctl (fd, req)
00145 int fd;
00146 ioreq_t req;
00147 {
00148 udp_fd_t *udp_fd;
00149 udp_port_t *udp_port;
00150 nwio_udpopt_t *udp_opt;
00151 acc_t *opt_acc;
00152 int result;
00153
00154 udp_fd= &udp_fd_table[fd];
00155
00156 assert (udp_fd->uf_flags & UFF_INUSE);
00157
00158 udp_port= udp_fd->uf_port;
00159 udp_fd->uf_flags |= UFF_IOCTL_IP;
00160 udp_fd->uf_ioreq= req;
00161
00162 if (udp_port->up_state != UPS_MAIN)
00163 return NW_SUSPEND;
00164
00165 switch(req)
00166 {
00167 case NWIOSUDPOPT:
00168 result= udp_setopt(udp_fd);
00169 break;
00170 case NWIOGUDPOPT:
00171 opt_acc= bf_memreq(sizeof(*udp_opt));
00172 assert (opt_acc->acc_length == sizeof(*udp_opt));
00173 udp_opt= (nwio_udpopt_t *)ptr2acc_data(opt_acc);
00174
00175 *udp_opt= udp_fd->uf_udpopt;
00176 udp_opt->nwuo_locaddr= udp_fd->uf_port->up_ipaddr;
00177 result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd, 0, opt_acc,
00178 TRUE);
00179 if (result == NW_OK)
00180 reply_thr_put(udp_fd, NW_OK, TRUE);
00181 break;
00182 case NWIOUDPPEEK:
00183 result= udp_peek(udp_fd);
00184 break;
00185 default:
00186 reply_thr_get(udp_fd, EBADIOCTL, TRUE);
00187 result= NW_OK;
00188 break;
00189 }
00190 if (result != NW_SUSPEND)
00191 udp_fd->uf_flags &= ~UFF_IOCTL_IP;
00192 return result;
00193 }
00194
00195 PUBLIC int udp_read (fd, count)
00196 int fd;
00197 size_t count;
00198 {
00199 udp_fd_t *udp_fd;
00200 acc_t *tmp_acc, *next_acc;
00201
00202 udp_fd= &udp_fd_table[fd];
00203 if (!(udp_fd->uf_flags & UFF_OPTSET))
00204 {
00205 reply_thr_put(udp_fd, EBADMODE, FALSE);
00206 return NW_OK;
00207 }
00208
00209 udp_fd->uf_rd_count= count;
00210
00211 if (udp_fd->uf_rdbuf_head)
00212 {
00213 if (get_time() <= udp_fd->uf_exp_tim)
00214 return udp_packet2user (udp_fd);
00215 tmp_acc= udp_fd->uf_rdbuf_head;
00216 while (tmp_acc)
00217 {
00218 next_acc= tmp_acc->acc_ext_link;
00219 bf_afree(tmp_acc);
00220 tmp_acc= next_acc;
00221 }
00222 udp_fd->uf_rdbuf_head= NULL;
00223 }
00224 udp_fd->uf_flags |= UFF_READ_IP;
00225 return NW_SUSPEND;
00226 }
00227
00228 PRIVATE void udp_main(udp_port)
00229 udp_port_t *udp_port;
00230 {
00231 udp_fd_t *udp_fd;
00232 int result, i;
00233
00234 switch (udp_port->up_state)
00235 {
00236 case UPS_EMPTY:
00237 udp_port->up_state= UPS_SETPROTO;
00238
00239 udp_port->up_ipfd= ip_open(udp_port->up_ipdev,
00240 udp_port->up_ipdev, udp_get_data, udp_put_data,
00241 udp_ip_arrived, 0 );
00242 if (udp_port->up_ipfd < 0)
00243 {
00244 udp_port->up_state= UPS_ERROR;
00245 DBLOCK(1, printf("%s, %d: unable to open ip port\n",
00246 __FILE__, __LINE__));
00247 return;
00248 }
00249
00250 result= ip_ioctl(udp_port->up_ipfd, NWIOSIPOPT);
00251 if (result == NW_SUSPEND)
00252 udp_port->up_flags |= UPF_SUSPEND;
00253 if (result<0)
00254 {
00255 return;
00256 }
00257 if (udp_port->up_state != UPS_GETCONF)
00258 return;
00259
00260 case UPS_GETCONF:
00261 udp_port->up_flags &= ~UPF_SUSPEND;
00262
00263 result= ip_ioctl(udp_port->up_ipfd, NWIOGIPCONF);
00264 if (result == NW_SUSPEND)
00265 udp_port->up_flags |= UPF_SUSPEND;
00266 if (result<0)
00267 {
00268 return;
00269 }
00270 if (udp_port->up_state != UPS_MAIN)
00271 return;
00272
00273 case UPS_MAIN:
00274 udp_port->up_flags &= ~UPF_SUSPEND;
00275
00276 for (i= 0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++, udp_fd++)
00277 {
00278 if (!(udp_fd->uf_flags & UFF_INUSE))
00279 continue;
00280 if (udp_fd->uf_port != udp_port)
00281 continue;
00282 if (udp_fd->uf_flags & UFF_IOCTL_IP)
00283 udp_ioctl(i, udp_fd->uf_ioreq);
00284 }
00285 read_ip_packets(udp_port);
00286 return;
00287 default:
00288 DBLOCK(1, printf("udp_port_table[%d].up_state= %d\n",
00289 udp_port->up_ipdev, udp_port->up_state));
00290 ip_panic(( "unknown state" ));
00291 break;
00292 }
00293 }
00294
00295 PRIVATE int udp_select(fd, operations)
00296 int fd;
00297 unsigned operations;
00298 {
00299 int i;
00300 unsigned resops;
00301 udp_fd_t *udp_fd;
00302
00303 udp_fd= &udp_fd_table[fd];
00304 assert (udp_fd->uf_flags & UFF_INUSE);
00305
00306 resops= 0;
00307
00308 if (operations & SR_SELECT_READ)
00309 {
00310 if (udp_sel_read(udp_fd))
00311 resops |= SR_SELECT_READ;
00312 else if (!(operations & SR_SELECT_POLL))
00313 udp_fd->uf_flags |= UFF_SEL_READ;
00314 }
00315 if (operations & SR_SELECT_WRITE)
00316 {
00317
00318 resops |= SR_SELECT_WRITE;
00319 }
00320 if (operations & SR_SELECT_EXCEPTION)
00321 {
00322 printf("udp_select: not implemented for exceptions\n");
00323 }
00324 return resops;
00325 }
00326
00327 PRIVATE acc_t *udp_get_data (port, offset, count, for_ioctl)
00328 int port;
00329 size_t offset;
00330 size_t count;
00331 int for_ioctl;
00332 {
00333 udp_port_t *udp_port;
00334 udp_fd_t *udp_fd;
00335 int result;
00336
00337 udp_port= &udp_port_table[port];
00338
00339 switch(udp_port->up_state)
00340 {
00341 case UPS_SETPROTO:
00342 assert (for_ioctl);
00343 if (!count)
00344 {
00345 result= (int)offset;
00346 if (result<0)
00347 {
00348 udp_port->up_state= UPS_ERROR;
00349 break;
00350 }
00351 udp_port->up_state= UPS_GETCONF;
00352 if (udp_port->up_flags & UPF_SUSPEND)
00353 udp_main(udp_port);
00354 return NULL;
00355 }
00356 else
00357 {
00358 struct nwio_ipopt *ipopt;
00359 acc_t *acc;
00360
00361 assert (!offset);
00362 assert (count == sizeof(*ipopt));
00363
00364 acc= bf_memreq(sizeof(*ipopt));
00365 ipopt= (struct nwio_ipopt *)ptr2acc_data(acc);
00366 ipopt->nwio_flags= NWIO_COPY | NWIO_EN_LOC |
00367 NWIO_EN_BROAD | NWIO_REMANY | NWIO_PROTOSPEC |
00368 NWIO_HDR_O_ANY | NWIO_RWDATALL;
00369 ipopt->nwio_proto= IPPROTO_UDP;
00370 return acc;
00371 }
00372 case UPS_MAIN:
00373 assert (!for_ioctl);
00374 assert (udp_port->up_flags & UPF_WRITE_IP);
00375 if (!count)
00376 {
00377 result= (int)offset;
00378 assert (udp_port->up_wr_pack);
00379 bf_afree(udp_port->up_wr_pack);
00380 udp_port->up_wr_pack= 0;
00381 if (udp_port->up_flags & UPF_WRITE_SP)
00382 {
00383 if (udp_port->up_write_fd)
00384 {
00385 udp_fd= udp_port->up_write_fd;
00386 udp_port->up_write_fd= NULL;
00387 udp_fd->uf_flags &= ~UFF_WRITE_IP;
00388 reply_thr_get(udp_fd, result, FALSE);
00389 }
00390 udp_port->up_flags &= ~(UPF_WRITE_SP |
00391 UPF_WRITE_IP);
00392 if (udp_port->up_flags & UPF_MORE2WRITE)
00393 {
00394 udp_restart_write_port(udp_port);
00395 }
00396 }
00397 else
00398 udp_port->up_flags &= ~UPF_WRITE_IP;
00399 }
00400 else
00401 {
00402 return bf_cut (udp_port->up_wr_pack, offset, count);
00403 }
00404 break;
00405 default:
00406 printf("udp_get_data(%d, 0x%x, 0x%x) called but up_state= 0x%x\n",
00407 port, offset, count, udp_port->up_state);
00408 break;
00409 }
00410 return NULL;
00411 }
00412
00413 PRIVATE int udp_put_data (fd, offset, data, for_ioctl)
00414 int fd;
00415 size_t offset;
00416 acc_t *data;
00417 int for_ioctl;
00418 {
00419 udp_port_t *udp_port;
00420 int result;
00421
00422 udp_port= &udp_port_table[fd];
00423
00424 switch (udp_port->up_state)
00425 {
00426 case UPS_GETCONF:
00427 if (!data)
00428 {
00429 result= (int)offset;
00430 if (result<0)
00431 {
00432 udp_port->up_state= UPS_ERROR;
00433 return NW_OK;
00434 }
00435 udp_port->up_state= UPS_MAIN;
00436 if (udp_port->up_flags & UPF_SUSPEND)
00437 udp_main(udp_port);
00438 }
00439 else
00440 {
00441 struct nwio_ipconf *ipconf;
00442
00443 data= bf_packIffLess(data, sizeof(*ipconf));
00444 ipconf= (struct nwio_ipconf *)ptr2acc_data(data);
00445 assert (ipconf->nwic_flags & NWIC_IPADDR_SET);
00446 udp_port->up_ipaddr= ipconf->nwic_ipaddr;
00447 bf_afree(data);
00448 }
00449 break;
00450 case UPS_MAIN:
00451 assert(0);
00452
00453 assert (udp_port->up_flags & UPF_READ_IP);
00454 if (!data)
00455 {
00456 result= (int)offset;
00457 compare (result, >=, 0);
00458 if (udp_port->up_flags & UPF_READ_SP)
00459 {
00460 udp_port->up_flags &= ~(UPF_READ_SP|
00461 UPF_READ_IP);
00462 read_ip_packets(udp_port);
00463 }
00464 else
00465 udp_port->up_flags &= ~UPF_READ_IP;
00466 }
00467 else
00468 {
00469 assert (!offset);
00470
00471 udp_ip_arrived(fd, data, bf_bufsize(data));
00472 }
00473 break;
00474 default:
00475 ip_panic((
00476 "udp_put_data(%d, 0x%x, %p) called but up_state= 0x%x\n",
00477 fd, offset, data, udp_port->up_state ));
00478 }
00479 return NW_OK;
00480 }
00481
00482 PRIVATE int udp_setopt(udp_fd)
00483 udp_fd_t *udp_fd;
00484 {
00485 udp_fd_t *fd_ptr;
00486 nwio_udpopt_t oldopt, newopt;
00487 acc_t *data;
00488 unsigned int new_en_flags, new_di_flags, old_en_flags, old_di_flags,
00489 all_flags, flags;
00490 unsigned long new_flags;
00491 int i;
00492
00493 data= (*udp_fd->uf_get_userdata)(udp_fd->uf_srfd, 0,
00494 sizeof(nwio_udpopt_t), TRUE);
00495
00496 if (!data)
00497 return EFAULT;
00498
00499 data= bf_packIffLess(data, sizeof(nwio_udpopt_t));
00500 assert (data->acc_length == sizeof(nwio_udpopt_t));
00501
00502 newopt= *(nwio_udpopt_t *)ptr2acc_data(data);
00503 bf_afree(data);
00504 oldopt= udp_fd->uf_udpopt;
00505
00506 old_en_flags= oldopt.nwuo_flags & 0xffff;
00507 old_di_flags= (oldopt.nwuo_flags >> 16) & 0xffff;
00508
00509 new_en_flags= newopt.nwuo_flags & 0xffff;
00510 new_di_flags= (newopt.nwuo_flags >> 16) & 0xffff;
00511
00512 if (new_en_flags & new_di_flags)
00513 {
00514 DBLOCK(1, printf("returning EBADMODE\n"));
00515
00516 reply_thr_get(udp_fd, EBADMODE, TRUE);
00517 return NW_OK;
00518 }
00519
00520
00521 if (new_di_flags & NWUO_ACC_MASK)
00522 {
00523 DBLOCK(1, printf("returning EBADMODE\n"));
00524
00525 reply_thr_get(udp_fd, EBADMODE, TRUE);
00526 return NW_OK;
00527
00528 }
00529
00530 if (!(new_en_flags & NWUO_ACC_MASK))
00531 new_en_flags |= (old_en_flags & NWUO_ACC_MASK);
00532
00533
00534 if (new_di_flags & NWUO_LOCPORT_MASK)
00535 {
00536 DBLOCK(1, printf("returning EBADMODE\n"));
00537
00538 reply_thr_get(udp_fd, EBADMODE, TRUE);
00539 return NW_OK;
00540
00541 }
00542 if (!(new_en_flags & NWUO_LOCPORT_MASK))
00543 {
00544 new_en_flags |= (old_en_flags & NWUO_LOCPORT_MASK);
00545 newopt.nwuo_locport= oldopt.nwuo_locport;
00546 }
00547 else if ((new_en_flags & NWUO_LOCPORT_MASK) == NWUO_LP_SEL)
00548 {
00549 newopt.nwuo_locport= find_unused_port(udp_fd-udp_fd_table);
00550 }
00551 else if ((new_en_flags & NWUO_LOCPORT_MASK) == NWUO_LP_SET)
00552 {
00553 if (!newopt.nwuo_locport)
00554 {
00555 DBLOCK(1, printf("returning EBADMODE\n"));
00556
00557 reply_thr_get(udp_fd, EBADMODE, TRUE);
00558 return NW_OK;
00559 }
00560 }
00561
00562
00563 if (!((new_en_flags | new_di_flags) & NWUO_LOCADDR_MASK))
00564 {
00565 new_en_flags |= (old_en_flags & NWUO_LOCADDR_MASK);
00566 new_di_flags |= (old_di_flags & NWUO_LOCADDR_MASK);
00567 }
00568
00569
00570 if (!((new_en_flags | new_di_flags) & NWUO_BROAD_MASK))
00571 {
00572 new_en_flags |= (old_en_flags & NWUO_BROAD_MASK);
00573 new_di_flags |= (old_di_flags & NWUO_BROAD_MASK);
00574 }
00575
00576
00577 if (!((new_en_flags | new_di_flags) & NWUO_REMPORT_MASK))
00578 {
00579 new_en_flags |= (old_en_flags & NWUO_REMPORT_MASK);
00580 new_di_flags |= (old_di_flags & NWUO_REMPORT_MASK);
00581 newopt.nwuo_remport= oldopt.nwuo_remport;
00582 }
00583
00584
00585 if (!((new_en_flags | new_di_flags) & NWUO_REMADDR_MASK))
00586 {
00587 new_en_flags |= (old_en_flags & NWUO_REMADDR_MASK);
00588 new_di_flags |= (old_di_flags & NWUO_REMADDR_MASK);
00589 newopt.nwuo_remaddr= oldopt.nwuo_remaddr;
00590 }
00591
00592
00593 if (!((new_en_flags | new_di_flags) & NWUO_RW_MASK))
00594 {
00595 new_en_flags |= (old_en_flags & NWUO_RW_MASK);
00596 new_di_flags |= (old_di_flags & NWUO_RW_MASK);
00597 }
00598
00599
00600 if (!((new_en_flags | new_di_flags) & NWUO_IPOPT_MASK))
00601 {
00602 new_en_flags |= (old_en_flags & NWUO_IPOPT_MASK);
00603 new_di_flags |= (old_di_flags & NWUO_IPOPT_MASK);
00604 }
00605
00606 new_flags= ((unsigned long)new_di_flags << 16) | new_en_flags;
00607 if ((new_flags & NWUO_RWDATONLY) &&
00608 ((new_flags & NWUO_LOCPORT_MASK) == NWUO_LP_ANY ||
00609 (new_flags & (NWUO_RP_ANY|NWUO_RA_ANY|NWUO_EN_IPOPT))))
00610 {
00611 DBLOCK(1, printf("returning EBADMODE\n"));
00612
00613 reply_thr_get(udp_fd, EBADMODE, TRUE);
00614 return NW_OK;
00615 }
00616
00617
00618 if ((new_flags & NWUO_LOCPORT_MASK) == NWUO_LP_SEL ||
00619 (new_flags & NWUO_LOCPORT_MASK) == NWUO_LP_SET)
00620 {
00621 for (i= 0, fd_ptr= udp_fd_table; i<UDP_FD_NR; i++, fd_ptr++)
00622 {
00623 if (fd_ptr == udp_fd)
00624 continue;
00625 if (!(fd_ptr->uf_flags & UFF_INUSE))
00626 continue;
00627 if (fd_ptr->uf_port != udp_fd->uf_port)
00628 continue;
00629 flags= fd_ptr->uf_udpopt.nwuo_flags;
00630 if ((flags & NWUO_LOCPORT_MASK) != NWUO_LP_SEL &&
00631 (flags & NWUO_LOCPORT_MASK) != NWUO_LP_SET)
00632 continue;
00633 if (fd_ptr->uf_udpopt.nwuo_locport !=
00634 newopt.nwuo_locport)
00635 {
00636 continue;
00637 }
00638 if ((flags & NWUO_ACC_MASK) !=
00639 (new_flags & NWUO_ACC_MASK))
00640 {
00641 DBLOCK(1, printf(
00642 "address inuse: new fd= %d, old_fd= %d, port= %u\n",
00643 udp_fd-udp_fd_table,
00644 fd_ptr-udp_fd_table,
00645 newopt.nwuo_locport));
00646
00647 reply_thr_get(udp_fd, EADDRINUSE, TRUE);
00648 return NW_OK;
00649 }
00650 }
00651 }
00652
00653 if (udp_fd->uf_flags & UFF_OPTSET)
00654 unhash_fd(udp_fd);
00655
00656 newopt.nwuo_flags= new_flags;
00657 udp_fd->uf_udpopt= newopt;
00658
00659 all_flags= new_en_flags | new_di_flags;
00660 if ((all_flags & NWUO_ACC_MASK) && (all_flags & NWUO_LOCPORT_MASK) &&
00661 (all_flags & NWUO_LOCADDR_MASK) &&
00662 (all_flags & NWUO_BROAD_MASK) &&
00663 (all_flags & NWUO_REMPORT_MASK) &&
00664 (all_flags & NWUO_REMADDR_MASK) &&
00665 (all_flags & NWUO_RW_MASK) &&
00666 (all_flags & NWUO_IPOPT_MASK))
00667 udp_fd->uf_flags |= UFF_OPTSET;
00668 else
00669 {
00670 udp_fd->uf_flags &= ~UFF_OPTSET;
00671 }
00672
00673 if (udp_fd->uf_flags & UFF_OPTSET)
00674 hash_fd(udp_fd);
00675
00676 reply_thr_get(udp_fd, NW_OK, TRUE);
00677 return NW_OK;
00678 }
00679
00680 PRIVATE udpport_t find_unused_port(fd)
00681 int fd;
00682 {
00683 udpport_t port, nw_port;
00684
00685 for (port= 0x8000+fd; port < 0xffff-UDP_FD_NR; port+= UDP_FD_NR)
00686 {
00687 nw_port= htons(port);
00688 if (is_unused_port(nw_port))
00689 return nw_port;
00690 }
00691 for (port= 0x8000; port < 0xffff; port++)
00692 {
00693 nw_port= htons(port);
00694 if (is_unused_port(nw_port))
00695 return nw_port;
00696 }
00697 ip_panic(( "unable to find unused port (shouldn't occur)" ));
00698 return 0;
00699 }
00700
00701
00702
00703
00704
00705 PRIVATE void reply_thr_put(udp_fd, reply, for_ioctl)
00706 udp_fd_t *udp_fd;
00707 int reply;
00708 int for_ioctl;
00709 {
00710 int result;
00711
00712 result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd, reply,
00713 (acc_t *)0, for_ioctl);
00714 assert(result == NW_OK);
00715 }
00716
00717
00718
00719
00720
00721 PRIVATE void reply_thr_get(udp_fd, reply, for_ioctl)
00722 udp_fd_t *udp_fd;
00723 int reply;
00724 int for_ioctl;
00725 {
00726 acc_t *result;
00727 result= (*udp_fd->uf_get_userdata)(udp_fd->uf_srfd, reply,
00728 (size_t)0, for_ioctl);
00729 assert (!result);
00730 }
00731
00732 PRIVATE int is_unused_port(port)
00733 udpport_t port;
00734 {
00735 int i;
00736 udp_fd_t *udp_fd;
00737
00738 for (i= 0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++,
00739 udp_fd++)
00740 {
00741 if (!(udp_fd->uf_flags & UFF_OPTSET))
00742 continue;
00743 if (udp_fd->uf_udpopt.nwuo_locport == port)
00744 return FALSE;
00745 }
00746 return TRUE;
00747 }
00748
00749 PRIVATE void read_ip_packets(udp_port)
00750 udp_port_t *udp_port;
00751 {
00752 int result;
00753
00754 do
00755 {
00756 udp_port->up_flags |= UPF_READ_IP;
00757 result= ip_read(udp_port->up_ipfd, UDP_MAX_DATAGRAM);
00758 if (result == NW_SUSPEND)
00759 {
00760 udp_port->up_flags |= UPF_READ_SP;
00761 return;
00762 }
00763 assert(result == NW_OK);
00764 udp_port->up_flags &= ~UPF_READ_IP;
00765 } while(!(udp_port->up_flags & UPF_READ_IP));
00766 }
00767
00768
00769 PRIVATE int udp_peek (udp_fd)
00770 udp_fd_t *udp_fd;
00771 {
00772 acc_t *pack, *tmp_acc, *next_acc;
00773 int result;
00774
00775 if (!(udp_fd->uf_flags & UFF_OPTSET))
00776 {
00777 udp_fd->uf_flags &= ~UFF_IOCTL_IP;
00778 reply_thr_put(udp_fd, EBADMODE, TRUE);
00779 return NW_OK;
00780 }
00781
00782 if (udp_fd->uf_rdbuf_head)
00783 {
00784 if (get_time() <= udp_fd->uf_exp_tim)
00785 {
00786 pack= bf_cut(udp_fd->uf_rdbuf_head, 0,
00787 sizeof(udp_io_hdr_t));
00788 result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd,
00789 (size_t)0, pack, TRUE);
00790
00791 udp_fd->uf_flags &= ~UFF_IOCTL_IP;
00792 result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd,
00793 result, (acc_t *)0, TRUE);
00794 assert (result == 0);
00795 return result;
00796 }
00797 tmp_acc= udp_fd->uf_rdbuf_head;
00798 while (tmp_acc)
00799 {
00800 next_acc= tmp_acc->acc_ext_link;
00801 bf_afree(tmp_acc);
00802 tmp_acc= next_acc;
00803 }
00804 udp_fd->uf_rdbuf_head= NULL;
00805 }
00806 udp_fd->uf_flags |= UFF_PEEK_IP;
00807 return NW_SUSPEND;
00808 }
00809
00810 PRIVATE int udp_sel_read (udp_fd)
00811 udp_fd_t *udp_fd;
00812 {
00813 acc_t *pack, *tmp_acc, *next_acc;
00814 int result;
00815
00816 if (!(udp_fd->uf_flags & UFF_OPTSET))
00817 return 1;
00818
00819 if (udp_fd->uf_rdbuf_head)
00820 {
00821 if (get_time() <= udp_fd->uf_exp_tim)
00822 return 1;
00823
00824 tmp_acc= udp_fd->uf_rdbuf_head;
00825 while (tmp_acc)
00826 {
00827 next_acc= tmp_acc->acc_ext_link;
00828 bf_afree(tmp_acc);
00829 tmp_acc= next_acc;
00830 }
00831 udp_fd->uf_rdbuf_head= NULL;
00832 }
00833 return 0;
00834 }
00835
00836 PRIVATE int udp_packet2user (udp_fd)
00837 udp_fd_t *udp_fd;
00838 {
00839 acc_t *pack, *tmp_pack;
00840 udp_io_hdr_t *hdr;
00841 int result, hdr_len;
00842 size_t size, transf_size;
00843
00844 pack= udp_fd->uf_rdbuf_head;
00845 udp_fd->uf_rdbuf_head= pack->acc_ext_link;
00846
00847 size= bf_bufsize (pack);
00848
00849 if (udp_fd->uf_udpopt.nwuo_flags & NWUO_RWDATONLY)
00850 {
00851
00852 pack= bf_packIffLess (pack, UDP_IO_HDR_SIZE);
00853 assert (pack->acc_length >= UDP_IO_HDR_SIZE);
00854
00855 hdr= (udp_io_hdr_t *)ptr2acc_data(pack);
00856 #if CONF_UDP_IO_NW_BYTE_ORDER
00857 hdr_len= UDP_IO_HDR_SIZE+NTOHS(hdr->uih_ip_opt_len);
00858 #else
00859 hdr_len= UDP_IO_HDR_SIZE+hdr->uih_ip_opt_len;
00860 #endif
00861
00862 assert (size>= hdr_len);
00863 size -= hdr_len;
00864 tmp_pack= bf_cut(pack, hdr_len, size);
00865 bf_afree(pack);
00866 pack= tmp_pack;
00867 }
00868
00869 if (size>udp_fd->uf_rd_count)
00870 {
00871 tmp_pack= bf_cut (pack, 0, udp_fd->uf_rd_count);
00872 bf_afree(pack);
00873 pack= tmp_pack;
00874 transf_size= udp_fd->uf_rd_count;
00875 }
00876 else
00877 transf_size= size;
00878
00879 result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd,
00880 (size_t)0, pack, FALSE);
00881
00882 if (result >= 0)
00883 if (size > transf_size)
00884 result= EPACKSIZE;
00885 else
00886 result= transf_size;
00887
00888 udp_fd->uf_flags &= ~UFF_READ_IP;
00889 result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd, result,
00890 (acc_t *)0, FALSE);
00891 assert (result == 0);
00892
00893 return result;
00894 }
00895
00896 PRIVATE void udp_ip_arrived(port, pack, pack_size)
00897 int port;
00898 acc_t *pack;
00899 size_t pack_size;
00900 {
00901 udp_port_t *udp_port;
00902 udp_fd_t *udp_fd, *share_fd;
00903 acc_t *ip_hdr_acc, *udp_acc, *ipopt_pack, *no_ipopt_pack, *tmp_acc;
00904 ip_hdr_t *ip_hdr;
00905 udp_hdr_t *udp_hdr;
00906 udp_io_hdr_t *udp_io_hdr;
00907 size_t ip_hdr_size, udp_size, data_size, opt_size;
00908 ipaddr_t src_addr, dst_addr, ipaddr;
00909 udpport_t src_port, dst_port;
00910 u8_t u16[2];
00911 u16_t chksum;
00912 unsigned long dst_type, flags;
00913 clock_t exp_tim;
00914 int i, delivered, hash;
00915
00916 udp_port= &udp_port_table[port];
00917
00918 ip_hdr_acc= bf_cut(pack, 0, IP_MIN_HDR_SIZE);
00919 ip_hdr_acc= bf_packIffLess(ip_hdr_acc, IP_MIN_HDR_SIZE);
00920 ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_hdr_acc);
00921 ip_hdr_size= (ip_hdr->ih_vers_ihl & IH_IHL_MASK) << 2;
00922 if (ip_hdr_size != IP_MIN_HDR_SIZE)
00923 {
00924 bf_afree(ip_hdr_acc);
00925 ip_hdr_acc= bf_cut(pack, 0, ip_hdr_size);
00926 ip_hdr_acc= bf_packIffLess(ip_hdr_acc, ip_hdr_size);
00927 ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_hdr_acc);
00928 }
00929
00930 pack_size -= ip_hdr_size;
00931 if (pack_size < UDP_HDR_SIZE)
00932 {
00933 if (pack_size == 0 && ip_hdr->ih_proto == 0)
00934 {
00935
00936 ipaddr= ip_hdr->ih_src;
00937 udp_port->up_ipaddr= ipaddr;
00938 DBLOCK(1, printf("udp_ip_arrived: using address ");
00939 writeIpAddr(ipaddr); printf("\n"));
00940 }
00941 else
00942 DBLOCK(1, printf("packet too small\n"));
00943
00944 bf_afree(ip_hdr_acc);
00945 bf_afree(pack);
00946 return;
00947 }
00948
00949 udp_acc= bf_delhead(pack, ip_hdr_size);
00950 pack= NULL;
00951
00952
00953 udp_acc= bf_packIffLess(udp_acc, UDP_HDR_SIZE);
00954 udp_hdr= (udp_hdr_t *)ptr2acc_data(udp_acc);
00955 udp_size= ntohs(udp_hdr->uh_length);
00956 if (udp_size > pack_size)
00957 {
00958 DBLOCK(1, printf("packet too large\n"));
00959
00960 bf_afree(ip_hdr_acc);
00961 bf_afree(udp_acc);
00962 return;
00963 }
00964
00965 src_addr= ip_hdr->ih_src;
00966 dst_addr= ip_hdr->ih_dst;
00967
00968 if (udp_hdr->uh_chksum)
00969 {
00970 u16[0]= 0;
00971 u16[1]= ip_hdr->ih_proto;
00972 chksum= pack_oneCsum(udp_acc);
00973 chksum= oneC_sum(chksum, (u16_t *)&src_addr, sizeof(ipaddr_t));
00974 chksum= oneC_sum(chksum, (u16_t *)&dst_addr, sizeof(ipaddr_t));
00975 chksum= oneC_sum(chksum, (u16_t *)u16, sizeof(u16));
00976 chksum= oneC_sum(chksum, (u16_t *)&udp_hdr->uh_length,
00977 sizeof(udp_hdr->uh_length));
00978 if (~chksum & 0xffff)
00979 {
00980 DBLOCK(1, printf("checksum error in udp packet\n");
00981 printf("src ip_addr= ");
00982 writeIpAddr(src_addr);
00983 printf(" dst ip_addr= ");
00984 writeIpAddr(dst_addr);
00985 printf("\n");
00986 printf("packet chksum= 0x%x, sum= 0x%x\n",
00987 udp_hdr->uh_chksum, chksum));
00988
00989 bf_afree(ip_hdr_acc);
00990 bf_afree(udp_acc);
00991 return;
00992 }
00993 }
00994
00995 exp_tim= get_time() + UDP_READ_EXP_TIME;
00996 src_port= udp_hdr->uh_src_port;
00997 dst_port= udp_hdr->uh_dst_port;
00998
00999
01000
01001
01002 delivered= 0;
01003
01004 if (dst_addr == udp_port->up_ipaddr)
01005 dst_type= NWUO_EN_LOC;
01006 else
01007 {
01008 dst_type= NWUO_EN_BROAD;
01009
01010
01011 delivered= 1;
01012 }
01013
01014 DBLOCK(0x20, printf("udp: got packet from ");
01015 writeIpAddr(src_addr);
01016 printf(".%u to ", ntohs(src_port));
01017 writeIpAddr(dst_addr);
01018 printf(".%u\n", ntohs(dst_port)));
01019
01020 no_ipopt_pack= bf_memreq(UDP_IO_HDR_SIZE);
01021 udp_io_hdr= (udp_io_hdr_t *)ptr2acc_data(no_ipopt_pack);
01022 udp_io_hdr->uih_src_addr= src_addr;
01023 udp_io_hdr->uih_dst_addr= dst_addr;
01024 udp_io_hdr->uih_src_port= src_port;
01025 udp_io_hdr->uih_dst_port= dst_port;
01026 data_size = udp_size-UDP_HDR_SIZE;
01027 #if CONF_UDP_IO_NW_BYTE_ORDER
01028 udp_io_hdr->uih_ip_opt_len= HTONS(0);
01029 udp_io_hdr->uih_data_len= htons(data_size);
01030 #else
01031 udp_io_hdr->uih_ip_opt_len= 0;
01032 udp_io_hdr->uih_data_len= data_size;
01033 #endif
01034 no_ipopt_pack->acc_next= bf_cut(udp_acc, UDP_HDR_SIZE, data_size);
01035
01036 if (ip_hdr_size == IP_MIN_HDR_SIZE)
01037 {
01038 ipopt_pack= no_ipopt_pack;
01039 ipopt_pack->acc_linkC++;
01040 }
01041 else
01042 {
01043 ipopt_pack= bf_memreq(UDP_IO_HDR_SIZE);
01044 *(udp_io_hdr_t *)ptr2acc_data(ipopt_pack)= *udp_io_hdr;
01045 udp_io_hdr= (udp_io_hdr_t *)ptr2acc_data(ipopt_pack);
01046 opt_size = ip_hdr_size-IP_MIN_HDR_SIZE;
01047 #if CONF_UDP_IO_NW_BYTE_ORDER
01048 udp_io_hdr->uih_ip_opt_len= htons(opt_size);
01049 #else
01050 udp_io_hdr->uih_ip_opt_len= opt_size;
01051 #endif
01052 tmp_acc= bf_cut(ip_hdr_acc, (size_t)IP_MIN_HDR_SIZE, opt_size);
01053 assert(tmp_acc->acc_linkC == 1);
01054 assert(tmp_acc->acc_next == NULL);
01055 ipopt_pack->acc_next= tmp_acc;
01056
01057 tmp_acc->acc_next= no_ipopt_pack->acc_next;
01058 if (tmp_acc->acc_next)
01059 tmp_acc->acc_next->acc_linkC++;
01060 }
01061
01062 hash= dst_port;
01063 hash ^= (hash >> 8);
01064 hash &= (UDP_PORT_HASH_NR-1);
01065
01066 for (i= 0; i<2; i++)
01067 {
01068 share_fd= NULL;
01069
01070 udp_fd= (i == 0) ? udp_port->up_port_any :
01071 udp_port->up_port_hash[hash];
01072 for (; udp_fd; udp_fd= udp_fd->uf_port_next)
01073 {
01074 if (i && udp_fd->uf_udpopt.nwuo_locport != dst_port)
01075 continue;
01076
01077 assert(udp_fd->uf_flags & UFF_INUSE);
01078 assert(udp_fd->uf_flags & UFF_OPTSET);
01079
01080 if (udp_fd->uf_port != udp_port)
01081 continue;
01082
01083 flags= udp_fd->uf_udpopt.nwuo_flags;
01084 if (!(flags & dst_type))
01085 continue;
01086
01087 if ((flags & NWUO_RP_SET) &&
01088 udp_fd->uf_udpopt.nwuo_remport != src_port)
01089 {
01090 continue;
01091 }
01092
01093 if ((flags & NWUO_RA_SET) &&
01094 udp_fd->uf_udpopt.nwuo_remaddr != src_addr)
01095 {
01096 continue;
01097 }
01098
01099 if (i)
01100 {
01101
01102 delivered= 1;
01103 }
01104
01105 if ((flags & NWUO_ACC_MASK) == NWUO_SHARED &&
01106 (!share_fd || !udp_fd->uf_rdbuf_head))
01107 {
01108 share_fd= udp_fd;
01109 continue;
01110 }
01111
01112 if (flags & NWUO_EN_IPOPT)
01113 pack= ipopt_pack;
01114 else
01115 pack= no_ipopt_pack;
01116
01117 pack->acc_linkC++;
01118 udp_rd_enqueue(udp_fd, pack, exp_tim);
01119 if (udp_fd->uf_flags & UFF_READ_IP)
01120 udp_packet2user(udp_fd);
01121 }
01122
01123 if (share_fd)
01124 {
01125 flags= share_fd->uf_udpopt.nwuo_flags;
01126 if (flags & NWUO_EN_IPOPT)
01127 pack= ipopt_pack;
01128 else
01129 pack= no_ipopt_pack;
01130
01131 pack->acc_linkC++;
01132 udp_rd_enqueue(share_fd, pack, exp_tim);
01133 if (share_fd->uf_flags & UFF_READ_IP)
01134 udp_packet2user(share_fd);
01135 }
01136 }
01137
01138 if (ipopt_pack)
01139 bf_afree(ipopt_pack);
01140 if (no_ipopt_pack)
01141 bf_afree(no_ipopt_pack);
01142
01143 if (!delivered)
01144 {
01145 DBLOCK(0x2, printf("udp: could not deliver packet from ");
01146 writeIpAddr(src_addr);
01147 printf(".%u to ", ntohs(src_port));
01148 writeIpAddr(dst_addr);
01149 printf(".%u\n", ntohs(dst_port)));
01150
01151 pack= bf_append(ip_hdr_acc, udp_acc);
01152 ip_hdr_acc= NULL;
01153 udp_acc= NULL;
01154 icmp_snd_unreachable(udp_port->up_ipdev, pack,
01155 ICMP_PORT_UNRCH);
01156 return;
01157 }
01158
01159 assert (ip_hdr_acc);
01160 bf_afree(ip_hdr_acc);
01161 assert (udp_acc);
01162 bf_afree(udp_acc);
01163 }
01164
01165 PUBLIC void udp_close(fd)
01166 int fd;
01167 {
01168 udp_fd_t *udp_fd;
01169 acc_t *tmp_acc, *next_acc;
01170
01171 udp_fd= &udp_fd_table[fd];
01172
01173 assert (udp_fd->uf_flags & UFF_INUSE);
01174
01175 if (udp_fd->uf_flags & UFF_OPTSET)
01176 unhash_fd(udp_fd);
01177
01178 udp_fd->uf_flags= UFF_EMPTY;
01179 tmp_acc= udp_fd->uf_rdbuf_head;
01180 while (tmp_acc)
01181 {
01182 next_acc= tmp_acc->acc_ext_link;
01183 bf_afree(tmp_acc);
01184 tmp_acc= next_acc;
01185 }
01186 udp_fd->uf_rdbuf_head= NULL;
01187 }
01188
01189 PUBLIC int udp_write(fd, count)
01190 int fd;
01191 size_t count;
01192 {
01193 udp_fd_t *udp_fd;
01194 udp_port_t *udp_port;
01195
01196 udp_fd= &udp_fd_table[fd];
01197 udp_port= udp_fd->uf_port;
01198
01199 if (!(udp_fd->uf_flags & UFF_OPTSET))
01200 {
01201 reply_thr_get (udp_fd, EBADMODE, FALSE);
01202 return NW_OK;
01203 }
01204
01205 assert (!(udp_fd->uf_flags & UFF_WRITE_IP));
01206
01207 udp_fd->uf_wr_count= count;
01208
01209 udp_fd->uf_flags |= UFF_WRITE_IP;
01210
01211 restart_write_fd(udp_fd);
01212
01213 if (udp_fd->uf_flags & UFF_WRITE_IP)
01214 {
01215 DBLOCK(1, printf("replying NW_SUSPEND\n"));
01216
01217 return NW_SUSPEND;
01218 }
01219 else
01220 {
01221 return NW_OK;
01222 }
01223 }
01224
01225 PRIVATE void restart_write_fd(udp_fd)
01226 udp_fd_t *udp_fd;
01227 {
01228 udp_port_t *udp_port;
01229 acc_t *pack, *ip_hdr_pack, *udp_hdr_pack, *ip_opt_pack, *user_data;
01230 udp_hdr_t *udp_hdr;
01231 udp_io_hdr_t *udp_io_hdr;
01232 ip_hdr_t *ip_hdr;
01233 size_t ip_opt_size, user_data_size;
01234 unsigned long flags;
01235 u16_t chksum;
01236 u8_t u16[2];
01237 int result;
01238
01239 udp_port= udp_fd->uf_port;
01240
01241 if (udp_port->up_flags & UPF_WRITE_IP)
01242 {
01243 udp_port->up_flags |= UPF_MORE2WRITE;
01244 return;
01245 }
01246
01247 assert (udp_fd->uf_flags & UFF_WRITE_IP);
01248 udp_fd->uf_flags &= ~UFF_WRITE_IP;
01249
01250 assert (!udp_port->up_wr_pack);
01251
01252 pack= (*udp_fd->uf_get_userdata)(udp_fd->uf_srfd, 0,
01253 udp_fd->uf_wr_count, FALSE);
01254 if (!pack)
01255 {
01256 udp_fd->uf_flags &= ~UFF_WRITE_IP;
01257 reply_thr_get (udp_fd, EFAULT, FALSE);
01258 return;
01259 }
01260
01261 flags= udp_fd->uf_udpopt.nwuo_flags;
01262
01263 ip_hdr_pack= bf_memreq(IP_MIN_HDR_SIZE);
01264 ip_hdr= (ip_hdr_t *)ptr2acc_data(ip_hdr_pack);
01265
01266 udp_hdr_pack= bf_memreq(UDP_HDR_SIZE);
01267 udp_hdr= (udp_hdr_t *)ptr2acc_data(udp_hdr_pack);
01268
01269 if (flags & NWUO_RWDATALL)
01270 {
01271 pack= bf_packIffLess(pack, UDP_IO_HDR_SIZE);
01272 udp_io_hdr= (udp_io_hdr_t *)ptr2acc_data(pack);
01273 #if CONF_UDP_IO_NW_BYTE_ORDER
01274 ip_opt_size= ntohs(udp_io_hdr->uih_ip_opt_len);
01275 #else
01276 ip_opt_size= udp_io_hdr->uih_ip_opt_len;
01277 #endif
01278 if (UDP_IO_HDR_SIZE+ip_opt_size>udp_fd->uf_wr_count)
01279 {
01280 bf_afree(ip_hdr_pack);
01281 bf_afree(udp_hdr_pack);
01282 bf_afree(pack);
01283 reply_thr_get (udp_fd, EINVAL, FALSE);
01284 return;
01285 }
01286 if (ip_opt_size & 3)
01287 {
01288 bf_afree(ip_hdr_pack);
01289 bf_afree(udp_hdr_pack);
01290 bf_afree(pack);
01291 reply_thr_get (udp_fd, EFAULT, FALSE);
01292 return;
01293 }
01294 if (ip_opt_size)
01295 ip_opt_pack= bf_cut(pack, UDP_IO_HDR_SIZE, ip_opt_size);
01296 else
01297 ip_opt_pack= 0;
01298 user_data_size= udp_fd->uf_wr_count-UDP_IO_HDR_SIZE-
01299 ip_opt_size;
01300 user_data= bf_cut(pack, UDP_IO_HDR_SIZE+ip_opt_size,
01301 user_data_size);
01302 bf_afree(pack);
01303 }
01304 else
01305 {
01306 udp_io_hdr= 0;
01307 ip_opt_size= 0;
01308 user_data_size= udp_fd->uf_wr_count;
01309 ip_opt_pack= 0;
01310 user_data= pack;
01311 }
01312
01313 ip_hdr->ih_vers_ihl= (IP_MIN_HDR_SIZE+ip_opt_size) >> 2;
01314 ip_hdr->ih_tos= UDP_TOS;
01315 ip_hdr->ih_flags_fragoff= HTONS(UDP_IP_FLAGS);
01316 ip_hdr->ih_ttl= IP_DEF_TTL;
01317 ip_hdr->ih_proto= IPPROTO_UDP;
01318 if (flags & NWUO_RA_SET)
01319 {
01320 ip_hdr->ih_dst= udp_fd->uf_udpopt.nwuo_remaddr;
01321 }
01322 else
01323 {
01324 assert (udp_io_hdr);
01325 ip_hdr->ih_dst= udp_io_hdr->uih_dst_addr;
01326 }
01327
01328 if ((flags & NWUO_LOCPORT_MASK) != NWUO_LP_ANY)
01329 udp_hdr->uh_src_port= udp_fd->uf_udpopt.nwuo_locport;
01330 else
01331 {
01332 assert (udp_io_hdr);
01333 udp_hdr->uh_src_port= udp_io_hdr->uih_src_port;
01334 }
01335
01336 if (flags & NWUO_RP_SET)
01337 udp_hdr->uh_dst_port= udp_fd->uf_udpopt.nwuo_remport;
01338 else
01339 {
01340 assert (udp_io_hdr);
01341 udp_hdr->uh_dst_port= udp_io_hdr->uih_dst_port;
01342 }
01343
01344 udp_hdr->uh_length= htons(UDP_HDR_SIZE+user_data_size);
01345 udp_hdr->uh_chksum= 0;
01346
01347 udp_hdr_pack->acc_next= user_data;
01348 chksum= pack_oneCsum(udp_hdr_pack);
01349 chksum= oneC_sum(chksum, (u16_t *)&udp_fd->uf_port->up_ipaddr,
01350 sizeof(ipaddr_t));
01351 chksum= oneC_sum(chksum, (u16_t *)&ip_hdr->ih_dst, sizeof(ipaddr_t));
01352 u16[0]= 0;
01353 u16[1]= IPPROTO_UDP;
01354 chksum= oneC_sum(chksum, (u16_t *)u16, sizeof(u16));
01355 chksum= oneC_sum(chksum, (u16_t *)&udp_hdr->uh_length, sizeof(u16_t));
01356 if (~chksum)
01357 chksum= ~chksum;
01358 udp_hdr->uh_chksum= chksum;
01359
01360 if (ip_opt_pack)
01361 {
01362 ip_opt_pack= bf_packIffLess(ip_opt_pack, ip_opt_size);
01363 ip_opt_pack->acc_next= udp_hdr_pack;
01364 udp_hdr_pack= ip_opt_pack;
01365 }
01366 ip_hdr_pack->acc_next= udp_hdr_pack;
01367
01368 assert (!udp_port->up_wr_pack);
01369 assert (!(udp_port->up_flags & UPF_WRITE_IP));
01370
01371 udp_port->up_wr_pack= ip_hdr_pack;
01372 udp_port->up_flags |= UPF_WRITE_IP;
01373 result= ip_write(udp_port->up_ipfd, bf_bufsize(ip_hdr_pack));
01374 if (result == NW_SUSPEND)
01375 {
01376 udp_port->up_flags |= UPF_WRITE_SP;
01377 udp_fd->uf_flags |= UFF_WRITE_IP;
01378 udp_port->up_write_fd= udp_fd;
01379 }
01380 else if (result<0)
01381 reply_thr_get(udp_fd, result, FALSE);
01382 else
01383 reply_thr_get (udp_fd, udp_fd->uf_wr_count, FALSE);
01384 }
01385
01386 PRIVATE u16_t pack_oneCsum(pack)
01387 acc_t *pack;
01388 {
01389 u16_t prev;
01390 int odd_byte;
01391 char *data_ptr;
01392 int length;
01393 char byte_buf[2];
01394
01395 assert (pack);
01396
01397 prev= 0;
01398
01399 odd_byte= FALSE;
01400 for (; pack; pack= pack->acc_next)
01401 {
01402
01403 data_ptr= ptr2acc_data(pack);
01404 length= pack->acc_length;
01405
01406 if (!length)
01407 continue;
01408 if (odd_byte)
01409 {
01410 byte_buf[1]= *data_ptr;
01411 prev= oneC_sum(prev, (u16_t *)byte_buf, 2);
01412 data_ptr++;
01413 length--;
01414 odd_byte= FALSE;
01415 }
01416 if (length & 1)
01417 {
01418 odd_byte= TRUE;
01419 length--;
01420 byte_buf[0]= data_ptr[length];
01421 }
01422 if (!length)
01423 continue;
01424 prev= oneC_sum (prev, (u16_t *)data_ptr, length);
01425 }
01426 if (odd_byte)
01427 {
01428 byte_buf[1]= 0;
01429 prev= oneC_sum (prev, (u16_t *)byte_buf, 1);
01430 }
01431 return prev;
01432 }
01433
01434 PRIVATE void udp_restart_write_port(udp_port )
01435 udp_port_t *udp_port;
01436 {
01437 udp_fd_t *udp_fd;
01438 int i;
01439
01440 assert (!udp_port->up_wr_pack);
01441 assert (!(udp_port->up_flags & (UPF_WRITE_IP|UPF_WRITE_SP)));
01442
01443 while (udp_port->up_flags & UPF_MORE2WRITE)
01444 {
01445 udp_port->up_flags &= ~UPF_MORE2WRITE;
01446
01447 for (i= 0, udp_fd= udp_port->up_next_fd; i<UDP_FD_NR;
01448 i++, udp_fd++)
01449 {
01450 if (udp_fd == &udp_fd_table[UDP_FD_NR])
01451 udp_fd= udp_fd_table;
01452
01453 if (!(udp_fd->uf_flags & UFF_INUSE))
01454 continue;
01455 if (!(udp_fd->uf_flags & UFF_WRITE_IP))
01456 continue;
01457 if (udp_fd->uf_port != udp_port)
01458 continue;
01459 restart_write_fd(udp_fd);
01460 if (udp_port->up_flags & UPF_WRITE_IP)
01461 {
01462 udp_port->up_next_fd= udp_fd+1;
01463 udp_port->up_flags |= UPF_MORE2WRITE;
01464 return;
01465 }
01466 }
01467 }
01468 }
01469
01470 PUBLIC int udp_cancel(fd, which_operation)
01471 int fd;
01472 int which_operation;
01473 {
01474 udp_fd_t *udp_fd;
01475
01476 DBLOCK(0x10, printf("udp_cancel(%d, %d)\n", fd, which_operation));
01477
01478 udp_fd= &udp_fd_table[fd];
01479
01480 switch (which_operation)
01481 {
01482 case SR_CANCEL_READ:
01483 assert (udp_fd->uf_flags & UFF_READ_IP);
01484 udp_fd->uf_flags &= ~UFF_READ_IP;
01485 reply_thr_put(udp_fd, EINTR, FALSE);
01486 break;
01487 case SR_CANCEL_WRITE:
01488 assert (udp_fd->uf_flags & UFF_WRITE_IP);
01489 udp_fd->uf_flags &= ~UFF_WRITE_IP;
01490 if (udp_fd->uf_port->up_write_fd == udp_fd)
01491 udp_fd->uf_port->up_write_fd= NULL;
01492 reply_thr_get(udp_fd, EINTR, FALSE);
01493 break;
01494 case SR_CANCEL_IOCTL:
01495 assert (udp_fd->uf_flags & UFF_IOCTL_IP);
01496 udp_fd->uf_flags &= ~UFF_IOCTL_IP;
01497 udp_fd->uf_flags &= ~UFF_PEEK_IP;
01498 reply_thr_get(udp_fd, EINTR, TRUE);
01499 break;
01500 default:
01501 ip_panic(( "got unknown cancel request" ));
01502 }
01503 return NW_OK;
01504 }
01505
01506 PRIVATE void udp_buffree (priority)
01507 int priority;
01508 {
01509 int i;
01510 udp_fd_t *udp_fd;
01511 acc_t *tmp_acc;
01512
01513 if (priority == UDP_PRI_FDBUFS_EXTRA)
01514 {
01515 for (i=0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++, udp_fd++)
01516 {
01517 while (udp_fd->uf_rdbuf_head &&
01518 udp_fd->uf_rdbuf_head->acc_ext_link)
01519 {
01520 tmp_acc= udp_fd->uf_rdbuf_head;
01521 udp_fd->uf_rdbuf_head= tmp_acc->acc_ext_link;
01522 bf_afree(tmp_acc);
01523 }
01524 }
01525 }
01526
01527 if (priority == UDP_PRI_FDBUFS)
01528 {
01529 for (i=0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++, udp_fd++)
01530 {
01531 while (udp_fd->uf_rdbuf_head)
01532 {
01533 tmp_acc= udp_fd->uf_rdbuf_head;
01534 udp_fd->uf_rdbuf_head= tmp_acc->acc_ext_link;
01535 bf_afree(tmp_acc);
01536 }
01537 }
01538 }
01539 }
01540
01541 PRIVATE void udp_rd_enqueue(udp_fd, pack, exp_tim)
01542 udp_fd_t *udp_fd;
01543 acc_t *pack;
01544 clock_t exp_tim;
01545 {
01546 acc_t *tmp_acc;
01547 int result;
01548
01549 if (pack->acc_linkC != 1)
01550 {
01551 tmp_acc= bf_dupacc(pack);
01552 bf_afree(pack);
01553 pack= tmp_acc;
01554 }
01555 pack->acc_ext_link= NULL;
01556 if (udp_fd->uf_rdbuf_head == NULL)
01557 {
01558 udp_fd->uf_exp_tim= exp_tim;
01559 udp_fd->uf_rdbuf_head= pack;
01560 }
01561 else
01562 udp_fd->uf_rdbuf_tail->acc_ext_link= pack;
01563 udp_fd->uf_rdbuf_tail= pack;
01564
01565 if (udp_fd->uf_flags & UFF_PEEK_IP)
01566 {
01567 pack= bf_cut(udp_fd->uf_rdbuf_head, 0,
01568 sizeof(udp_io_hdr_t));
01569 result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd,
01570 (size_t)0, pack, TRUE);
01571
01572 udp_fd->uf_flags &= ~UFF_IOCTL_IP;
01573 udp_fd->uf_flags &= ~UFF_PEEK_IP;
01574 result= (*udp_fd->uf_put_userdata)(udp_fd->uf_srfd,
01575 result, (acc_t *)0, TRUE);
01576 assert (result == 0);
01577 }
01578
01579 if (udp_fd->uf_flags & UFF_SEL_READ)
01580 {
01581 udp_fd->uf_flags &= ~UFF_SEL_READ;
01582 if (udp_fd->uf_select_res)
01583 udp_fd->uf_select_res(udp_fd->uf_srfd, SR_SELECT_READ);
01584 else
01585 printf("udp_rd_enqueue: no select_res\n");
01586 }
01587 }
01588
01589 PRIVATE void hash_fd(udp_fd)
01590 udp_fd_t *udp_fd;
01591 {
01592 udp_port_t *udp_port;
01593 int hash;
01594
01595 udp_port= udp_fd->uf_port;
01596 if ((udp_fd->uf_udpopt.nwuo_flags & NWUO_LOCPORT_MASK) ==
01597 NWUO_LP_ANY)
01598 {
01599 udp_fd->uf_port_next= udp_port->up_port_any;
01600 udp_port->up_port_any= udp_fd;
01601 }
01602 else
01603 {
01604 hash= udp_fd->uf_udpopt.nwuo_locport;
01605 hash ^= (hash >> 8);
01606 hash &= (UDP_PORT_HASH_NR-1);
01607
01608 udp_fd->uf_port_next= udp_port->up_port_hash[hash];
01609 udp_port->up_port_hash[hash]= udp_fd;
01610 }
01611 }
01612
01613 PRIVATE void unhash_fd(udp_fd)
01614 udp_fd_t *udp_fd;
01615 {
01616 udp_port_t *udp_port;
01617 udp_fd_t *prev, *curr, **udp_fd_p;
01618 int hash;
01619
01620 udp_port= udp_fd->uf_port;
01621 if ((udp_fd->uf_udpopt.nwuo_flags & NWUO_LOCPORT_MASK) ==
01622 NWUO_LP_ANY)
01623 {
01624 udp_fd_p= &udp_port->up_port_any;
01625 }
01626 else
01627 {
01628 hash= udp_fd->uf_udpopt.nwuo_locport;
01629 hash ^= (hash >> 8);
01630 hash &= (UDP_PORT_HASH_NR-1);
01631
01632 udp_fd_p= &udp_port->up_port_hash[hash];
01633 }
01634 for (prev= NULL, curr= *udp_fd_p; curr;
01635 prev= curr, curr= curr->uf_port_next)
01636 {
01637 if (curr == udp_fd)
01638 break;
01639 }
01640 assert(curr);
01641 if (prev)
01642 prev->uf_port_next= curr->uf_port_next;
01643 else
01644 *udp_fd_p= curr->uf_port_next;
01645 }
01646
01647 #ifdef BUF_CONSISTENCY_CHECK
01648 PRIVATE void udp_bufcheck()
01649 {
01650 int i;
01651 udp_port_t *udp_port;
01652 udp_fd_t *udp_fd;
01653 acc_t *tmp_acc;
01654
01655 for (i= 0, udp_port= udp_port_table; i<udp_conf_nr; i++, udp_port++)
01656 {
01657 if (udp_port->up_wr_pack)
01658 bf_check_acc(udp_port->up_wr_pack);
01659 }
01660
01661 for (i= 0, udp_fd= udp_fd_table; i<UDP_FD_NR; i++, udp_fd++)
01662 {
01663 for (tmp_acc= udp_fd->uf_rdbuf_head; tmp_acc;
01664 tmp_acc= tmp_acc->acc_ext_link)
01665 {
01666 bf_check_acc(tmp_acc);
01667 }
01668 }
01669 }
01670 #endif
01671
01672
01673
01674