BSD 4_3_Net_2 release
[unix-history] / usr / src / sys / netccitt / pk_subr.c
index 015bd78..e1bf921 100644 (file)
@@ -7,9 +7,35 @@
  * 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_subr.c   7.10 (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_subr.c   7.16 (Berkeley) 6/6/91
  */
 
 #include "param.h"
  */
 
 #include "param.h"
@@ -47,18 +73,19 @@ struct socket *so;
 {
        register struct pklcd *lcp;
        register int error = ENOBUFS;
 {
        register struct pklcd *lcp;
        register int error = ENOBUFS;
+       int pk_output();
 
        MALLOC(lcp, struct pklcd *, sizeof (*lcp), M_PCB, M_NOWAIT);
        if (lcp) {
                bzero ((caddr_t)lcp, sizeof (*lcp));
                insque (&lcp -> lcd_q, &pklcd_q);
 
        MALLOC(lcp, struct pklcd *, sizeof (*lcp), M_PCB, M_NOWAIT);
        if (lcp) {
                bzero ((caddr_t)lcp, sizeof (*lcp));
                insque (&lcp -> lcd_q, &pklcd_q);
+               lcp -> lcd_state = READY;
+               lcp -> lcd_send = pk_output;
                if (so) {
                        error = soreserve (so, pk_sendspace, pk_recvspace);
                        lcp -> lcd_so = so;
                        if (so -> so_options & SO_ACCEPTCONN)
                                lcp -> lcd_state = LISTEN;
                if (so) {
                        error = soreserve (so, pk_sendspace, pk_recvspace);
                        lcp -> lcd_so = so;
                        if (so -> so_options & SO_ACCEPTCONN)
                                lcp -> lcd_state = LISTEN;
-                       else
-                               lcp -> lcd_state = READY;
                } else
                        sbreserve (&lcp -> lcd_sb, pk_sendspace);
        }
                } else
                        sbreserve (&lcp -> lcd_sb, pk_sendspace);
        }
@@ -157,7 +184,7 @@ int lcn, type;
         * be enough room for the link level to insert its header.
         */
        m -> m_data += max_linkhdr;
         * be enough room for the link level to insert its header.
         */
        m -> m_data += max_linkhdr;
-       m -> m_len = PKHEADERLN;
+       m -> m_pkthdr.len = m -> m_len = PKHEADERLN;
 
        xp = mtod (m, struct x25_packet *);
        *(long *)xp = 0;                /* ugly, but fast */
 
        xp = mtod (m, struct x25_packet *);
        *(long *)xp = 0;                /* ugly, but fast */
@@ -208,7 +235,7 @@ int restart_cause;
        pkp -> pk_state = DTE_SENT_RESTART;
        lcp = pkp -> pk_chan[0];
        m = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESTART);
        pkp -> pk_state = DTE_SENT_RESTART;
        lcp = pkp -> pk_chan[0];
        m = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESTART);
-       m -> m_len += 2;
+       m -> m_pkthdr.len = m -> m_len += 2;
        mtod (m, struct x25_packet *) -> packet_data = 0;       /* DTE only */
        mtod (m, octet *)[4]  = restart_cause;
        pk_output (lcp);
        mtod (m, struct x25_packet *) -> packet_data = 0;       /* DTE only */
        mtod (m, octet *)[4]  = restart_cause;
        pk_output (lcp);
@@ -330,7 +357,8 @@ int (*callee) ();
                        sa -> x25_udata[0] = spi;
                        lcp -> lcd_upper = callee;
                        lcp -> lcd_flags = X25_MBS_HOLD;
                        sa -> x25_udata[0] = spi;
                        lcp -> lcd_upper = callee;
                        lcp -> lcd_flags = X25_MBS_HOLD;
-                       error = pk_bind (lcp, nam) || pk_listen (lcp);
+                       if ((error = pk_bind (lcp, nam)) == 0)
+                               error = pk_listen (lcp);
                        (void) m_free (nam);
                }
                if (error)
                        (void) m_free (nam);
                }
                if (error)
