BSD 4_3_Net_2 release
[unix-history] / usr / src / sys / netccitt / pk_usrreq.c
index 4c20379..7bfcd0a 100644 (file)
@@ -7,23 +7,49 @@
  * the Laboratory for Computation Vision and the Computer Science Department
  * of the University of British Columbia.
  *
  * the Laboratory for Computation Vision and the Computer Science Department
  * of the University of British Columbia.
  *
- * %sccs.include.redist.c%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
  *
  *
- *     @(#)pk_usrreq.c 7.11 (Berkeley) %G%
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)pk_usrreq.c 7.16 (Berkeley) 6/27/91
  */
 
 #include "param.h"
 #include "systm.h"
 #include "mbuf.h"
 #include "socket.h"
  */
 
 #include "param.h"
 #include "systm.h"
 #include "mbuf.h"
 #include "socket.h"
-#include "protosw.h"
 #include "socketvar.h"
 #include "socketvar.h"
+#include "protosw.h"
 #include "errno.h"
 #include "ioctl.h"
 #include "errno.h"
 #include "ioctl.h"
-#include "user.h"
 #include "stat.h"
 
 #include "../net/if.h"
 #include "stat.h"
 
 #include "../net/if.h"
+#include "../net/route.h"
 
 #include "x25.h"
 #include "pk.h"
 
 #include "x25.h"
 #include "pk.h"
@@ -148,10 +174,7 @@ struct mbuf *control;
         *  After a receive, we should send a RR.
         */
        case PRU_RCVD: 
         *  After a receive, we should send a RR.
         */
        case PRU_RCVD: 
-               lcp -> lcd_rxcnt++;
-               lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RR);
-               pk_output (lcp);
-               /*pk_flowcontrol (lcp, sbspace (&so -> so_rcv) <= 0, 1);*/
+               pk_flowcontrol (lcp, /*sbspace (&so -> so_rcv) <= */ 0, 1);
                break;
 
        /* 
                break;
 
        /* 
@@ -179,10 +202,10 @@ struct mbuf *control;
                        register struct cmsghdr *ch = mtod (m, struct cmsghdr *);
                        control -> m_len -= sizeof (*ch);
                        control -> m_data += sizeof (*ch);
                        register struct cmsghdr *ch = mtod (m, struct cmsghdr *);
                        control -> m_len -= sizeof (*ch);
                        control -> m_data += sizeof (*ch);
-                       pk_ctloutput (PRCO_SETOPT, so, ch -> cmsg_level,
+                       error = pk_ctloutput (PRCO_SETOPT, so, ch -> cmsg_level,
                                        ch -> cmsg_type, &control);
                }
                                        ch -> cmsg_type, &control);
                }
-               if (m)
+               if (error == 0 && m)
                        error = pk_send (lcp, m);
                break;
 
                        error = pk_send (lcp, m);
                break;
 
@@ -269,18 +292,23 @@ release:
 /* 
  * If you want to use UBC X.25 level 3 in conjunction with some
  * other X.25 level 2 driver, have the ifp -> if_ioctl routine
 /* 
  * If you want to use UBC X.25 level 3 in conjunction with some
  * other X.25 level 2 driver, have the ifp -> if_ioctl routine
- * assign pk_start to pkp -> pk_start when called with SIOCSIFCONF_X25.
+ * assign pk_start to ia -> ia_start when called with SIOCSIFCONF_X25.
  */
 /* ARGSUSED */
 pk_start (lcp)
 register struct pklcd *lcp;
 {
  */
 /* ARGSUSED */
 pk_start (lcp)
 register struct pklcd *lcp;
 {
-       extern int pk_send ();
-
-       lcp -> lcd_send = pk_send;
-       return (pk_output (lcp));
+       pk_output (lcp);
+       return (0); /* XXX pk_output should return a value */
 }
 
 }
 
+#ifndef _offsetof
+#define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
+#endif
+struct sockaddr_x25 pk_sockmask = {
+_offsetof(struct sockaddr_x25, x25_addr[0]),
+0, -1};
+
 /*ARGSUSED*/
 pk_control (so, cmd, data, ifp)
 struct socket *so;
 /*ARGSUSED*/
 pk_control (so, cmd, data, ifp)
 struct socket *so;
@@ -312,8 +340,8 @@ register struct ifnet *ifp;
                return (0);
 
        case SIOCSIFCONF_X25:
                return (0);
 
        case SIOCSIFCONF_X25:
