Please wait until the page is fully downloaded and then press the "Expand" button or the blue line numbers.

0047001 /*
0047002 generic/psip.c
A pseudo-ip driver is not present with the current distribution. Probably because there is a disperse of protocols that can be used among them PPP, SLIP, PLIP. An excellent collection of those drivers can be found at Claudio Tantignone's site.



0047003 
0047004 Implementation of a pseudo IP device.
0047005 
0047006 Created:       Apr 22, 1993 by Philip Homburg
0047007 
0047008 Copyright 1995 Philip Homburg
0047009 */
0047010 
0047011 #include "inet.h"
0047012 #include "assert.h"
0047013 #include "buf.h"
0047014 #include "event.h"
0047015 #include "type.h"
0047016 #include "ip_int.h"
0047017 #include "psip.h"
0047018 #include "sr.h"
0047019 
0047020 #if ENABLE_PSIP
0047021 
0047022 THIS_FILE
0047023 
0047024 typedef struct psip_port
0047025 {
0047026          int pp_flags;
0047027          int pp_ipdev;
0047028          int pp_opencnt;
0047029          struct psip_fd *pp_rd_head;
0047030          struct psip_fd *pp_rd_tail;
0047031          acc_t *pp_promisc_head;
0047032          acc_t *pp_promisc_tail;
0047033 } psip_port_t;
0047034 
0047035 #define PPF_EMPTY       0
0047036 #define PPF_CONFIGURED       1
0047037 #define PPF_ENABLED       2
0047038 #define PPF_PROMISC       4
0047039 
0047040 #define PSIP_FD_NR       (1*IP_PORT_MAX)
0047041 
0047042 typedef struct psip_fd
0047043 {
0047044          int pf_flags;
0047045          int pf_srfd;
0047046          psip_port_t *pf_port;
0047047          get_userdata_t pf_get_userdata;
0047048          put_userdata_t pf_put_userdata;
0047049          struct psip_fd *pf_rd_next;
0047050          size_t pf_rd_count;
0047051          nwio_psipopt_t pf_psipopt;
0047052 } psip_fd_t;
0047053 
0047054 #define PFF_EMPTY       0
0047055 #define PFF_INUSE       1
0047056 #define PFF_READ_IP       2
0047057 #define PFF_PROMISC       4
0047058 
0047059 PRIVATE psip_port_t *psip_port_table;
0047060 PRIVATE psip_fd_t psip_fd_table[PSIP_FD_NR];
0047061 
0047062 FORWARD int psip_open ARGS(( int port, int srfd,
0047063          get_userdata_t get_userdata, put_userdata_t put_userdata,
0047064          put_pkt_t pkt_pkt ));
0047065 FORWARD int psip_ioctl ARGS(( int fd, ioreq_t req ));
0047066 FORWARD int psip_read ARGS(( int fd, size_t count ));
0047067 FORWARD int psip_write ARGS(( int fd, size_t count ));
0047068 FORWARD void psip_close ARGS(( int fd ));
0047069 FORWARD int psip_cancel ARGS(( int fd, int which_operation ));
0047070 FORWARD void promisc_restart_read ARGS(( psip_port_t *psip_port ));
0047071 FORWARD int psip_setopt ARGS(( psip_fd_t *psip_fd, nwio_psipopt_t *newoptp ));
0047072 FORWARD void psip_buffree ARGS(( int priority ));
0047073 #ifdef BUF_CONSISTENCY_CHECK
0047074 FORWARD void psip_bufcheck ARGS(( void ));
0047075 #endif
0047076 FORWARD void reply_thr_put ARGS(( psip_fd_t *psip_fd, int reply,
0047077          int for_ioctl ));
0047078 FORWARD void reply_thr_get ARGS(( psip_fd_t *psip_fd, int reply,
0047079          int for_ioctl ));
0047080 
0047081 PUBLIC void psip_prep()
0047082 {
0047083          psip_port_table= alloc(psip_conf_nr * sizeof(psip_port_table[0]));
0047084 }
0047085 
0047086 PUBLIC void psip_init()
0047087 {
0047088          int i;
0047089          psip_port_t *psip_port;
0047090          psip_fd_t *psip_fd;
0047091 
0047092 #if ZERO
0047093          for (i=0, psip_port= psip_port_table; i<psip_conf_nr; i++, psip_port++)
0047094                   psip_port->pp_flags= PPF_EMPTY;
0047095 
0047096          for (i=0, psip_fd= psip_fd_table; i<PSIP_FD_NR; i++, psip_fd++)
0047097                   psip_fd->pf_flags= PFF_EMPTY;
0047098 #endif
0047099 
0047100          for (i=0, psip_port= psip_port_table; i<psip_conf_nr; i++, psip_port++)
0047101          {
0047102                   psip_port->pp_flags |= PPF_CONFIGURED;
0047103 #if ZERO
0047104                   psip_port->pp_opencnt= 0;
0047105                   psip_port->pp_rd_head= NULL;
0047106                   psip_port->pp_promisc_head= NULL;
0047107 #endif
0047108          }
0047109 
0047110 #ifndef BUF_CONSISTENCY_CHECK
0047111          bf_logon(psip_buffree);
0047112 #else
0047113          bf_logon(psip_buffree, psip_bufcheck);
0047114 #endif
0047115 }
0047116 
0047117 PUBLIC int psip_enable(port_nr, ip_port_nr)
0047118 int port_nr;
0047119 int ip_port_nr;
0047120 {
0047121          psip_port_t *psip_port;
0047122 
0047123          assert(port_nr >= 0 && port_nr < psip_conf_nr);
0047124 
0047125          psip_port= &psip_port_table[port_nr];
0047126          assert(psip_port->pp_flags & PPF_CONFIGURED);
0047127 
0047128          psip_port->pp_ipdev= ip_port_nr;
0047129          psip_port->pp_flags |= PPF_ENABLED;
0047130 
0047131          sr_add_minor(if2minor(psip_conf[port_nr].pc_ifno, PSIP_DEV_OFF),
0047132                   port_nr, psip_open, psip_close, psip_read,
0047133                   psip_write, psip_ioctl, psip_cancel);
0047134 
0047135          return NW_OK;
0047136 }
0047137 
0047138 PUBLIC int psip_send(port_nr, pack)
0047139 int port_nr;
0047140 acc_t *pack;
0047141 {
0047142          psip_port_t *psip_port;
0047143          psip_fd_t *psip_fd, *mark_fd;
0047144          int i, result, result1;
0047145          size_t buf_size;
0047146          acc_t *hdr_pack;
0047147          psip_io_hdr_t *hdr;
0047148 
0047149          assert(port_nr >= 0 && port_nr < psip_conf_nr);
0047150          psip_port= &psip_port_table[port_nr];
0047151 
0047152          if (psip_port->pp_opencnt == 0)
0047153          {
0047154                   bf_afree(pack);
0047155                   return NW_OK;
0047156          }
0047157 
0047158          for(;;)
0047159          {
0047160                   mark_fd= psip_port->pp_rd_tail;
0047161 
0047162                   for(i= 0; i<PSIP_FD_NR; i++)
0047163                   {
0047164                            psip_fd= psip_port->pp_rd_head;
0047165                            if (!psip_fd)
0047166                                     return NW_SUSPEND;
0047167                            psip_port->pp_rd_head= psip_fd->pf_rd_next;
0047168                            if (!(psip_fd->pf_flags & PFF_PROMISC))
0047169                                     break;
0047170                            psip_fd->pf_rd_next= NULL;
0047171                            if (psip_port->pp_rd_head == NULL)
0047172                                     psip_port->pp_rd_head= psip_fd;
0047173                            else
0047174                                     psip_port->pp_rd_tail->pf_rd_next= psip_fd;
0047175                            psip_port->pp_rd_tail= psip_fd;
0047176                            if (psip_fd == mark_fd)
0047177                                     return NW_SUSPEND;
0047178                   }
0047179                   if (i == PSIP_FD_NR)
0047180                            ip_panic(( "psip_send: loop" ));
0047181 
0047182                   assert(psip_fd->pf_flags & PFF_READ_IP);
0047183                   psip_fd->pf_flags &= ~PFF_READ_IP;
0047184 
0047185                   buf_size= bf_bufsize(pack);
0047186                   if (buf_size <= psip_fd->pf_rd_count)
0047187                   {
0047188                            if (psip_port->pp_flags & PPF_PROMISC)
0047189                            {
0047190                                     /* Deal with promiscuous mode. */
0047191                                     hdr_pack= bf_memreq(sizeof(*hdr));
0047192                                     hdr= (psip_io_hdr_t *)ptr2acc_data(hdr_pack);
0047193                                     memset(hdr, '\0', sizeof(*hdr));
0047194                                     hdr->pih_flags |= PF_LOC2REM;
0047195 
0047196                                     pack->acc_linkC++;
0047197                                     hdr_pack->acc_next= pack;
0047198                                     hdr_pack->acc_ext_link= NULL;
0047199                                     if (psip_port->pp_promisc_head)
0047200                                     {
0047201                                              /* Append at the end. */
0047202                                              psip_port->pp_promisc_tail->
0047203                                                     acc_ext_link= hdr_pack;
0047204                                              psip_port->pp_promisc_tail= hdr_pack;
0047205                                     }
0047206                                     else
0047207                                     {
0047208                                              /* First packet. */
0047209                                              psip_port->pp_promisc_head= hdr_pack;
0047210                                              psip_port->pp_promisc_tail= hdr_pack;
0047211                                              if (psip_port->pp_rd_head)
0047212                                               promisc_restart_read(psip_port);
0047213                                     }
0047214                            }
0047215                            result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
0047216                                     (size_t)0, pack, FALSE);
0047217                            if (result == NW_OK)
0047218                                     result= buf_size;
0047219                   }
0047220                   else
0047221                            result= EPACKSIZE;
0047222 
0047223                   result1= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
0047224                                     (size_t)result, NULL, FALSE);
0047225                   assert(result1 == NW_OK);
0047226                   if (result == EPACKSIZE)
0047227                            continue;
0047228                   return NW_OK;
0047229          }
0047230          return NW_SUSPEND;
0047231 }
0047232 
0047233 PRIVATE int psip_open(port, srfd, get_userdata, put_userdata, put_pkt)
0047234 int port;
0047235 int srfd;
0047236 get_userdata_t get_userdata;
0047237 put_userdata_t put_userdata;
0047238 put_pkt_t put_pkt;
0047239 {
0047240          psip_port_t *psip_port;
0047241          psip_fd_t *psip_fd;
0047242          int i;
0047243 
0047244          assert(port >= 0 && port < psip_conf_nr);
0047245          psip_port= &psip_port_table[port];
0047246 
0047247          if (!(psip_port->pp_flags & PPF_ENABLED))
0047248                   return ENXIO;
0047249 
0047250          for (i= 0, psip_fd= psip_fd_table; i<PSIP_FD_NR; i++, psip_fd++)
0047251          {
0047252                   if (psip_fd->pf_flags & PFF_INUSE)
0047253                            continue;
0047254                   break;
0047255          }
0047256          if (i == PSIP_FD_NR)
0047257                   return ENFILE;
0047258          psip_fd->pf_flags |= PFF_INUSE;
0047259          psip_fd->pf_srfd= srfd;
0047260          psip_fd->pf_port= psip_port;
0047261          psip_fd->pf_get_userdata= get_userdata;
0047262          psip_fd->pf_put_userdata= put_userdata;
0047263          psip_port->pp_opencnt++;
0047264 
0047265          return i;
0047266 }
0047267 
0047268 PRIVATE int psip_ioctl(fd, req)
0047269 int fd;
0047270 ioreq_t req;
0047271 {
0047272          int result;
0047273          psip_fd_t *psip_fd;
0047274          acc_t *data;
0047275          nwio_psipopt_t *psip_opt, *newoptp;
0047276 
0047277          assert(fd >= 0 && fd < PSIP_FD_NR);
0047278          psip_fd= &psip_fd_table[fd];
0047279 
0047280          switch(req)
0047281          {
0047282          case NWIOSPSIPOPT:
0047283                   data= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd, 0,
0047284                            sizeof(*psip_opt), TRUE);
0047285                   if (!data)
0047286                   {
0047287                            result= EFAULT;
0047288                            break;
0047289                   }
0047290                   data= bf_packIffLess(data, sizeof(*psip_opt));
0047291                   assert (data->acc_length == sizeof(*psip_opt));
0047292 
0047293                   newoptp= (nwio_psipopt_t *)ptr2acc_data(data);
0047294                   result= psip_setopt(psip_fd, newoptp);
0047295                   bf_afree(data);
0047296                   if (result == NW_OK)
0047297                   {
0047298                            if (psip_fd->pf_psipopt.nwpo_flags & NWPO_EN_PROMISC)
0047299                            {
0047300                                     psip_fd->pf_flags |= PFF_PROMISC;
0047301                                     psip_fd->pf_port->pp_flags |= PPF_PROMISC;
0047302                            }
0047303                            else
0047304                            {
0047305                                     psip_fd->pf_flags &= ~PFF_PROMISC;
0047306                                     /* XXX check port flags */
0047307                            }
0047308                   }
0047309                   reply_thr_get(psip_fd, result, TRUE);
0047310                   break;
0047311          case NWIOGPSIPOPT:
0047312                   data= bf_memreq(sizeof(*psip_opt));
0047313                   psip_opt= (nwio_psipopt_t *)ptr2acc_data(data);
0047314 
0047315                   *psip_opt= psip_fd->pf_psipopt;
0047316                   result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd, 0,
0047317                            data, TRUE);
0047318                   if (result == NW_OK)
0047319                            reply_thr_put(psip_fd, NW_OK, TRUE);
0047320                   break;
0047321          default:
0047322                   reply_thr_put(psip_fd, ENOTTY, TRUE);
0047323                   break;
0047324          }
0047325          return NW_OK;
0047326 }
0047327 
0047328 PRIVATE int psip_read(fd, count)
0047329 int fd;
0047330 size_t count;
0047331 {
0047332          psip_port_t *psip_port;
0047333          psip_fd_t *psip_fd;
0047334 
0047335          assert(fd >= 0 && fd < PSIP_FD_NR);
0047336          psip_fd= &psip_fd_table[fd];
0047337          psip_port= psip_fd->pf_port;
0047338 
0047339          psip_fd->pf_rd_count= count;
0047340          if (psip_port->pp_rd_head == NULL)
0047341                   psip_port->pp_rd_head= psip_fd;
0047342          else
0047343                   psip_port->pp_rd_tail->pf_rd_next= psip_fd;
0047344          psip_fd->pf_rd_next= NULL;
0047345          psip_port->pp_rd_tail= psip_fd;
0047346 
0047347          psip_fd->pf_flags |= PFF_READ_IP;
0047348          if (psip_fd->pf_flags & PFF_PROMISC)
0047349                   promisc_restart_read(psip_port);
0047350          else
0047351                   ipps_get(psip_port->pp_ipdev);
0047352          if (psip_fd->pf_flags & PFF_READ_IP)
0047353                   return NW_SUSPEND;
0047354          return NW_OK;
0047355 }
0047356 
0047357 PRIVATE int psip_write(fd, count)
0047358 int fd;
0047359 size_t count;
0047360 {
0047361          psip_port_t *psip_port;
0047362          psip_fd_t *psip_fd;
0047363          acc_t *pack, *hdr_pack;
0047364          psip_io_hdr_t *hdr;
0047365 
0047366          assert(fd >= 0 && fd < PSIP_FD_NR);
0047367          psip_fd= &psip_fd_table[fd];
0047368          psip_port= psip_fd->pf_port;
0047369 
0047370          pack= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd, (size_t)0,
0047371                   count, FALSE);
0047372          if (pack == NULL)
0047373          {
0047374                   pack= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd,
0047375                            (size_t)EFAULT, (size_t)0, FALSE);
0047376                   assert(pack == NULL);
0047377                   return NW_OK;
0047378          }
0047379          if (psip_port->pp_flags & PPF_PROMISC)
0047380          {
0047381                   /* Deal with promiscuous mode. */
0047382                   hdr_pack= bf_memreq(sizeof(*hdr));
0047383                   hdr= (psip_io_hdr_t *)ptr2acc_data(hdr_pack);
0047384                   memset(hdr, '\0', sizeof(*hdr));
0047385                   hdr->pih_flags |= PF_REM2LOC;
0047386 
0047387                   pack->acc_linkC++;
0047388                   hdr_pack->acc_next= pack;
0047389                   hdr_pack->acc_ext_link= NULL;
0047390                   if (psip_port->pp_promisc_head)
0047391                   {
0047392                            /* Append at the end. */
0047393                            psip_port->pp_promisc_tail->acc_ext_link= hdr_pack;
0047394                   }
0047395                   else
0047396                   {
0047397                            /* First packet. */
0047398                            psip_port->pp_promisc_head= hdr_pack;
0047399                            if (psip_port->pp_rd_head)
0047400                                     promisc_restart_read(psip_port);
0047401                   }
0047402          }
0047403          ipps_put(psip_port->pp_ipdev, pack);
0047404          pack= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd, (size_t)count,
0047405                   (size_t)0, FALSE);
0047406          assert(pack == NULL);
0047407          return NW_OK;
0047408 }
0047409 
0047410 PRIVATE void psip_close(fd)
0047411 int fd;
0047412 {
0047413          psip_port_t *psip_port;
0047414          psip_fd_t *psip_fd;
0047415          acc_t *acc, *acc_next;
0047416          int i;
0047417 
0047418          assert(fd >= 0 && fd < PSIP_FD_NR);
0047419          psip_fd= &psip_fd_table[fd];
0047420          psip_port= psip_fd->pf_port;
0047421 
0047422          assert(psip_port->pp_opencnt >0);
0047423          psip_port->pp_opencnt--;
0047424          psip_fd->pf_flags= PFF_EMPTY;
0047425          ipps_get(psip_port->pp_ipdev);
0047426 
0047427          /* Check if the port should still be in promiscuous mode. */
0047428          if (psip_port->pp_flags & PPF_PROMISC)
0047429          {
0047430                   psip_port->pp_flags &= ~PPF_PROMISC;
0047431                   for (i= 0, psip_fd= psip_fd_table; i<PSIP_FD_NR;
0047432                            i++, psip_fd++)
0047433                   {
0047434                            if ((psip_fd->pf_flags & (PFF_INUSE|PFF_PROMISC)) !=
0047435                                     (PFF_INUSE|PFF_PROMISC))
0047436                            {
0047437                                     continue;
0047438                            }
0047439                            if (psip_fd->pf_port != psip_port)
0047440                                     continue;
0047441                            psip_port->pp_flags |= PPF_PROMISC;
0047442                            break;
0047443                   }
0047444                   if (!(psip_port->pp_flags & PPF_PROMISC))
0047445                   {
0047446                            /* Delete queued packets. */
0047447                            acc= psip_port->pp_promisc_head;
0047448                            psip_port->pp_promisc_head= NULL;
0047449                            while (acc)
0047450                            {
0047451                                     acc_next= acc->acc_ext_link;
0047452                                     bf_afree(acc);
0047453                                     acc= acc_next;
0047454                            }
0047455                   }
0047456          }
0047457 }
0047458 
0047459 PRIVATE int psip_cancel(fd, which_operation)
0047460 int fd;
0047461 int which_operation;
0047462 {
0047463          psip_port_t *psip_port;
0047464          psip_fd_t *psip_fd, *prev_fd, *tmp_fd;
0047465          int result;
0047466 
0047467          DBLOCK(1, printf("psip_cancel(%d, %d)\n", fd, which_operation));
0047468 
0047469          assert(fd >= 0 && fd < PSIP_FD_NR);
0047470          psip_fd= &psip_fd_table[fd];
0047471          psip_port= psip_fd->pf_port;
0047472 
0047473          switch(which_operation)
0047474          {
0047475 #if !CRAMPED
0047476          case SR_CANCEL_IOCTL:
0047477                   ip_panic(( "should not be here" ));
0047478 #endif
0047479          case SR_CANCEL_READ:
0047480                   assert(psip_fd->pf_flags & PFF_READ_IP);
0047481                   for (prev_fd= NULL, tmp_fd= psip_port->pp_rd_head; tmp_fd;
0047482                                     prev_fd= tmp_fd, tmp_fd= tmp_fd->pf_rd_next)
0047483                   {
0047484                            if (tmp_fd == psip_fd)
0047485                                     break;
0047486                   }
0047487 #if !CRAMPED
0047488                   if (tmp_fd == NULL)
0047489                            ip_panic(( "unable to find to request to cancel" ));
0047490 #endif
0047491                   if (prev_fd == NULL)
0047492                            psip_port->pp_rd_head= psip_fd->pf_rd_next;
0047493                   else
0047494                            prev_fd->pf_rd_next= psip_fd->pf_rd_next;
0047495                   if (psip_fd->pf_rd_next == NULL)
0047496                            psip_port->pp_rd_tail= prev_fd;
0047497                   psip_fd->pf_flags &= ~PFF_READ_IP;
0047498                   result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
0047499                                               (size_t)EINTR, NULL, FALSE);
0047500                   assert(result == NW_OK);
0047501                   break;
0047502 #if !CRAMPED
0047503          case SR_CANCEL_WRITE:
0047504                   ip_panic(( "should not be here" ));
0047505          default:
0047506                   ip_panic(( "invalid operation for cancel" ));
0047507 #endif
0047508          }
0047509          return NW_OK;
0047510 }
0047511 
0047512 PRIVATE void promisc_restart_read(psip_port)
0047513 psip_port_t *psip_port;
0047514 {
0047515          psip_fd_t *psip_fd, *mark_fd;
0047516          acc_t *pack;
0047517          size_t buf_size;
0047518          int i, result, result1;
0047519 
0047520          while (psip_port->pp_promisc_head)
0047521          {
0047522                   mark_fd= psip_port->pp_rd_tail;
0047523 
0047524                   for(i= 0; i<PSIP_FD_NR; i++)
0047525                   {
0047526                            psip_fd= psip_port->pp_rd_head;
0047527                            if (!psip_fd)
0047528                                     return;
0047529                            psip_port->pp_rd_head= psip_fd->pf_rd_next;
0047530                            if (psip_fd->pf_flags & PFF_PROMISC)
0047531                                     break;
0047532                            psip_fd->pf_rd_next= NULL;
0047533                            if (psip_port->pp_rd_head == NULL)
0047534                                     psip_port->pp_rd_head= psip_fd;
0047535                            else
0047536                                     psip_port->pp_rd_tail->pf_rd_next= psip_fd;
0047537                            psip_port->pp_rd_tail= psip_fd;
0047538                            if (psip_fd == mark_fd)
0047539                                     return;
0047540                   }
0047541                   if (i == PSIP_FD_NR)
0047542                            ip_panic(( "psip'promisc_restart_read: loop" ));
0047543 
0047544                   assert(psip_fd->pf_flags & PFF_READ_IP);
0047545                   psip_fd->pf_flags &= ~PFF_READ_IP;
0047546 
0047547                   pack= psip_port->pp_promisc_head;
0047548                   buf_size= bf_bufsize(pack);
0047549                   if (buf_size <= psip_fd->pf_rd_count)
0047550                   {
0047551                            psip_port->pp_promisc_head= pack->acc_ext_link;
0047552                            result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
0047553                                     (size_t)0, pack, FALSE);
0047554                            if (result == NW_OK)
0047555                                     result= buf_size;
0047556                   }
0047557                   else
0047558                            result= EPACKSIZE;
0047559 
0047560                   result1= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd,
0047561                                     (size_t)result, NULL, FALSE);
0047562                   assert(result1 == NW_OK);
0047563          }
0047564 }
0047565 
0047566 PRIVATE int psip_setopt(psip_fd, newoptp)
0047567 psip_fd_t *psip_fd;
0047568 nwio_psipopt_t *newoptp;
0047569 {
0047570          nwio_psipopt_t oldopt;
0047571          int result;
0047572          unsigned int new_en_flags, new_di_flags, old_en_flags, old_di_flags,
0047573                   all_flags, flags;
0047574          unsigned long new_flags;
0047575          int i;
0047576 
0047577          oldopt= psip_fd->pf_psipopt;
0047578 
0047579          old_en_flags= oldopt.nwpo_flags & 0xffff;
0047580          old_di_flags= (oldopt.nwpo_flags >> 16) & 0xffff;
0047581 
0047582          new_en_flags= newoptp->nwpo_flags & 0xffff;
0047583          new_di_flags= (newoptp->nwpo_flags >> 16) & 0xffff;
0047584 
0047585          if (new_en_flags & new_di_flags)
0047586                   return EBADMODE;
0047587 
0047588          /* NWUO_LOCADDR_MASK */
0047589          if (!((new_en_flags | new_di_flags) & NWPO_PROMISC_MASK))
0047590          {
0047591                   new_en_flags |= (old_en_flags & NWPO_PROMISC_MASK);
0047592                   new_di_flags |= (old_di_flags & NWPO_PROMISC_MASK);
0047593          }
0047594 
0047595          new_flags= ((unsigned long)new_di_flags << 16) | new_en_flags;
0047596 
0047597          psip_fd->pf_psipopt= *newoptp;
0047598          psip_fd->pf_psipopt.nwpo_flags= new_flags;
0047599 
0047600          return NW_OK;
0047601 }
0047602 
0047603 PRIVATE void psip_buffree (priority)
0047604 int priority;
0047605 {
0047606          int i;
0047607          psip_port_t *psip_port;
0047608          acc_t *tmp_acc, *next_acc;
0047609 
0047610          if (priority == PSIP_PRI_EXP_PROMISC)
0047611          {
0047612                   for (i=0, psip_port= psip_port_table; i<psip_conf_nr;
0047613                            i++, psip_port++)
0047614                   {
0047615                            if (!(psip_port->pp_flags & PPF_CONFIGURED) )
0047616                                     continue;
0047617                            if (psip_port->pp_promisc_head)
0047618                            {
0047619                                     tmp_acc= psip_port->pp_promisc_head;
0047620                                     while(tmp_acc)
0047621                                     {
0047622                                              next_acc= tmp_acc->acc_ext_link;
0047623                                              bf_afree(tmp_acc);
0047624                                              tmp_acc= next_acc;
0047625                                     }
0047626                                     psip_port->pp_promisc_head= NULL;
0047627                            }
0047628                   }
0047629          }
0047630 }
0047631 
0047632 #ifdef BUF_CONSISTENCY_CHECK
0047633 PRIVATE void psip_bufcheck()
0047634 {
0047635          int i;
0047636          psip_port_t *psip_port;
0047637          acc_t *tmp_acc;
0047638 
0047639          for (i= 0, psip_port= psip_port_table; i<psip_conf_nr;
0047640                   i++, psip_port++)
0047641          {
0047642                   for (tmp_acc= psip_port->pp_promisc_head; tmp_acc;
0047643                            tmp_acc= tmp_acc->acc_ext_link)
0047644                   {
0047645                            bf_check_acc(tmp_acc);
0047646                   }
0047647          }
0047648 }
0047649 #endif
0047650 
0047651 /*
0047652 reply_thr_put
0047653 */
0047654 
0047655 PRIVATE void reply_thr_put(psip_fd, reply, for_ioctl)
0047656 psip_fd_t *psip_fd;
0047657 int reply;
0047658 int for_ioctl;
0047659 {
0047660          int result;
0047661 
0047662          result= (*psip_fd->pf_put_userdata)(psip_fd->pf_srfd, reply,
0047663                   (acc_t *)0, for_ioctl);
0047664          assert(result == NW_OK);
0047665 }
0047666 
0047667 /*
0047668 reply_thr_get
0047669 */
0047670 
0047671 PRIVATE void reply_thr_get(psip_fd, reply, for_ioctl)
0047672 psip_fd_t *psip_fd;
0047673 int reply;
0047674 int for_ioctl;
0047675 {
0047676          acc_t *result;
0047677          result= (*psip_fd->pf_get_userdata)(psip_fd->pf_srfd, reply,
0047678                   (size_t)0, for_ioctl);
0047679          assert (!result);
0047680 }
0047681 
0047682 #endif /* ENABLE_PSIP */
0047683 
0047684 /*
0047685  * $PchId: psip.c,v 1.6 1996/05/07 20:50:31 philip Exp $
0047686  */