@@ -367,7 +395,7 @@ register struct sockaddr_x25 *sa;
        else
                sa -> x25_opts.op_wsize = lcp -> lcd_windowsize;
        sa -> x25_net = pkp -> pk_xcp -> xc_addr.x25_net;
        else
                sa -> x25_opts.op_wsize = lcp -> lcd_windowsize;
        sa -> x25_net = pkp -> pk_xcp -> xc_addr.x25_net;
-       lcp -> lcd_flags = sa -> x25_opts.op_flags;
+       lcp -> lcd_flags |= sa -> x25_opts.op_flags;
        lcp -> lcd_stime = time.tv_sec;
 }
 
        lcp -> lcd_stime = time.tv_sec;
 }
 
@@ -386,6 +414,10 @@ register struct sockaddr_x25 *sa;
                /*
                 * use first net configured (last in list
                 * headed by pkcbhead) if net is zero
                /*
                 * use first net configured (last in list
                 * headed by pkcbhead) if net is zero
+                *
+                * This is clearly bogus for many llc2's sharing
+                * the same xcp; we will replace this with a
+                * routing lookup.
                 */
                if (sa -> x25_net == 0 && pkp -> pk_next == 0)
                        break;
                 */
                if (sa -> x25_net == 0 && pkp -> pk_next == 0)
                        break;
@@ -404,9 +436,13 @@ register struct sockaddr_x25 *sa;
                soisconnecting (lcp -> lcd_so);
        lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CALL);
        pk_callrequest (lcp, lcp -> lcd_ceaddr, pkp -> pk_xcp);
                soisconnecting (lcp -> lcd_so);
        lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_CALL);
        pk_callrequest (lcp, lcp -> lcd_ceaddr, pkp -> pk_xcp);
-       return (*pkp -> pk_start) (lcp);
+       return (*pkp -> pk_ia -> ia_start) (lcp);
 }
 
 }
 