-               if (error = suser (u.u_cred, &u.u_acflag))
-                       return (error);
+               if ((so->so_state & SS_PRIV) == 0)
+                       return (EPERM);
                if (ifp == 0)
                        panic ("pk_control");
                if (ifa == (struct ifaddr *)0) {
                if (ifp == 0)
                        panic ("pk_control");
                if (ifa == (struct ifaddr *)0) {
@@ -331,49 +359,37 @@ register struct ifnet *ifp;
                        } else
                                ifp -> if_addrlist = &ia -> ia_ifa;
                        ifa = &ia -> ia_ifa;
                        } else
                                ifp -> if_addrlist = &ia -> ia_ifa;
                        ifa = &ia -> ia_ifa;
-                       ifa -> ifa_netmask = (struct sockaddr *)&ia -> ia_sockmask;
+                       ifa -> ifa_netmask = (struct sockaddr *)&pk_sockmask;
                        ifa -> ifa_addr = (struct sockaddr *)&ia -> ia_xc.xc_addr;
                        ifa -> ifa_addr = (struct sockaddr *)&ia -> ia_xc.xc_addr;
-                       ia -> ia_xcp = &ia -> ia_xc;
+                       ifa -> ifa_dstaddr = (struct sockaddr *)&ia -> ia_dstaddr; /* XXX */
                        ia -> ia_ifp = ifp;
                        ia -> ia_ifp = ifp;
-                       ia -> ia_pkcb.pk_ia = ia;
-                       ia -> ia_pkcb.pk_next = pkcbhead;
-                       ia -> ia_pkcb.pk_state = DTE_WAITING;
-                       ia -> ia_pkcb.pk_start = pk_start;
-                       pkcbhead = &ia -> ia_pkcb;
+                       ia -> ia_dstaddr.x25_family = AF_CCITT;
+                       ia -> ia_dstaddr.x25_len = pk_sockmask.x25_len;
+               } else {
+                       rtinit (ifa, (int)RTM_DELETE, 0);
                }
                old_maxlcn = ia -> ia_maxlcn;
                ia -> ia_xc = ifr -> ifr_xc;
                }
                old_maxlcn = ia -> ia_maxlcn;
                ia -> ia_xc = ifr -> ifr_xc;
-               if (ia -> ia_chan && (ia -> ia_maxlcn != old_maxlcn)) {
-                       pk_restart (&ia -> ia_pkcb, X25_RESTART_NETWORK_CONGESTION);
-                       dev_lcp = ia -> ia_chan[0];
-                       free ((caddr_t)ia -> ia_chan, M_IFADDR);
-                       ia -> ia_chan = 0;
-               }
-               if (ia -> ia_chan == 0) {
-                       n = (ia -> ia_maxlcn + 1) * sizeof (struct pklcd *);
-                       ia -> ia_chan = (struct pklcd **) malloc (n, M_IFADDR, M_WAITOK);
-                       if (ia -> ia_chan) {
-                               bzero ((caddr_t)ia -> ia_chan, n);
-                               if (dev_lcp == 0)
-                                       dev_lcp = pk_attach ((struct socket *)0);
-                               ia -> ia_chan[0] = dev_lcp;
-                               dev_lcp -> lcd_state = READY;
-                               dev_lcp -> lcd_pkp = &ia -> ia_pkcb;
-                       } else {
-                               if (dev_lcp)
-                                       pk_close (dev_lcp);
-                               return (ENOBUFS);
-                       }
+               ia -> ia_dstaddr.x25_net = ia -> ia_xc.xc_addr.x25_net;
+               if (ia -> ia_maxlcn != old_maxlcn && old_maxlcn != 0) {
+                       /* VERY messy XXX */
+                       register struct pkcb *pkp;
+                       for (pkp = pkcbhead; pkp; pkp = pkp -> pk_next)
+                               if (pkp -> pk_ia == ia)
+                                       pk_resize (pkp);
                }
                /*
                 * Give the interface a chance to initialize if this
                 * is its first address, and to validate the address.
                 */
                }
                /*
                 * Give the interface a chance to initialize if this
                 * is its first address, and to validate the address.
                 */
+               ia -> ia_start = pk_start;
                s = splimp();
                if (ifp -> if_ioctl)
                        error = (*ifp -> if_ioctl)(ifp, SIOCSIFCONF_X25, ifa);
                if (error)
                        ifp -> if_flags &= ~IFF_UP;
                s = splimp();
                if (ifp -> if_ioctl)
                        error = (*ifp -> if_ioctl)(ifp, SIOCSIFCONF_X25, ifa);
                if (error)
                        ifp -> if_flags &= ~IFF_UP;
