home *** CD-ROM | disk | FTP | other *** search
/ Super Net 1 / SUPERNET_1.iso / PC / OTROS / SUN / SLIP / CSN_SLIP.TAR / slip-4.1.1 / streamsip.c < prev   
Encoding:
C/C++ Source or Header  |  1991-01-05  |  6.3 KB  |  333 lines

  1. /*
  2.  *    Streams IP network module. SunOS 4.1.
  3.  *
  4.  *    Copyright CSIRO Division of Mathematics and Statistics 21 June 1990
  5.  *
  6.  *    Author: Mark Andrews, marka@syd.dms.csiro.au
  7.  *
  8.  *    Permission is hereby granted for this code to be distributed
  9.  *    free of charge with this copyright intact. Derived works should
  10.  *    be marked as so.
  11.  */
  12.  
  13. #include "slip.h"
  14. #if NSLIP > 0
  15. #include <sys/types.h>
  16. #include <sys/stream.h>
  17. #include <sys/stropts.h>
  18. #include <sys/param.h>
  19. #include <sys/systm.h>
  20. #include <sys/user.h>
  21. #include <sys/errno.h>
  22. #include <sys/mbuf.h>
  23. #include <sys/socket.h>
  24. #include <sys/uio.h>
  25. #include <sys/ioctl.h>
  26. #include <sys/file.h>
  27. #include <net/if.h>
  28. #include <net/netisr.h>
  29. #include <netinet/in.h>
  30. #include <netinet/in_var.h>
  31. #include <sys/syslog.h>
  32.  
  33. #include <sys/slip.h> /* needed for SLIPMTU (should be derived from
  34.     underlying streams module for PPP), and SLIOGUNIT */
  35.  
  36.  
  37. static int rput();
  38. static int wput();
  39. static int if_in();
  40. static int stream_open();
  41. static int stream_close();
  42. static int stream_ioctl();
  43. static int if_out();
  44. static int if_ioc();
  45.  
  46. static struct module_info minfo = { 518, "str_ip", 0, INFPSZ, 1024, 1024};
  47.  
  48. static struct qinit rinit = {
  49.     rput, if_in, stream_open, stream_close, NULL, &minfo, NULL
  50.     };
  51. static struct qinit winit = {
  52.     wput, NULL, NULL, NULL, NULL, &minfo, NULL
  53.     };
  54.  
  55. struct streamtab streams_ip = { &rinit, &winit, NULL, NULL };
  56.  
  57. typedef struct {
  58.     queue_t *q;
  59.     struct ifnet i
  60.     } ifhead ;
  61.  
  62. static ifhead ifheads[NSLIP];
  63.  
  64. static int stream_open(q,dev,flag,sflag)
  65.     queue_t *q;
  66.     dev_t dev;
  67.     int flag;
  68.     int sflag;
  69. {
  70.     struct ifnet *ifp;
  71.  
  72.     if(!suser()) {
  73.     u.u_error = EPERM;
  74.     return(OPENFAIL);
  75.     }
  76.  
  77.     for ( dev = 0 ; dev < NSLIP ; dev++)
  78.     if ( !ifheads[dev].q )
  79.         break;
  80.  
  81.     if (dev > NSLIP)
  82.     return(OPENFAIL);
  83.  
  84.     ifp = &ifheads[dev].i;
  85.     WR(q)->q_ptr = q->q_ptr = (caddr_t)&ifheads[dev];
  86.     ifheads[dev].q = q;
  87.  
  88.     if (!ifp->if_mtu) {
  89.     ifp->if_name = "slip";
  90.     ifp->if_mtu = SLIPMTU;
  91.     ifp->if_flags = IFF_POINTOPOINT;
  92.     ifp->if_unit = dev;
  93.     ifp->if_ioctl = if_ioc;
  94.     ifp->if_output = if_out;
  95.     ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
  96.  
  97.     if_attach(ifp);
  98.     }
  99.  
  100.     return(ifp->if_unit);
  101. }
  102.  
  103. static int stream_close(q,flag)
  104.     queue_t *q;
  105.     int flag;
  106. {
  107.     ((ifhead *)(q->q_ptr))->q = NULL;
  108.     ((ifhead *)(q->q_ptr))->i.if_flags &= ~IFF_UP;
  109.     q->q_ptr = NULL;
  110. }
  111.  
  112. static int wput(q,mp)
  113.     queue_t *q;
  114.     mblk_t *mp;
  115. {
  116.     struct iocblk *iocp;
  117.  
  118.     switch (mp->b_datap->db_type) {
  119.     case M_FLUSH:
  120.     if (*mp->b_rptr & FLUSHW)
  121.         flushq(q, FLUSHDATA);
  122.     case M_IOCTL:
  123.     iocp = (struct iocblk *) mp->b_rptr;
  124.     switch(iocp->ioc_cmd) {
  125.     case SLIOGUNIT:
  126.         if ((mp->b_cont = allocb(sizeof(int),BPRI_MED)) == NULL) {
  127.         mp->b_datap->db_type =  M_IOCNAK;
  128.         iocp->ioc_error = ENOSR;
  129.         } else {
  130.         mp->b_datap->db_type = M_IOCACK;
  131.         *((int *)(mp->b_cont->b_wptr)) = 
  132.             ((ifhead *)(q->q_ptr))->i.if_unit;
  133.         mp->b_cont->b_wptr += sizeof(int);
  134.         iocp->ioc_count = sizeof(int);
  135.         iocp->ioc_error = 0;
  136.         }
  137.         break;
  138.     default:
  139.         putnext(q,mp);
  140.         return;
  141.     }
  142.     qreply(q,mp);
  143.     break;
  144.     default:
  145.     putnext(q,mp);
  146.     }
  147. }
  148.  
  149. static int rput(q,mp)
  150.     queue_t *q;
  151.     mblk_t *mp;
  152. {
  153.     switch (mp->b_datap->db_type) {
  154.     case M_DATA:
  155.     case M_FLUSH:
  156.     putq(q,mp);
  157.     break;
  158.     default:
  159.     putnext(q,mp);
  160.     }
  161. }
  162.  
  163. static int if_out(ifp, m0, dst)
  164.     struct ifnet *ifp;
  165.     struct mbuf *m0;
  166.     struct sockaddr *dst;
  167. {
  168.     int len = 0;
  169.     queue_t *q = ifheads[ifp->if_unit].q;
  170.     struct mbuf *m;
  171.     mblk_t *mp;
  172.     int s;
  173.  
  174.     if (q == 0) {
  175.     m_freem(m0);
  176.     return(EHOSTDOWN);
  177.     }
  178.  
  179.     ifp->if_opackets++;
  180.     switch (dst->sa_family) {
  181.  
  182.     case AF_INET:
  183.     for (m = m0; m!= 0 ; m = m->m_next) {
  184.         len += m->m_len;
  185.     }
  186.     if ((mp = allocb(len, BPRI_MED)) == NULL) {
  187.         ifp->if_oerrors++;
  188.         m_freem(m0);
  189.         return(ENOSR);
  190.     }
  191.     for (m = m0; m!= 0 ; m = m->m_next) {
  192.         bcopy(mtod(m, u_char *),mp->b_wptr,m->m_len);
  193.         mp->b_wptr += m->m_len;
  194.     }
  195.     s = splstr();
  196.     if (q)
  197.         putnext(WR(q),mp);
  198.     else
  199.         freemsg(mp);
  200.     splx(s);
  201.     m_freem(m0);
  202.     break;
  203.     default:
  204.     m_freem(m0);
  205.     return(EAFNOSUPPORT);
  206.     }
  207.     return(0);
  208. }
  209.  
  210. static int if_in(q)
  211.     queue_t *q;
  212. {
  213.     mblk_t *mp, *bp;
  214.     int len;
  215.     struct mbuf *m;
  216.     struct ifnet *ifp = &((ifhead*)q->q_ptr)->i;
  217.     int offset;
  218.     int s;
  219.  
  220.  
  221.     while ((mp = getq(q)) != NULL) {
  222.     switch (mp->b_datap->db_type) {
  223.     default: /* paranoid */
  224.         putnext(q,mp);
  225.         continue;
  226.     case M_FLUSH:
  227.         if (*mp->b_rptr & FLUSHR)
  228.         flushq(q, FLUSHDATA);
  229.         putnext(q,mp);
  230.         continue;
  231.     case M_DATA:
  232.         MGET(m, M_DONTWAIT, MT_DATA);    /* get an MBUF */
  233.         if(!m) { /* dropit */
  234.         ifp->if_ierrors++;
  235.         freemsg(mp);
  236.         log(LOG_ERR,"slip: MGET FAILED\n");
  237.         continue;
  238.         }
  239.  
  240.         len = sizeof(ifp);
  241.         for (bp = mp; bp != 0 ; bp = bp->b_cont ) {
  242.         len += bp->b_wptr - bp->b_rptr;
  243.         }
  244.  
  245.         if (len > MLEN) {
  246.         if (len > MCLBYTES) {
  247.             ifp->if_ierrors++;
  248.             freemsg(mp);
  249.             m_freem(m);
  250.             continue;
  251.         }
  252.         MCLGET(m);
  253.         if (m->m_len == MLEN) {
  254.             ifp->if_ierrors++;
  255.             freemsg(mp);
  256.             m_freem(m);
  257.             log(LOG_ERR,"slip: MCLGET FAILED\n");
  258.             continue;
  259.         }
  260.  
  261.         }
  262.         /* assert mbuf big enough to hold whole message */
  263.  
  264.         /* copy pointer */
  265.         bcopy((char*)&ifp,mtod(m,char*),offset=sizeof(ifp));
  266.  
  267.         /* copy data */
  268.         for (bp = mp; bp != 0 ; bp = bp->b_cont ) {
  269.         bcopy(bp->b_rptr,mtod(m,char*)+offset,bp->b_wptr - bp->b_rptr);
  270.         offset += bp->b_wptr - bp->b_rptr;
  271.         bp->b_rptr = bp->b_wptr;
  272.         }
  273.         m->m_len = offset;
  274.  
  275.         ifp->if_ipackets++;
  276.         /* enqueue / drop */
  277.         s = splimp();
  278.         if (IF_QFULL(&ipintrq)) {
  279.         IF_DROP(&ipintrq);
  280.         ifp->if_ierrors++;
  281.         m_freem(m);
  282.         (void) splx(s);
  283.         log(LOG_ERR,"slip: IF_QFULL\n");
  284.         } else {
  285.         IF_ENQUEUE(&ipintrq, m);
  286.         schednetisr(NETISR_IP);
  287.         (void) splx(s);
  288.         }
  289.         freemsg(mp);
  290.     }
  291.     }
  292. }
  293.  
  294. static int if_ioc(ifp, cmd, data)
  295.     struct ifnet *ifp;
  296.     int cmd;
  297.     caddr_t data;
  298. {
  299.     struct ifaddr *ifa = (struct ifaddr *)data;
  300.     int s;
  301.     int error = 0;
  302.  
  303.     if (ifa == NULL)
  304.     return(EFAULT);
  305.     s = splimp();
  306.     switch (cmd) {
  307.     case SIOCSIFADDR:
  308.     switch (ifa->ifa_addr.sa_family) {
  309.     case AF_INET:
  310.         ifp->if_flags |= IFF_UP;
  311.         break;
  312.     default:
  313.         error = EAFNOSUPPORT;
  314.         break;
  315.     }
  316.     break;
  317.     case SIOCSIFDSTADDR:
  318.     switch (ifa->ifa_addr.sa_family) {
  319.     case AF_INET:
  320.         break;
  321.     default:
  322.         error = EAFNOSUPPORT;
  323.         break;
  324.     }
  325.     break;
  326.     default:
  327.     error = EINVAL;
  328.     }
  329.     splx(s);
  330.     return(error);
  331. }
  332. #endif
  333.