+struct bcdinfo {
+       octet *cp;
+       unsigned posn;
+};
 /* 
  *  Build the rest of the CALL REQUEST packet. Fill in calling
  *  address, facilities fields and the user data field.
 /* 
  *  Build the rest of the CALL REQUEST packet. Fill in calling
  *  address, facilities fields and the user data field.
@@ -420,39 +456,30 @@ register struct x25config *xcp;
        register struct x25_calladdr *a;
        register struct mbuf *m = lcp -> lcd_template;
        register struct x25_packet *xp = mtod (m, struct x25_packet *);
        register struct x25_calladdr *a;
        register struct mbuf *m = lcp -> lcd_template;
        register struct x25_packet *xp = mtod (m, struct x25_packet *);
-       unsigned posn = 0;
-       octet *cp;
+       struct bcdinfo b;
 
        if (lcp -> lcd_flags & X25_DBIT)
                xp -> d_bit = 1;
        a = (struct x25_calladdr *) &xp -> packet_data;
 
        if (lcp -> lcd_flags & X25_DBIT)
                xp -> d_bit = 1;
        a = (struct x25_calladdr *) &xp -> packet_data;
-       a -> calling_addrlen = strlen (xcp -> xc_addr.x25_addr);
-       a -> called_addrlen = strlen (sa -> x25_addr);
-       cp = (octet *) a -> address_field;
-       to_bcd (&cp, (int)a -> called_addrlen, sa -> x25_addr, &posn);
-       to_bcd (&cp, (int)a -> calling_addrlen, xcp -> xc_addr.x25_addr, &posn);
-       if (posn & 0x01)
-               *cp++ &= 0xf0;
-       m -> m_len += cp - (octet *) a;
+       b.cp = (octet *) a -> address_field;
+       b.posn = 0;
+       a -> called_addrlen = to_bcd (&b, sa, xcp);
+       a -> calling_addrlen = to_bcd (&b, &xcp -> xc_addr, xcp);
+       if (b.posn & 0x01)
+               *b.cp++ &= 0xf0;
+       m -> m_pkthdr.len = m -> m_len += b.cp - (octet *) a;
 
        if (lcp -> lcd_facilities) {
                m -> m_pkthdr.len += 
 
        if (lcp -> lcd_facilities) {
                m -> m_pkthdr.len += 
-                       (m -> m_next = lcp -> lcd_facilities) -> m_len;
+                       (m -> m_next = lcp -> lcd_facilities) -> m_pkthdr.len;
                lcp -> lcd_facilities = 0;
        } else
                lcp -> lcd_facilities = 0;
        } else
-               build_facilities (m, sa, (int)xcp -> xc_type);
+               pk_build_facilities (m, sa, (int)xcp -> xc_type);
 
        m_copyback (m, m -> m_pkthdr.len, sa -> x25_udlen, sa -> x25_udata);
 
        m_copyback (m, m -> m_pkthdr.len, sa -> x25_udlen, sa -> x25_udata);
-#ifdef ANDREW
-       printf ("call: ");
-       for (cp = mtod (m, octet *), posn = 0; posn < m -> m_len; ++posn)
-               printf ("%x ", *cp++);
-       printf ("\n");
-#endif
 }
 
 }
 
-static
-build_facilities (m, sa, type)
+pk_build_facilities (m, sa, type)
 register struct mbuf *m;
 struct sockaddr_x25 *sa;
 {
 register struct mbuf *m;
 struct sockaddr_x25 *sa;
 {
@@ -488,17 +515,41 @@ struct sockaddr_x25 *sa;
        m -> m_pkthdr.len = (m -> m_len += *cp + 1);
 }
 
        m -> m_pkthdr.len = (m -> m_len += *cp + 1);
 }
 
-to_bcd (a, len, x, posn)
-register octet **a;
-register char *x;
-register int len;
-register unsigned *posn;
+to_bcd (b, sa, xcp)
+register struct bcdinfo *b;
+struct sockaddr_x25 *sa;
+register struct x25config *xcp;
 {
 {
-       while (--len >= 0)
-               if ((*posn)++ & 0x01)
-                       *(*a)++ |= *x++ & 0x0F;
+       register char *x = sa -> x25_addr;
+       unsigned start = b -> posn;
+       /*
+        * The nodnic and prepnd0 stuff looks tedious,
+        * but it does allow full X.121 addresses to be used,
+        * which is handy for routing info (& OSI type 37 addresses).
+        */
+       if (xcp -> xc_addr.x25_net && (xcp -> xc_nodnic || xcp -> xc_prepnd0)) {
+               char dnicname[sizeof(long) * NBBY/3 + 2];
+               register char *p = dnicname;
+
+               sprintf (p, "%d", xcp -> xc_addr.x25_net & 0x7fff);
+               for (; *p; p++) /* *p == 0 means dnic matched */
+                       if ((*p ^ *x++) & 0x0f)
+                               break;
+               if (*p || xcp -> xc_nodnic == 0)
+                       x = sa -> x25_addr;
+               if (*p && xcp -> xc_prepnd0) {
+                       if ((b -> posn)++ & 0x01)
+                               *(b -> cp)++;
+                       else
+                               *(b -> cp) = 0;
+               }
+       }
+       while (*x)
+               if ((b -> posn)++ & 0x01)
+                       *(b -> cp)++ |= *x++ & 0x0F;
                else
                else