+               else
+                       error = rtinit (ifa, (int)RTM_ADD, RTF_UP);
                splx (s);
                return (error);
 
                splx (s);
                return (error);
 
@@ -391,35 +407,43 @@ int cmd, level, optname;
 {
        register struct mbuf *m = *mp;
        register struct pklcd *lcp = (struct pklcd *) so -> so_pcb;
 {
        register struct mbuf *m = *mp;
        register struct pklcd *lcp = (struct pklcd *) so -> so_pcb;
-       int error;
+       int error = EOPNOTSUPP;
 
 
+       if (m == 0)
+               return (EINVAL);
        if (cmd == PRCO_SETOPT) switch (optname) {
        if (cmd == PRCO_SETOPT) switch (optname) {
-       case PK_ACCTFILE:
-               if (m == 0)
-                       return (EINVAL);
-               if (m -> m_len)
-                       error = pk_accton (mtod (m, char *));
-               else
-                       error = pk_accton ((char *)0);
-               (void) m_freem (m);
-               *mp = 0;
-               return (error);
-
        case PK_FACILITIES:
                if (m == 0)
                        return (EINVAL);
                lcp -> lcd_facilities = m;
                *mp = 0;
                return (0);
        case PK_FACILITIES:
                if (m == 0)
                        return (EINVAL);
                lcp -> lcd_facilities = m;
                *mp = 0;
                return (0);
+
+       case PK_ACCTFILE:
+               if ((so->so_state & SS_PRIV) == 0)
+                       error = EPERM;
+               else if (m -> m_len)
+                       error = pk_accton (mtod (m, char *));
+               else
+                       error = pk_accton ((char *)0);
+               break;
+
+       case PK_RTATTACH:
+               error = pk_rtattach (so, m);
+               break;
+           
+       case PK_PRLISTEN:
+               error = pk_user_protolisten (mtod (m, u_char *));
        }
        if (*mp) {
                (void) m_freem (*mp);
                *mp = 0;
        }
        }
        if (*mp) {
                (void) m_freem (*mp);
                *mp = 0;
        }
-       return (EOPNOTSUPP);
+       return (error);
 
 }
 
 
 }
 
+
 /*
  * Do an in-place conversion of an "old style"
  * socket address to the new style
 /*
  * Do an in-place conversion of an "old style"
  * socket address to the new style
@@ -439,22 +463,25 @@ register struct mbuf *m;
        bzero ((caddr_t)newp, sizeof (*newp));
 
        newp -> x25_family = AF_CCITT;
        bzero ((caddr_t)newp, sizeof (*newp));
 
        newp -> x25_family = AF_CCITT;
+       newp -> x25_len = sizeof(*newp);
        newp -> x25_opts.op_flags = (oldp -> xaddr_facilities & X25_REVERSE_CHARGE)
                | X25_MQBIT | X25_OLDSOCKADDR;
        if (oldp -> xaddr_facilities & XS_HIPRIO)       /* Datapac specific */
                newp -> x25_opts.op_psize = X25_PS128;
        bcopy ((caddr_t)oldp -> xaddr_addr, newp -> x25_addr,
        newp -> x25_opts.op_flags = (oldp -> xaddr_facilities & X25_REVERSE_CHARGE)
                | X25_MQBIT | X25_OLDSOCKADDR;
        if (oldp -> xaddr_facilities & XS_HIPRIO)       /* Datapac specific */
                newp -> x25_opts.op_psize = X25_PS128;
        bcopy ((caddr_t)oldp -> xaddr_addr, newp -> x25_addr,
-               (unsigned)min (oldp -> xaddr_len, sizeof (newp -> x25_addr) - 1));
-       bcopy ((caddr_t)oldp -> xaddr_proto, newp -> x25_udata, 4);
-       newp -> x25_udlen = 4;
-
+              (unsigned)min (oldp -> xaddr_len, sizeof (newp -> x25_addr) - 1));
+       if (bcmp ((caddr_t)oldp -> xaddr_proto, newp -> x25_udata, 4) != 0) {
+               bcopy ((caddr_t)oldp -> xaddr_proto, newp -> x25_udata, 4);
+               newp -> x25_udlen = 4;
+       }
        ocp = (caddr_t)oldp -> xaddr_userdata;
        ncp = newp -> x25_udata + 4;
        while (*ocp && ocp < (caddr_t)oldp -> xaddr_userdata + 12) {
        ocp = (caddr_t)oldp -> xaddr_userdata;
        ncp = newp -> x25_udata + 4;
        while (*ocp && ocp < (caddr_t)oldp -> xaddr_userdata + 12) {
+               if (newp -> x25_udlen == 0)
+                       newp -> x25_udlen = 4;
                *ncp++ = *ocp++;
                newp -> x25_udlen++;
        }
                *ncp++ = *ocp++;
                newp -> x25_udlen++;
        }
