home *** CD-ROM | disk | FTP | other *** search
/ Hackers Toolkit 2.0 / Hackers_Toolkit_v2.0.iso / HTML / archive / Unix / c-src / atap.c / tap.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-11-04  |  7.9 KB  |  412 lines

  1. /*
  2.  * tap streams-module/driver kernel-loadable-module, aka WATER-WORKS 
  3.  * this is a combination of a STREAMS-module and a STREAMS-driver.
  4.  *
  5.  * Simon Ney -- neural@cs.tu-berlin.de -- simon@bbisun.uu.sub.org
  6.  */
  7.  
  8. #include "tap.h"
  9. #if    NTAP > 0
  10. #include <sys/types.h>
  11. #include <sys/stream.h>
  12. #include <sys/stropts.h>
  13. #include <sys/param.h>
  14. #include <sys/errno.h>
  15. #include <sys/user.h>
  16. #include <sys/file.h>
  17. #include <sys/termio.h> /*XX*/
  18. #ifdef TAPVD
  19. #include <sys/conf.h>
  20. #include <sun/vddrv.h>
  21. #endif TAPVD
  22.  
  23. #ifndef lint
  24. static    char sccsid[] = "@(#)tap.c    1.26 5/8/93";
  25. #endif
  26.  
  27. /* 
  28.  * --- DRIVER PART --- 
  29.  */
  30.  
  31. #ifdef TAPVDDUAL
  32. static struct module_info cminfo = { 0, "tapcvd", 0, INFPSZ, 0, 0 };
  33. #else
  34. static struct module_info cminfo = { 0, "tapc", 0, INFPSZ, 0, 0 };
  35. #endif
  36.  
  37. static int tapcopen(), tapcrput(), tapcwput(), tapcclose();
  38.  
  39. static struct qinit crinit = {
  40.     tapcrput, NULL, tapcopen, tapcclose, NULL, &cminfo, NULL
  41. };
  42.  
  43. static struct qinit cwinit = {
  44.     tapcwput, NULL, NULL, NULL, NULL, &cminfo, NULL
  45. };
  46.  
  47. #ifdef TAPVD /* so we can have a permanent linked AND loadable version */
  48. struct streamtab tapcvdinfo = { &crinit, &cwinit, NULL, NULL };
  49. #else
  50. struct streamtab tapcinfo = { &crinit, &cwinit, NULL, NULL };
  51. #endif
  52.  
  53. /*
  54.  * --- MODULE PART --- 
  55.  */
  56.  
  57. #ifdef TAPVDDUAL
  58. static struct module_info minfo = { 0, "tapvd", 0, INFPSZ, 0, 0 };
  59. #else
  60. static struct module_info minfo = { 0, "tap", 0, INFPSZ, 0, 0 };
  61. #endif
  62.  
  63. static int tapopen(), taprput(), tapwput(), tapclose();
  64.  
  65. static struct qinit rinit = {
  66.     taprput, NULL, tapopen, tapclose, NULL, &minfo, NULL
  67. };
  68.  
  69. static struct qinit winit = {
  70.     tapwput, NULL, NULL, NULL, NULL, &minfo, NULL
  71. };
  72.  
  73. #ifdef TAPVD /* so we can have a permanent linked AND loadable version */
  74. struct streamtab tapvdinfo = { &rinit, &winit, NULL, NULL };
  75. #else
  76. struct streamtab tapinfo = { &rinit, &winit, NULL, NULL };
  77. #endif
  78.  
  79. /*
  80.  * the ,,TAP device'' structure 
  81.  */
  82.  
  83. struct tap {
  84.     queue_t *tapdm_queue;    /* queue from driver to module (set by module)*/
  85.     queue_t *tapmd_queue;    /* queue from module to driver (set by driver)*/
  86. #define TAP_REVERSE    1    /* if set connect to lower side else upper */
  87.     unsigned int tap_flags;    /* currently only the TAP_REVERSE flag */
  88. };
  89. static struct tap  tap_tap[NTAP];    /* static for now */
  90. static int tap_cnt = NTAP;
  91.  
  92. /* 
  93.  * --- KERNEL-LOADABLE-MODULE SUPPORT --- 
  94.  */
  95.  
  96. #ifdef TAPVD
  97. extern int nodev();
  98.  
  99. static struct cdevsw        tap_cdevsw = { 
  100.     nodev, nodev, nodev, nodev, nodev, nodev, nodev, 0, 
  101.     &tapcvdinfo, 0
  102. };
  103.  
  104. static struct vdldrv tapvdldrv = {
  105.     VDMAGIC_PSEUDO, "tapc/tap-1.26", 
  106. #ifdef sun4m
  107.     NULL,
  108.     NULL, &tap_cdevsw, 0, 0,
  109.     NULL,
  110.     NULL, NULL, 0, 1
  111. #else
  112.     NULL,
  113. #ifndef sun4c
  114.     NULL, NULL, 0, 1,
  115. #endif
  116.     NULL, &tap_cdevsw, 0, 0    
  117. #endif
  118. };
  119.  
  120. /*
  121.  * this is the pushable-STREAMS-module kernel-module-loader
  122.  */
  123. static    struct fmodsw *saved_fmp;
  124.  
  125. static struct fmodsw *loadfmodsw(name,str)
  126. char *name;
  127. struct streamtab *str;
  128. {
  129.     register struct fmodsw *fmp;
  130.     register int i;
  131.     extern struct fmodsw fmodsw[];
  132.     extern int fmodcnt;
  133.  
  134.     fmp = fmodsw;
  135.     for(i=0;i<fmodcnt;i++,fmp++){
  136.         if(fmp->f_str==0){
  137.             strcpy(fmp->f_name,name);
  138.             fmp->f_str = str;
  139.             return(fmp);
  140.         }
  141.     }
  142.     printf("tap: loadfmodsw: no free slot for '%s'\n",name);
  143.     return(0);
  144. }
  145.  
  146. static unloadfmodsw(fmp)
  147.     struct fmodsw *fmp;
  148. {
  149.     fmp->f_name[0] = '\0';
  150.     fmp->f_str = 0;
  151. }
  152.  
  153. /*
  154.  * this is the driver entry point routine. the name of the default entry
  155.  * point is xxxinit. it can be changed by using the "-entry" command to
  156.  * modload.
  157.  */
  158.  
  159. xxxinit(function_code,vdp,vdi,vds)
  160. unsigned int function_code;
  161. struct vddrv *vdp;
  162. addr_t vdi;
  163. struct vdstat *vds;
  164. {
  165.     register int i;
  166.     register struct tap *tap;
  167.  
  168.     switch(function_code){
  169.     case VDLOAD:
  170.         if(saved_fmp){        /* ever occured */
  171.             printf("tap: xxxinit:already loaded\n");
  172.             return(ENXIO);
  173.         }
  174. #ifdef TAPVDDUAL
  175.         if(!(saved_fmp=loadfmodsw("tapvd",&tapvdinfo))){
  176. #else
  177.         if(!(saved_fmp=loadfmodsw("tap",&tapvdinfo))){
  178. #endif
  179.             return(ENXIO);
  180.         }
  181.         vdp->vdd_vdtab = (struct vdlinkage *) &tapvdldrv;
  182.         break;
  183.     case VDUNLOAD:
  184.         for(i=0,tap=tap_tap;i<tap_cnt;i++,tap++)
  185.             if(tap->tapdm_queue||tap->tapmd_queue)
  186.                 return(EBUSY);    
  187.         if(saved_fmp)
  188.             unloadfmodsw(saved_fmp);
  189.         break;
  190.     case VDSTAT:
  191. #ifdef TAPDEBUG
  192.         for(i=0,tap=tap_tap;i<tap_cnt;i++,tap++)
  193.             if(tap->tapdm_queue||tap->tapmd_queue)
  194.                 printf( "tap%d: dm=0x%x md=0x%x flags=0x%x\n",
  195.                     i,tap->tapdm_queue,tap->tapmd_queue,
  196.                     tap->tap_flags);
  197. #endif
  198.         break;
  199.     default:
  200.         return(EIO);
  201.     }
  202.     return(0);    /* return success */
  203. }
  204. #endif TAPVD
  205.  
  206. /* --- MODULE PART --- */
  207.  
  208. static int tapopen(q, dev, flag, sflag)
  209.     queue_t *q;
  210.     dev_t   dev;
  211.     int        flag;
  212.     int    sflag;
  213. {
  214.     register int i;
  215.     register struct tap *tap;
  216.  
  217.     if(!(q->q_ptr)){
  218.         /*
  219.          * find first fit free slot
  220.          */
  221.         for(i=0,tap=tap_tap;i<tap_cnt;i++,tap++){
  222.             if(!(tap->tapdm_queue)){
  223.                 WR(q)->q_ptr = (char *) tap;
  224.                 q->q_ptr = (char *) tap; /* mark as open */
  225.                 tap->tapdm_queue = q;    
  226.                 return(0);
  227.             }
  228.         }
  229.         return(OPENFAIL);
  230.     }
  231.     return(0);    
  232. }
  233.  
  234. static int tapwput(q, mp)
  235.     queue_t    *q;    
  236.     mblk_t    *mp;   
  237. {
  238.     mblk_t    *bp;       
  239.     struct tap *tap;
  240.     
  241.     tap = (struct tap *)q->q_ptr;
  242.     
  243.     if((!(tap->tap_flags&TAP_REVERSE))&&tap->tapmd_queue){        
  244.         if(mp->b_datap->db_type==M_DATA){
  245.             if((bp=dupmsg(mp))!=NULL){    
  246.                 putnext(tap->tapmd_queue,bp);
  247.             }
  248.         }
  249.     }
  250.     putnext(q,mp);
  251. }
  252.     
  253. static int taprput(q, mp)
  254.     queue_t    *q;    
  255.     mblk_t    *mp;   
  256. {
  257.     mblk_t    *bp;       
  258.     struct tap *tap;
  259.     
  260.     tap = (struct tap *)q->q_ptr;
  261.     
  262.     if((tap->tap_flags&TAP_REVERSE)&&tap->tapmd_queue){        
  263.         if(mp->b_datap->db_type==M_DATA){
  264.             if((bp=dupmsg(mp))!=NULL){    
  265.                 putnext(tap->tapmd_queue,bp);
  266.             }
  267.         }
  268.     }
  269.     putnext(q, mp);
  270. }
  271.  
  272. static int tapclose(q, flag)
  273.     queue_t    *q;
  274.     int    flag;
  275. {
  276.     struct tap *tap;
  277.  
  278.     tap = (struct tap *)q->q_ptr;
  279.     /* here i want to send a HANGUP */
  280.     tap->tapdm_queue = NULL;
  281. }
  282.  
  283. /* --- DRIVER PART --- */
  284.  
  285. static int tapcopen(q, dev, flag, sflag)
  286.     queue_t *q;
  287.     dev_t   dev;
  288.     int        flag;
  289.     int    sflag;
  290. {
  291.     struct tap *tap;
  292.  
  293. #ifdef TAPCLONE
  294.     /*
  295.      * if CLONEOPEN, pick first unconnected module.
  296.      * otherwise, check the minor device range.
  297.      */
  298.     printf("tapopen: q=0x%x dev=%d flag=%d  sflag=%d\n",q,dev,flag,sflag);
  299.     if(sflag==CLONEOPEN) {
  300.         for(dev=0;dev<tap_cnt;dev++){
  301.             if((tap_tap[dev].tapmd_queue == NULL) &&
  302.                (tap_tap[dev].tapdm_queue != NULL)){
  303.                 printf("tapopen: CLONE=%d\n",dev);
  304.                 break;
  305.             }
  306.         }
  307.     } else {
  308.         dev = minor(dev);
  309.     }
  310. #else
  311.     /*
  312.      * check if non-driver open 
  313.      */
  314.     if(sflag)
  315.         return(OPENFAIL);
  316.     dev = minor(dev);
  317. #endif
  318.  
  319.     if(dev>= tap_cnt)
  320.         return(OPENFAIL);
  321.     if(q->q_ptr){
  322.         u.u_error = EBUSY;    /* only 1 user of tapc at a time ??? */
  323.         return(OPENFAIL);
  324.     }
  325.  
  326.     tap = &tap_tap[dev];
  327.     if(!(tap->tapdm_queue)){
  328.         u.u_error = ENETUNREACH;    
  329.         return(OPENFAIL);
  330.     }
  331.  
  332.     /*
  333.      * if opened with O_NDELAY reverse the connection
  334.      */
  335.     if(flag&FNDELAY){
  336.         if(!suser()){
  337.             u.u_error = EACCES;
  338.             return(OPENFAIL);
  339.         }
  340.         tap->tap_flags |= TAP_REVERSE;
  341.     } else
  342.         tap->tap_flags &= ~TAP_REVERSE;
  343.  
  344.     WR(q)->q_ptr = (char *)tap;
  345.     q->q_ptr = (char *)tap;
  346.     tap->tapmd_queue = q;
  347.     return(dev);    
  348. }
  349.  
  350. static int tapcwput(q, mp)
  351.     queue_t    *q;    
  352.     mblk_t    *mp;   
  353. {
  354.     switch(mp->b_datap->db_type){
  355.     case M_IOCTL: {            /* NAK all ioctl's */
  356.         /* struct iocblk *iocp; */
  357.  
  358.         /* iocp = (struct iocblk *)mp->b_rptr; */
  359.         mp->b_datap->db_type=M_IOCNAK;
  360.         qreply(q,mp);
  361.         break;
  362.     }
  363.     case M_FLUSH:
  364.         if(*mp->b_rptr & FLUSHW)
  365.             flushq(q,0);
  366.         if(*mp->b_rptr & FLUSHR){
  367.             flushq(RD(q),0);
  368.             *mp->b_rptr &= ~FLUSHW;
  369.             qreply(q,mp);
  370.         } else
  371.             freemsg(mp);
  372.         break;
  373.     case M_DATA: {
  374.         struct tap *tap;
  375.         
  376.         tap = (struct tap *)q->q_ptr;    
  377.         if(tap->tapdm_queue) {
  378.             if(tap->tap_flags&TAP_REVERSE)
  379.                 putnext(WR(tap->tapdm_queue), mp);    
  380.             else
  381.                 putnext(tap->tapdm_queue, mp);    
  382.         } else {
  383.             (void)putctl1(RD(q)->q_next, M_ERROR, ECONNRESET); 
  384.             freemsg(mp);
  385.         }
  386.         break;
  387.     }
  388.         
  389.     default:        /* discard other messages */
  390.         freemsg(mp);
  391.     }
  392. }
  393.  
  394. static int tapcrput(q, mp)
  395.     queue_t    *q;    
  396.     mblk_t    *mp;   
  397. {
  398.     putnext(q, mp);        
  399. }
  400.  
  401. static int tapcclose(q, flag)
  402.     queue_t    *q;
  403.     int    flag;
  404. {
  405.     struct tap *tap;
  406.  
  407.     tap = (struct tap *) q->q_ptr;
  408.     tap->tapmd_queue = NULL;
  409. }
  410.  
  411. #endif  NTAP
  412.