-                       **a = *x++ << 4;
+                       *(b -> cp) = *x++ << 4;
+       return ((b -> posn) - start);
 }
 
 /* 
 }
 
 /* 
@@ -562,7 +613,8 @@ register struct pklcd *lcp;
            (forced == 0 && lcp -> lcd_rxrnr_condition == inhibit))
                return;
        lcp -> lcd_rxrnr_condition = inhibit;
            (forced == 0 && lcp -> lcd_rxrnr_condition == inhibit))
                return;
        lcp -> lcd_rxrnr_condition = inhibit;
-       lcp -> lcd_template = pk_template (lcp -> lcd_lcn, inhibit ? RNR : RR);
+       lcp -> lcd_template =
+               pk_template (lcp -> lcd_lcn, inhibit ? X25_RNR : X25_RR);
        pk_output (lcp);
 }
 
        pk_output (lcp);
 }
 
@@ -594,7 +646,7 @@ register struct pklcd *lcp;
        lcp -> lcd_output_window = lcp -> lcd_input_window =
                lcp -> lcd_last_transmitted_pr = 0;
        m = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESET);
        lcp -> lcd_output_window = lcp -> lcd_input_window =
                lcp -> lcd_last_transmitted_pr = 0;
        m = lcp -> lcd_template = pk_template (lcp -> lcd_lcn, X25_RESET);
-       m -> m_len += 2;
+       m -> m_pkthdr.len = m -> m_len += 2;
        mtod (m, struct x25_packet *) -> packet_data = 0;
        mtod (m, octet *)[4] = diagnostic;
        pk_output (lcp);
        mtod (m, struct x25_packet *) -> packet_data = 0;
        mtod (m, octet *)[4] = diagnostic;
        pk_output (lcp);
@@ -689,8 +741,6 @@ unsigned pr;
 
        if (so && ((so -> so_snd.sb_flags & SB_WAIT) || so -> so_snd.sb_sel))
                sowwakeup (so);
 
        if (so && ((so -> so_snd.sb_flags & SB_WAIT) || so -> so_snd.sb_sel))
                sowwakeup (so);
-       if (lcp -> lcd_upper)
-               (*lcp -> lcd_upper) (lcp, 0);
 
        return (PACKET_OK);
 }
 
        return (PACKET_OK);
 }
@@ -779,7 +829,7 @@ register struct x25_packet *xp;
                break;
 
        case X25_DIAGNOSTIC:
                break;
 
        case X25_DIAGNOSTIC:
-               type = DIAGNOSTIC;
+               type = DIAG_TYPE;
                break;
 
        default: 
                break;
 
        default: 
@@ -842,7 +892,8 @@ register struct x25_packet *xp;
        pk_message(LCN(xp), lcp -> lcd_pkp, "reset code 0x%x, diagnostic 0x%x",
                        xp -> packet_data, 4[(u_char *)xp]);
                        
        pk_message(LCN(xp), lcp -> lcd_pkp, "reset code 0x%x, diagnostic 0x%x",
                        xp -> packet_data, 4[(u_char *)xp]);
                        
-       lcp -> lcd_so -> so_error = Reset_cause[code];
+       if (lcp -> lcd_so)
+               lcp -> lcd_so -> so_error = Reset_cause[code];
 }
 
 #define MAXCLEARCAUSE  25
 }
 
 #define MAXCLEARCAUSE  25
@@ -867,7 +918,8 @@ register struct x25_packet *xp;
 
        if (code > MAXCLEARCAUSE)
                code = 5;       /* EXRNCG */
 
        if (code > MAXCLEARCAUSE)
                code = 5;       /* EXRNCG */
-       lcp -> lcd_so -> so_error = Clear_cause[code];
+       if (lcp -> lcd_so)
+               lcp -> lcd_so -> so_error = Clear_cause[code];
 }
 
 char *
 }
 
 char *
@@ -899,17 +951,6 @@ char *fmt;
        printf ("\n");
 }
 
        printf ("\n");
 }
 
-pk_ifattach (ia, lloutput, llnext)
-register struct x25_ifaddr *ia;
-int (*lloutput) ();
-caddr_t llnext;
-{
-       /* this is here because you can't include both pk_var and hd_var */
-       /* this will probably be replace by a streams gluing mechanism */
-       ia -> ia_pkcb.pk_lloutput = lloutput;
-       ia -> ia_pkcb.pk_llnext = llnext;
-}
-
 pk_fragment (lcp, m0, qbit, mbit, wait)
 struct mbuf *m0;
 register struct pklcd *lcp;
 pk_fragment (lcp, m0, qbit, mbit, wait)
 struct mbuf *m0;
 register struct pklcd *lcp;