-
        bcopy ((caddr_t)newp, mtod (m, char *), sizeof (*newp));
        m -> m_len = sizeof (*newp);
 }
        bcopy ((caddr_t)newp, mtod (m, char *), sizeof (*newp));
        m -> m_len = sizeof (*newp);
 }
@@ -488,8 +515,9 @@ register struct mbuf *m;
        }
 
        bcopy (newp -> x25_udata, (caddr_t)oldp -> xaddr_proto, 4);
        }
 
        bcopy (newp -> x25_udata, (caddr_t)oldp -> xaddr_proto, 4);
-       bcopy (newp -> x25_udata + 4, (caddr_t)oldp -> xaddr_userdata,
-               (unsigned)(newp -> x25_udlen - 4));
+       if (newp -> x25_udlen > 4)
+               bcopy (newp -> x25_udata + 4, (caddr_t)oldp -> xaddr_userdata,
+                       (unsigned)(newp -> x25_udlen - 4));
 
        bcopy ((caddr_t)oldp, mtod (m, char *), sizeof (*oldp));
        m -> m_len = sizeof (*oldp);
 
        bcopy ((caddr_t)oldp, mtod (m, char *), sizeof (*oldp));
        m -> m_len = sizeof (*oldp);
@@ -514,12 +542,14 @@ struct mbuf *m;
        }
        return (0);
 }
        }
        return (0);
 }
+
 pk_send (lcp, m)
 struct pklcd *lcp;
 register struct mbuf *m;
 {
        int mqbit = 0, error = 0;
        register struct x25_packet *xp;
 pk_send (lcp, m)
 struct pklcd *lcp;
 register struct mbuf *m;
 {
        int mqbit = 0, error = 0;
        register struct x25_packet *xp;
+       register struct socket *so;
 
        if (m -> m_type == MT_OOBDATA) {
                if (lcp -> lcd_intrconf_pending)
 
        if (m -> m_type == MT_OOBDATA) {
                if (lcp -> lcd_intrconf_pending)
@@ -529,13 +559,14 @@ register struct mbuf *m;
                M_PREPEND(m, PKHEADERLN, M_WAITOK);
                if (m == 0 || error)
                        goto bad;
                M_PREPEND(m, PKHEADERLN, M_WAITOK);
                if (m == 0 || error)
                        goto bad;
-               lcp -> lcd_template = m;
                *(mtod (m, octet *)) = 0;
                xp = mtod (m, struct x25_packet *);
                xp -> fmt_identifier = 1;
                xp -> packet_type = X25_INTERRUPT;
                SET_LCN(xp, lcp -> lcd_lcn);
                *(mtod (m, octet *)) = 0;
                xp = mtod (m, struct x25_packet *);
                xp -> fmt_identifier = 1;
                xp -> packet_type = X25_INTERRUPT;
                SET_LCN(xp, lcp -> lcd_lcn);
-               return (pk_output (lcp));
+               sbinsertoob ( (so = lcp -> lcd_so) ?
+                       &so -> so_snd : &lcp -> lcd_sb, m);
+               goto send;
        }
        /*
         * Application has elected (at call setup time) to prepend
        }
        /*
         * Application has elected (at call setup time) to prepend
@@ -552,8 +583,10 @@ register struct mbuf *m;
                m -> m_data++;
                m -> m_pkthdr.len--;
        }
                m -> m_data++;
                m -> m_pkthdr.len--;
        }
-       if ((error = pk_fragment (lcp, m, mqbit & 0x80, mqbit & 0x40, 1)) == 0)
-               error = pk_output (lcp);
+       error = pk_fragment (lcp, m, mqbit & 0x80, mqbit & 0x40, 1);
+send:
+       if (error == 0 && lcp -> lcd_state == DATA_TRANSFER)
+               lcp -> lcd_send (lcp); /* XXXXXXXXX fix pk_output!!! */
        return (error);
 bad:
        if (m)
        return (error);
 bad:
        if (m)