00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #include "inet.h"
00012 #include "assert.h"
00013 #include "buf.h"
00014 #include "event.h"
00015 #include "type.h"
00016 #include "ip_int.h"
00017 #include "psip.h"
00018 #include "sr.h"
00019
00020 THIS_FILE
00021
00022 typedef struct psip_port
00023 {
00024 int pp_flags;
00025 int pp_ipdev;
00026 int pp_opencnt;
00027 struct psip_fd *pp_rd_head;
00028 struct psip_fd *pp_rd_tail;
00029 acc_t *pp_promisc_head;
00030 acc_t *pp_promisc_tail;
00031 } psip_port_t;
00032
00033 #define PPF_EMPTY 0
00034 #define PPF_CONFIGURED 1
00035 #define PPF_ENABLED 2
00036 #define PPF_PROMISC 4
00037
00038 #define PSIP_FD_NR (1*IP_PORT_MAX)
00039
00040 typedef struct psip_fd
00041 {
00042 int pf_flags;
00043 int pf_srfd;
00044 psip_port_t *pf_port;
00045 get_userdata_t pf_get_userdata;
00046 put_userdata_t pf_put_userdata;
00047 struct psip_fd *pf_rd_next;
00048 size_t pf_rd_count;
00049 nwio_psipopt_t pf_psipopt;
00050 } psip_fd_t;
00051
00052 #define PFF_EMPTY 0
00053 #define PFF_INUSE 1
00054 #define PFF_READ_IP 2
00055 #define PFF_PROMISC 4
00056 #define PFF_NEXTHOP 8
00057
00058 PRIVATE psip_port_t *psip_port_table;
00059 PRIVATE psip_fd_t psip_fd_table[PSIP_FD_NR];
00060
00061 FORWARD int psip_open ARGS(( int port, int srfd,
00062 get_userdata_t get_userdata, put_userdata_t put_userdata,
00063 put_pkt_t pkt_pkt, select_res_t select_res ));
00064 FORWARD int psip_ioctl ARGS(( int fd, ioreq_t req ));
00065 FORWARD int psip_read ARGS(( int fd, size_t count ));
00066 FORWARD int psip_write ARGS(( int fd, size_t count ));
00067 FORWARD int psip_select ARGS(( int port_nr, unsigned operations ));
00068 FORWARD void psip_close ARGS(( int fd ));
00069 FORWARD int psip_cancel ARGS(( int fd, int which_operation ));
00070 FORWARD void promisc_restart_read ARGS(( psip_port_t *psip_port ));
00071 FORWARD int psip_setopt ARGS(( psip_fd_t *psip_fd, nwio_psipopt_t *newoptp ));
00072 FORWARD void psip_buffree ARGS(( int priority ));
00073 FORWARD void check_promisc ARGS(( psip_port_t *psip_port ));
00074 #ifdef BUF_CONSISTENCY_CHECK
00075 FORWARD void psip_bufcheck ARGS(( void ));
00076 #endif
00077 FORWARD void reply_thr_put ARGS(( psip_fd_t *psip_fd, int reply,
00078 int for_ioctl ));
00079 FORWARD void reply_thr_get ARGS(( psip_fd_t *psip_fd, int reply,
00080 int for_ioctl ));
00081
00082 PUBLIC void psip_prep()
00083 {
00084 psip_port_table= alloc(psip_conf_nr * sizeof(psip_port_table[0]));
00085 }
00086
00087 PUBLIC void psip_init()
00088 {
00089 int i;
00090 psip_port_t *psip_port;
00091 psip_fd_t *psip_fd;
00092
00093 for (i=0, psip_port= psip_port_table; i<psip_conf_nr; i++, psip_port++)
00094 psip_port->pp_flags= PPF_EMPTY;
00095
00096 for (i=0, psip_fd= psip_fd_table; i<PSIP_FD_NR; i++, psip_fd++)
00097 psip_fd->pf_flags= PFF_EMPTY;
00098
00099 for (i=0, psip_port= psip_port_table; i<psip_conf_nr; i++, psip_port++)
00100 {
00101 psip_port->pp_flags |= PPF_CONFIGURED;
00102 psip_port->pp_opencnt= 0;
00103 psip_port->pp_rd_head= NULL;
00104 psip_port->pp_promisc_head= NULL;
00105 }
00106
00107 #ifndef BUF_CONSISTENCY_CHECK
00108 bf_logon(psip_buffree);
00109 #else
00110 bf_logon(psip_buffree, psip_bufcheck);
00111 #endif
00112 }
00113
00114 PUBLIC int psip_enable(port_nr, ip_port_nr)
00115 int port_nr;
00116 int ip_port_nr;
00117 {
00118 psip_port_t *psip_port;
00119
00120 assert(port_nr >= 0);
00121 if (port_nr >= psip_conf_nr)
00122 return -1;
00123
00124 psip_port= &psip_port_table[port_nr];
00125 if (!(psip_port->pp_flags &PPF_CONFIGURED))
00126 return -1;
00127
00128 psip_port->pp_ipdev= ip_port_nr;
00129 psip_port->pp_flags |= PPF_ENABLED;
00130
00131 sr_add_minor(if2minor(psip_conf[port_nr].pc_ifno, PSIP_DEV_OFF),
00132 port_nr, psip_open, psip_close, psip_read,
00133 psip_write, psip_ioctl, psip_cancel, psip_select);
00134
00135 return NW_OK;
00136 }
00137
00138 PUBLIC int psip_send(port_nr, dest, pack)
00139 int port_nr;
00140 ipaddr_t dest;
00141 acc_t *pack;
00142 {
00143 psip_port_t *psip_port;
00144 psip_fd_t *psip_fd, *mark_fd;
00145 int i, result, result1;
00146 size_t buf_size, extrasize;
00147 acc_t *hdr_pack, *acc;
00148 psip_io_hdr_t *hdr;
00149
00150 assert(port_nr >= 0 && port_nr < psip_conf_nr);
00151 psip_port= &psip_port_table[port_nr];
00152
00153 if (psip_port->pp_opencnt == 0)
00154 {
00155 bf_afree(pack);
00156 return NW_OK;
00157 }
00158
00159 for(;;)
00160 {
00161 mark_fd= psip_port->pp_rd_tail;
00162
00163 for(i= 0; i<PSIP_FD_NR; i++)
00164 {
00165 psip_fd= psip_port->pp_rd_head;
00166 if (!psip_fd)
00167 return NW_SUSPEND;
00168 psip_port->pp_rd_head= psip_fd->pf_rd_next;
00169 if (!(psip_fd->pf_flags & PFF_PROMISC))
00170 break;
00171 psip_fd->pf_rd_next= NULL;
00172 if (psip_port->pp_rd_head == NULL)
00173 psip_port->pp_rd_head= psip_fd;
00174 else
00175 psip_port->pp_rd_tail->pf_rd_next= psip_fd;
00176 psip_port->pp_rd_tail= psip_fd;
00177 if (psip_fd == mark_fd)
00178 return NW_SUSPEND;
00179 }
00180 if (i == PSIP_FD_NR)
00181 ip_panic(( "psip_send: loop" ));
00182
00183 assert(psip_fd->pf_flags & PFF_READ_IP);
00184 psip_fd->pf_flags &= ~PFF_READ_IP;
00185
00186 if (psip_fd->pf_flags & PFF_NEXTHOP)
00187 extrasize= sizeof(dest);
00188 else
00189 extrasize= 0;
00190
00191 buf_size= bf_bufsize(pack);
00192 if (buf_size+extrasize <= psip_fd->pf_rd_count)
00193 {
00194 if (psip_port->pp_flags & PPF_PROMISC)
00195 {
00196
00197 hdr_pack= bf_memreq(sizeof(*hdr));
00198 hdr= (psip_io_hdr_t *)ptr2acc_data(hdr_pack);
00199 memset(hdr, '\0', sizeof(*hdr));
00200 hdr->pih_flags |= PF_LOC2REM;
00201 hdr->pih_nexthop= dest;
00202
00203 pack->acc_linkC++;
00204 hdr_pack->acc_next= pack;
00205 hdr_pack->acc_ext_link= NULL;
00206 if (psip_port->pp_promisc_head)
00207 {
00208
00209 psip_port->pp_promisc_tail->
00210 acc_ext_link= hdr_pack;
00211 psip_port->pp_promisc_tail= hdr_pack;
00212 }
00213 else
00214 {
00215
00216 psip_port->pp_promisc_head= hdr_pack;
00217 psip_port->pp_promisc_tail= hdr_pack;
00218 if (psip_port->pp_rd_head)
00219 promisc_restart_read(psip_port);
00220 }
00221 }
00222
00223 if (extrasize)
00224 {
00225
00226 acc= bf_memreq(sizeof(dest));
00227 *(ipaddr_t *)(ptr2acc_data(acc))= dest;
00228 acc->acc_next= pack;
00229 pack= acc; acc= NULL;
00230 buf_size += extrasize;
00231 }
00232
00233 result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
00234 (size_t)0, pack, FALSE);
00235 if (result == NW_OK)
00236 result= buf_size;
00237 }
00238 else
00239 result= EPACKSIZE;
00240
00241 result1= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
00242 (size_t)result, NULL, FALSE);
00243 assert(result1 == NW_OK);
00244 if (result == EPACKSIZE)
00245 continue;
00246 return NW_OK;
00247 }
00248 return NW_SUSPEND;
00249 }
00250
00251 PRIVATE int psip_open(port, srfd, get_userdata, put_userdata, put_pkt,
00252 select_res)
00253 int port;
00254 int srfd;
00255 get_userdata_t get_userdata;
00256 put_userdata_t put_userdata;
00257 put_pkt_t put_pkt;
00258 select_res_t select_res;
00259 {
00260 psip_port_t *psip_port;
00261 psip_fd_t *psip_fd;
00262 int i;
00263
00264 assert(port >= 0 && port < psip_conf_nr);
00265 psip_port= &psip_port_table[port];
00266
00267 if (!(psip_port->pp_flags & PPF_ENABLED))
00268 return ENXIO;
00269
00270 for (i= 0, psip_fd= psip_fd_table; i<PSIP_FD_NR; i++, psip_fd++)
00271 {
00272 if (psip_fd->pf_flags & PFF_INUSE)
00273 continue;
00274 break;
00275 }
00276 if (i == PSIP_FD_NR)
00277 return ENFILE;
00278 psip_fd->pf_flags |= PFF_INUSE;
00279 psip_fd->pf_srfd= srfd;
00280 psip_fd->pf_port= psip_port;
00281 psip_fd->pf_get_userdata= get_userdata;
00282 psip_fd->pf_put_userdata= put_userdata;
00283 psip_port->pp_opencnt++;
00284
00285 return i;
00286 }
00287
00288 PRIVATE int psip_ioctl(fd, req)
00289 int fd;
00290 ioreq_t req;
00291 {
00292 int result;
00293 psip_fd_t *psip_fd;
00294 acc_t *data;
00295 nwio_ipconf_t *ipconfp;
00296 nwio_psipopt_t *psip_opt, *newoptp;
00297
00298 assert(fd >= 0 && fd < PSIP_FD_NR);
00299 psip_fd= &psip_fd_table[fd];
00300
00301 switch(req)
00302 {
00303 case NWIOSIPCONF:
00304 data= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd, 0,
00305 sizeof(*ipconfp), TRUE);
00306 if (!data)
00307 {
00308 result= EFAULT;
00309 break;
00310 }
00311 data= bf_packIffLess(data, sizeof(*ipconfp));
00312 assert (data->acc_length == sizeof(*ipconfp));
00313
00314 ipconfp= (nwio_ipconf_t *)ptr2acc_data(data);
00315 result= ip_setconf(psip_fd->pf_port->pp_ipdev, ipconfp);
00316 bf_afree(data);
00317 reply_thr_get(psip_fd, result, TRUE);
00318 break;
00319 case NWIOSPSIPOPT:
00320 data= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd, 0,
00321 sizeof(*psip_opt), TRUE);
00322 if (!data)
00323 {
00324 result= EFAULT;
00325 break;
00326 }
00327 data= bf_packIffLess(data, sizeof(*psip_opt));
00328 assert (data->acc_length == sizeof(*psip_opt));
00329
00330 newoptp= (nwio_psipopt_t *)ptr2acc_data(data);
00331 result= psip_setopt(psip_fd, newoptp);
00332 bf_afree(data);
00333 if (result == NW_OK)
00334 {
00335 if (psip_fd->pf_psipopt.nwpo_flags & NWPO_EN_PROMISC)
00336 {
00337 psip_fd->pf_flags |= PFF_PROMISC;
00338 psip_fd->pf_port->pp_flags |= PPF_PROMISC;
00339 }
00340 else
00341 {
00342 psip_fd->pf_flags &= ~PFF_PROMISC;
00343 check_promisc(psip_fd->pf_port);
00344 }
00345 if (psip_fd->pf_psipopt.nwpo_flags & NWPO_EN_NEXTHOP)
00346 {
00347 psip_fd->pf_flags |= PFF_NEXTHOP;
00348 }
00349 else
00350 {
00351 psip_fd->pf_flags &= ~PFF_NEXTHOP;
00352 }
00353 }
00354 reply_thr_get(psip_fd, result, TRUE);
00355 break;
00356 case NWIOGPSIPOPT:
00357 data= bf_memreq(sizeof(*psip_opt));
00358 psip_opt= (nwio_psipopt_t *)ptr2acc_data(data);
00359
00360 *psip_opt= psip_fd->pf_psipopt;
00361 result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd, 0,
00362 data, TRUE);
00363 if (result == NW_OK)
00364 reply_thr_put(psip_fd, NW_OK, TRUE);
00365 break;
00366 default:
00367 reply_thr_put(psip_fd, ENOTTY, TRUE);
00368 break;
00369 }
00370 return NW_OK;
00371 }
00372
00373 PRIVATE int psip_read(fd, count)
00374 int fd;
00375 size_t count;
00376 {
00377 psip_port_t *psip_port;
00378 psip_fd_t *psip_fd;
00379 acc_t *pack;
00380 size_t buf_size;
00381 int result, result1;
00382
00383 assert(fd >= 0 && fd < PSIP_FD_NR);
00384 psip_fd= &psip_fd_table[fd];
00385 psip_port= psip_fd->pf_port;
00386
00387 if ((psip_fd->pf_flags & PFF_PROMISC) && psip_port->pp_promisc_head)
00388 {
00389
00390 pack= psip_port->pp_promisc_head;
00391 buf_size= bf_bufsize(pack);
00392 if (buf_size <= count)
00393 {
00394 psip_port->pp_promisc_head= pack->acc_ext_link;
00395 result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
00396 (size_t)0, pack, FALSE);
00397 if (result == NW_OK)
00398 result= buf_size;
00399 }
00400 else
00401 result= EPACKSIZE;
00402
00403 result1= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
00404 (size_t)result, NULL, FALSE);
00405 assert(result1 == NW_OK);
00406 return NW_OK;
00407 }
00408
00409 psip_fd->pf_rd_count= count;
00410 if (psip_port->pp_rd_head == NULL)
00411 psip_port->pp_rd_head= psip_fd;
00412 else
00413 psip_port->pp_rd_tail->pf_rd_next= psip_fd;
00414 psip_fd->pf_rd_next= NULL;
00415 psip_port->pp_rd_tail= psip_fd;
00416
00417 psip_fd->pf_flags |= PFF_READ_IP;
00418 if (!(psip_fd->pf_flags & PFF_PROMISC))
00419 ipps_get(psip_port->pp_ipdev);
00420 if (psip_fd->pf_flags & PFF_READ_IP)
00421 return NW_SUSPEND;
00422 return NW_OK;
00423 }
00424
00425 PRIVATE int psip_write(fd, count)
00426 int fd;
00427 size_t count;
00428 {
00429 psip_port_t *psip_port;
00430 psip_fd_t *psip_fd;
00431 acc_t *pack, *hdr_pack;
00432 psip_io_hdr_t *hdr;
00433 size_t pack_len;
00434 ipaddr_t nexthop;
00435
00436 assert(fd >= 0 && fd < PSIP_FD_NR);
00437 psip_fd= &psip_fd_table[fd];
00438 psip_port= psip_fd->pf_port;
00439
00440 pack= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd, (size_t)0,
00441 count, FALSE);
00442 if (pack == NULL)
00443 {
00444 pack= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd,
00445 (size_t)EFAULT, (size_t)0, FALSE);
00446 assert(pack == NULL);
00447 return NW_OK;
00448 }
00449
00450 if (psip_fd->pf_flags & PFF_NEXTHOP)
00451 {
00452 pack_len= bf_bufsize(pack);
00453 if (pack_len <= sizeof(nexthop))
00454 {
00455
00456 bf_afree(pack); pack= NULL;
00457 pack= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd,
00458 (size_t)EPACKSIZE, (size_t)0, FALSE);
00459 assert(pack == NULL);
00460 return NW_OK;
00461 }
00462 pack= bf_packIffLess(pack, sizeof(nexthop));
00463 nexthop= *(ipaddr_t *)ptr2acc_data(pack);
00464 pack= bf_delhead(pack, sizeof(nexthop));
00465
00466
00467 if ((nexthop & HTONL(0xE0000000)) == HTONL(0xE0000000))
00468 nexthop= HTONL(0xffffffff);
00469 }
00470 else
00471 {
00472
00473 nexthop= HTONL(0x00000000);
00474 }
00475
00476 if (psip_port->pp_flags & PPF_PROMISC)
00477 {
00478
00479 hdr_pack= bf_memreq(sizeof(*hdr));
00480 hdr= (psip_io_hdr_t *)ptr2acc_data(hdr_pack);
00481 memset(hdr, '\0', sizeof(*hdr));
00482 hdr->pih_flags |= PF_REM2LOC;
00483 hdr->pih_nexthop= nexthop;
00484
00485 pack->acc_linkC++;
00486 hdr_pack->acc_next= pack;
00487 hdr_pack->acc_ext_link= NULL;
00488 if (psip_port->pp_promisc_head)
00489 {
00490
00491 psip_port->pp_promisc_tail->acc_ext_link= hdr_pack;
00492 psip_port->pp_promisc_tail= hdr_pack;
00493 }
00494 else
00495 {
00496
00497 psip_port->pp_promisc_head= hdr_pack;
00498 psip_port->pp_promisc_tail= hdr_pack;
00499 if (psip_port->pp_rd_head)
00500 promisc_restart_read(psip_port);
00501 }
00502 }
00503 ipps_put(psip_port->pp_ipdev, nexthop, pack);
00504 pack= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd, (size_t)count,
00505 (size_t)0, FALSE);
00506 assert(pack == NULL);
00507 return NW_OK;
00508 }
00509
00510 PRIVATE int psip_select(fd, operations)
00511 int fd;
00512 unsigned operations;
00513 {
00514 printf("psip_select: not implemented\n");
00515 return 0;
00516 }
00517
00518 PRIVATE void psip_close(fd)
00519 int fd;
00520 {
00521 psip_port_t *psip_port;
00522 psip_fd_t *psip_fd;
00523
00524 assert(fd >= 0 && fd < PSIP_FD_NR);
00525 psip_fd= &psip_fd_table[fd];
00526 psip_port= psip_fd->pf_port;
00527
00528 if (psip_fd->pf_flags & PFF_PROMISC)
00529 {
00530
00531
00532 psip_fd->pf_flags &= ~PFF_PROMISC;
00533 check_promisc(psip_fd->pf_port);
00534 }
00535
00536 assert(psip_port->pp_opencnt >0);
00537 psip_port->pp_opencnt--;
00538 psip_fd->pf_flags= PFF_EMPTY;
00539 ipps_get(psip_port->pp_ipdev);
00540
00541 }
00542
00543 PRIVATE int psip_cancel(fd, which_operation)
00544 int fd;
00545 int which_operation;
00546 {
00547 psip_port_t *psip_port;
00548 psip_fd_t *psip_fd, *prev_fd, *tmp_fd;
00549 int result;
00550
00551 DBLOCK(1, printf("psip_cancel(%d, %d)\n", fd, which_operation));
00552
00553 assert(fd >= 0 && fd < PSIP_FD_NR);
00554 psip_fd= &psip_fd_table[fd];
00555 psip_port= psip_fd->pf_port;
00556
00557 switch(which_operation)
00558 {
00559 case SR_CANCEL_IOCTL:
00560 ip_panic(( "should not be here" ));
00561 case SR_CANCEL_READ:
00562 assert(psip_fd->pf_flags & PFF_READ_IP);
00563 for (prev_fd= NULL, tmp_fd= psip_port->pp_rd_head; tmp_fd;
00564 prev_fd= tmp_fd, tmp_fd= tmp_fd->pf_rd_next)
00565 {
00566 if (tmp_fd == psip_fd)
00567 break;
00568 }
00569 if (tmp_fd == NULL)
00570 ip_panic(( "unable to find to request to cancel" ));
00571 if (prev_fd == NULL)
00572 psip_port->pp_rd_head= psip_fd->pf_rd_next;
00573 else
00574 prev_fd->pf_rd_next= psip_fd->pf_rd_next;
00575 if (psip_fd->pf_rd_next == NULL)
00576 psip_port->pp_rd_tail= prev_fd;
00577 psip_fd->pf_flags &= ~PFF_READ_IP;
00578 result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
00579 (size_t)EINTR, NULL, FALSE);
00580 assert(result == NW_OK);
00581 break;
00582 case SR_CANCEL_WRITE:
00583 ip_panic(( "should not be here" ));
00584 default:
00585 ip_panic(( "invalid operation for cancel" ));
00586 }
00587 return NW_OK;
00588 }
00589
00590 PRIVATE void promisc_restart_read(psip_port)
00591 psip_port_t *psip_port;
00592 {
00593 psip_fd_t *psip_fd, *prev, *next;
00594 acc_t *pack;
00595 size_t buf_size;
00596 int result, result1;
00597
00598
00599
00600
00601 pack= psip_port->pp_promisc_head;
00602 if (!pack)
00603 return;
00604 assert(pack->acc_ext_link == NULL);
00605
00606 for(psip_fd= psip_port->pp_rd_head, prev= NULL; psip_fd;
00607 prev= psip_fd, psip_fd= psip_fd->pf_rd_next)
00608 {
00609 again:
00610 if (!(psip_fd->pf_flags & PFF_PROMISC))
00611 continue;
00612 next= psip_fd->pf_rd_next;
00613 if (prev)
00614 prev->pf_rd_next= next;
00615 else
00616 psip_port->pp_rd_head= next;
00617 if (!next)
00618 psip_port->pp_rd_tail= prev;
00619
00620 assert(psip_fd->pf_flags & PFF_READ_IP);
00621 psip_fd->pf_flags &= ~PFF_READ_IP;
00622
00623 buf_size= bf_bufsize(pack);
00624 if (buf_size <= psip_fd->pf_rd_count)
00625 {
00626 psip_port->pp_promisc_head= pack->acc_ext_link;
00627 result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
00628 (size_t)0, pack, FALSE);
00629 if (result == NW_OK)
00630 result= buf_size;
00631 }
00632 else
00633 result= EPACKSIZE;
00634
00635 result1= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
00636 (size_t)result, NULL, FALSE);
00637 assert(result1 == NW_OK);
00638
00639 if (psip_port->pp_promisc_head)
00640 {
00641
00642 assert(result == EPACKSIZE);
00643 psip_fd= psip_port->pp_rd_head;
00644 prev= NULL;
00645 goto again;
00646 }
00647 break;
00648 }
00649 }
00650
00651 PRIVATE int psip_setopt(psip_fd, newoptp)
00652 psip_fd_t *psip_fd;
00653 nwio_psipopt_t *newoptp;
00654 {
00655 nwio_psipopt_t oldopt;
00656 unsigned int new_en_flags, new_di_flags, old_en_flags, old_di_flags;
00657 unsigned long new_flags;
00658
00659 oldopt= psip_fd->pf_psipopt;
00660
00661 old_en_flags= oldopt.nwpo_flags & 0xffff;
00662 old_di_flags= (oldopt.nwpo_flags >> 16) & 0xffff;
00663
00664 new_en_flags= newoptp->nwpo_flags & 0xffff;
00665 new_di_flags= (newoptp->nwpo_flags >> 16) & 0xffff;
00666
00667 if (new_en_flags & new_di_flags)
00668 return EBADMODE;
00669
00670
00671 if (!((new_en_flags | new_di_flags) & NWPO_PROMISC_MASK))
00672 {
00673 new_en_flags |= (old_en_flags & NWPO_PROMISC_MASK);
00674 new_di_flags |= (old_di_flags & NWPO_PROMISC_MASK);
00675 }
00676
00677 new_flags= ((unsigned long)new_di_flags << 16) | new_en_flags;
00678 if ((new_flags & NWPO_EN_PROMISC) &&
00679 (psip_fd->pf_port->pp_flags & PPF_PROMISC))
00680 {
00681 printf("psip_setopt: EBUSY for port %d, flags 0x%x\n",
00682 psip_fd->pf_port - psip_port_table,
00683 psip_fd->pf_port->pp_flags);
00684
00685 return EBUSY;
00686 }
00687
00688 psip_fd->pf_psipopt= *newoptp;
00689 psip_fd->pf_psipopt.nwpo_flags= new_flags;
00690
00691 return NW_OK;
00692 }
00693
00694 PRIVATE void check_promisc(psip_port)
00695 psip_port_t *psip_port;
00696 {
00697 int i;
00698 psip_fd_t *psip_fd;
00699 acc_t *acc, *acc_next;
00700
00701
00702
00703
00704 if (!(psip_port->pp_flags & PPF_PROMISC))
00705 return;
00706
00707 psip_port->pp_flags &= ~PPF_PROMISC;
00708 for (i= 0, psip_fd= psip_fd_table; i<PSIP_FD_NR; i++, psip_fd++)
00709 {
00710 if ((psip_fd->pf_flags & (PFF_INUSE|PFF_PROMISC)) !=
00711 (PFF_INUSE|PFF_PROMISC))
00712 {
00713 continue;
00714 }
00715 if (psip_fd->pf_port != psip_port)
00716 continue;
00717 printf("check_promisc: setting PROMISC for port %d\n",
00718 psip_port-psip_port_table);
00719 psip_port->pp_flags |= PPF_PROMISC;
00720 break;
00721 }
00722 if (!(psip_port->pp_flags & PPF_PROMISC))
00723 {
00724
00725 acc= psip_port->pp_promisc_head;
00726 psip_port->pp_promisc_head= NULL;
00727 while (acc)
00728 {
00729 acc_next= acc->acc_ext_link;
00730 bf_afree(acc);
00731 acc= acc_next;
00732 }
00733 }
00734 }
00735
00736 PRIVATE void psip_buffree (priority)
00737 int priority;
00738 {
00739 int i;
00740 psip_port_t *psip_port;
00741 acc_t *tmp_acc, *next_acc;
00742
00743 if (priority == PSIP_PRI_EXP_PROMISC)
00744 {
00745 for (i=0, psip_port= psip_port_table; i<psip_conf_nr;
00746 i++, psip_port++)
00747 {
00748 if (!(psip_port->pp_flags & PPF_CONFIGURED) )
00749 continue;
00750 if (psip_port->pp_promisc_head)
00751 {
00752 tmp_acc= psip_port->pp_promisc_head;
00753 while(tmp_acc)
00754 {
00755 next_acc= tmp_acc->acc_ext_link;
00756 bf_afree(tmp_acc);
00757 tmp_acc= next_acc;
00758 }
00759 psip_port->pp_promisc_head= NULL;
00760 }
00761 }
00762 }
00763 }
00764
00765 #ifdef BUF_CONSISTENCY_CHECK
00766 PRIVATE void psip_bufcheck()
00767 {
00768 int i;
00769 psip_port_t *psip_port;
00770 acc_t *tmp_acc;
00771
00772 for (i= 0, psip_port= psip_port_table; i<psip_conf_nr;
00773 i++, psip_port++)
00774 {
00775 for (tmp_acc= psip_port->pp_promisc_head; tmp_acc;
00776 tmp_acc= tmp_acc->acc_ext_link)
00777 {
00778 bf_check_acc(tmp_acc);
00779 }
00780 }
00781 }
00782 #endif
00783
00784
00785
00786
00787
00788 PRIVATE void reply_thr_put(psip_fd, reply, for_ioctl)
00789 psip_fd_t *psip_fd;
00790 int reply;
00791 int for_ioctl;
00792 {
00793 int result;
00794
00795 result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd, reply,
00796 (acc_t *)0, for_ioctl);
00797 assert(result == NW_OK);
00798 }
00799
00800
00801
00802
00803
00804 PRIVATE void reply_thr_get(psip_fd, reply, for_ioctl)
00805 psip_fd_t *psip_fd;
00806 int reply;
00807 int for_ioctl;
00808 {
00809 acc_t *result;
00810 result= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd, reply,
00811 (size_t)0, for_ioctl);
00812 assert (!result);
00813 }
00814
00815
00816
00817
00818