@@ -921,7 +962,7 @@ register struct pklcd *lcp;
        int totlen, psize = 1 << (lcp -> lcd_packetsize);
 
        if (m == 0)
        int totlen, psize = 1 << (lcp -> lcd_packetsize);
 
        if (m == 0)
-               return;
+               return 0;
        if (m -> m_flags & M_PKTHDR == 0)
                panic ("pk_fragment");
        totlen = m -> m_pkthdr.len;
        if (m -> m_flags & M_PKTHDR == 0)
                panic ("pk_fragment");
        totlen = m -> m_pkthdr.len;
@@ -977,12 +1018,13 @@ register struct mbuf *m0;
 int len0;
 {
        register struct mbuf *m, *n;
 int len0;
 {
        register struct mbuf *m, *n;
-       unsigned len = len0;
+       unsigned len = len0, remain;
 
        for (m = m0; m && len > m -> m_len; m = m -> m_next)
                len -= m -> m_len;
        if (m == 0)
                return (0);
 
        for (m = m0; m && len > m -> m_len; m = m -> m_next)
                len -= m -> m_len;
        if (m == 0)
                return (0);
+       remain = m -> m_len - len;
        if (m0 -> m_flags & M_PKTHDR) {
                MGETHDR(n, wait, m0 -> m_type);
                if (n == 0)
        if (m0 -> m_flags & M_PKTHDR) {
                MGETHDR(n, wait, m0 -> m_type);
                if (n == 0)
@@ -992,7 +1034,7 @@ int len0;
                m0 -> m_pkthdr.len = len0;
                if (m -> m_flags & M_EXT)
                        goto extpacket;
                m0 -> m_pkthdr.len = len0;
                if (m -> m_flags & M_EXT)
                        goto extpacket;
-               if (len > MHLEN) {
+               if (remain > MHLEN) {
                        /* m can't be the lead packet */
                        MH_ALIGN(n, 0);
                        n -> m_next = m_split (m, len, wait);
                        /* m can't be the lead packet */
                        MH_ALIGN(n, 0);
                        n -> m_next = m_split (m, len, wait);
@@ -1002,30 +1044,28 @@ int len0;
                        } else
                                return (n);
                } else
                        } else
                                return (n);
                } else
-                       MH_ALIGN(n, len);
-       } else if (len == m -> m_len) {
+                       MH_ALIGN(n, remain);
+       } else if (remain == 0) {
                n = m -> m_next;
                m -> m_next = 0;
                return (n);
                n = m -> m_next;
                m -> m_next = 0;
                return (n);
+       } else {
+               MGET(n, wait, m -> m_type);
+               if (n == 0)
+                       return (0);
+               M_ALIGN(n, remain);
        }
 extpacket:
        }
 extpacket:
-       len = m -> m_len - len;         /* remainder to be copied */
-       m -> m_len -= len;              /* now equals original len */
        if (m -> m_flags & M_EXT) {
                n -> m_flags |= M_EXT;
                n -> m_ext = m -> m_ext;
                mclrefcnt[mtocl (m -> m_ext.ext_buf)]++;
        if (m -> m_flags & M_EXT) {
                n -> m_flags |= M_EXT;
                n -> m_ext = m -> m_ext;
                mclrefcnt[mtocl (m -> m_ext.ext_buf)]++;
-               n -> m_data = m -> m_data + m -> m_len;
+               n -> m_data = m -> m_data + len;
        } else {
        } else {
-               MGET(n, wait, m -> m_type);
-               if (n == 0) {
-                       m -> m_len += len;
-                       return (0);
-               }
-               M_ALIGN(n, len);
-               bcopy (mtod (m, caddr_t), mtod (n, caddr_t), len);
+               bcopy (mtod (m, caddr_t) + len, mtod (n, caddr_t), remain);
        }
        }
-       n -> m_len = len;
+       n -> m_len = remain;
+       m -> m_len = len;
        n -> m_next = m -> m_next;
        m -> m_next = 0;
        return (n);
        n -> m_next = m -> m_next;
        m -> m_next = 0;
        return (n);