only delete space used by inode, on inode deletion; required
[unix-history] / usr / src / sys / netiso / if_cons.c
index b89745f..6a61cd1 100644 (file)
@@ -1,3 +1,12 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * %sccs.include.redist.c%
+ *
+ *     @(#)if_cons.c   7.11 (Berkeley) %G%
+ */
+
 /***********************************************************
                Copyright IBM Corporation 1987
 
 /***********************************************************
                Copyright IBM Corporation 1987
 
@@ -27,15 +36,10 @@ SOFTWARE.
 /*
  * $Header: if_cons.c,v 4.7 88/08/11 15:52:55 nhall Exp $
  * $Source: /usr/argo/sys/netiso/RCS/if_cons.c,v $
 /*
  * $Header: if_cons.c,v 4.7 88/08/11 15:52:55 nhall Exp $
  * $Source: /usr/argo/sys/netiso/RCS/if_cons.c,v $
- *     @(#)if_cons.c   7.7 (Berkeley) %G%
  *
  * cons.c - Connection Oriented Network Service:
  * including support for a) user transport-level service, 
  *     b) COSNS below CLNP, and c) CONS below TP.
  *
  * cons.c - Connection Oriented Network Service:
  * including support for a) user transport-level service, 
  *     b) COSNS below CLNP, and c) CONS below TP.
-
-#ifndef lint
-static char *rcsid = "$Header: if_cons.c,v 4.7 88/08/11 15:52:55 nhall Exp $";
-#endif lint
  */
 
 #ifdef TPCONS
  */
 
 #ifdef TPCONS
@@ -143,17 +147,8 @@ extern     struct ifaddr   *ifa_ifwithnet();
 
 extern struct ifaddr   *ifa_ifwithaddr();
 
 
 extern struct ifaddr   *ifa_ifwithaddr();
 
-Static  struct socket  dummysocket; /* for use by cosns */
-
 extern struct  isopcb  tp_isopcb; /* chain of all TP pcbs */
 extern struct  isopcb  tp_isopcb; /* chain of all TP pcbs */
-struct isopcb                  tp_incoming_pending;  /* incoming connections
-                                                                               for TP, pending */
 
 
-struct isopcb  *Xpcblist[] =  {
-       &tp_incoming_pending,
-       &tp_isopcb,
-       (struct isopcb *)0
-};
 
 Static         int parse_facil(), NSAPtoDTE(), make_partial_x25_packet();
 Static int FACILtoNSAP(), DTEtoNSAP();
 
 Static         int parse_facil(), NSAPtoDTE(), make_partial_x25_packet();
 Static int FACILtoNSAP(), DTEtoNSAP();
@@ -289,32 +284,28 @@ cons_init()
 #endif
 }
 
 #endif
 }
 
-tp_incoming(lcp, m0)
+tp_incoming(lcp, m)
 struct pklcd *lcp;
 struct pklcd *lcp;
-struct mbuf *m0;
+register struct mbuf *m;
 {
 {
-       register struct mbuf *m = m0->m_next; /* m0 has calling sockaddr_x25 */
        register struct isopcb *isop;
        register struct isopcb *isop;
-       extern struct isopcb tp_isopcb;
        int cons_tpinput();
 
        int cons_tpinput();
 
-       if (iso_pcballoc((struct socket *)0, &tp_incoming_pending)) {
-               m_freem(m);
-               pk_clear(lcp);
+       if (iso_pcballoc((struct socket *)0, &tp_isopcb)) {
+               pk_close(lcp);
                return;
        }
                return;
        }
-       isop = tp_incoming_pending.isop_next;
-       pk_output(lcp); /* Confirms call */
+       isop = tp_isopcb.isop_next;
        lcp->lcd_upper = cons_tpinput;
        lcp->lcd_upnext = (caddr_t)isop;
        lcp->lcd_upper = cons_tpinput;
        lcp->lcd_upnext = (caddr_t)isop;
+       lcp->lcd_send(lcp); /* Confirms call */
        isop->isop_chan = (caddr_t)lcp;
        isop->isop_laddr = &isop->isop_sladdr;
        isop->isop_faddr = &isop->isop_sfaddr;
        DTEtoNSAP(isop->isop_laddr, &lcp->lcd_laddr);
        DTEtoNSAP(isop->isop_faddr, &lcp->lcd_faddr);
        isop->isop_chan = (caddr_t)lcp;
        isop->isop_laddr = &isop->isop_sladdr;
        isop->isop_faddr = &isop->isop_sfaddr;
        DTEtoNSAP(isop->isop_laddr, &lcp->lcd_laddr);
        DTEtoNSAP(isop->isop_faddr, &lcp->lcd_faddr);
-       parse_facil(isop, lcp, &(mtod(m, struct x25_packet *)->packet_data),
+       parse_facil(lcp, isop, &(mtod(m, struct x25_packet *)->packet_data),
                m->m_pkthdr.len - PKHEADERLN);
                m->m_pkthdr.len - PKHEADERLN);
-       m_freem(m);
 }
 
 cons_tpinput(lcp, m0)
 }
 
 cons_tpinput(lcp, m0)
@@ -323,32 +314,44 @@ struct pklcd *lcp;
 {
        register struct isopcb *isop = (struct isopcb *)lcp->lcd_upnext;
        register struct x25_packet *xp;
 {
        register struct isopcb *isop = (struct isopcb *)lcp->lcd_upnext;
        register struct x25_packet *xp;
-       int cmd;
+       int cmd, ptype = CLEAR;
 
 
+       if (isop == 0)
+               return;
        if (m0 == 0)
                goto dead;
        switch(m0->m_type) {
        case MT_DATA:
        case MT_OOBDATA:
        if (m0 == 0)
                goto dead;
        switch(m0->m_type) {
        case MT_DATA:
        case MT_OOBDATA:
-               tpcons_input(m0, isop->isop_faddr, isop->isop_laddr,
-                       (struct socket *)0, (caddr_t)lcp);
+               tpcons_input(m0, isop->isop_faddr, isop->isop_laddr, (caddr_t)lcp);
+               return;
 
        case MT_CONTROL:
 
        case MT_CONTROL:
-               switch (pk_decode(mtod(m0, struct x25_packet *))) {
-               default:
-                       return;
+               switch (ptype = pk_decode(mtod(m0, struct x25_packet *))) {
 
                case RR:
                        cmd = PRC_CONS_SEND_DONE;
                        break;
 
 
                case RR:
                        cmd = PRC_CONS_SEND_DONE;
                        break;
 
+               case CALL_ACCEPTED:
+                       if (lcp->lcd_sb.sb_mb)
+                               lcp->lcd_send(lcp); /* XXX - fix this */
+                       /*FALLTHROUGH*/
+               default:
+                       return;
+
                dead:
                dead:
-               case RESET:
                case CLEAR:
                case CLEAR_CONF:
                case CLEAR:
                case CLEAR_CONF:
+                       lcp->lcd_upper = 0;
+                       lcp->lcd_upnext = 0;
+                       isop->isop_chan = 0;
+               case RESET:
                        cmd = PRC_ROUTEDEAD;
                }
                tpcons_ctlinput(cmd, isop->isop_faddr, isop);
                        cmd = PRC_ROUTEDEAD;
                }
                tpcons_ctlinput(cmd, isop->isop_faddr, isop);
+               if (cmd = PRC_ROUTEDEAD && isop->isop_refcnt == 0) 
+                       iso_pcbdetach(isop);
        }
 }
 
        }
 }
 
@@ -368,6 +371,7 @@ cons_connect(isop)
        register struct pklcd *lcp = (struct pklcd *)isop->isop_chan;
        register struct mbuf    *m;
        struct ifaddr                   *ifa;
        register struct pklcd *lcp = (struct pklcd *)isop->isop_chan;
        register struct mbuf    *m;
        struct ifaddr                   *ifa;
+       int error;
 
        IFDEBUG(D_CCONN)
                printf("cons_connect(0x%x): ", isop);
 
        IFDEBUG(D_CCONN)
                printf("cons_connect(0x%x): ", isop);
@@ -377,14 +381,17 @@ cons_connect(isop)
                printf("\n" );
        ENDDEBUG
        NSAPtoDTE(isop->isop_faddr, &lcp->lcd_faddr);
                printf("\n" );
        ENDDEBUG
        NSAPtoDTE(isop->isop_faddr, &lcp->lcd_faddr);
+       lcp->lcd_upper = cons_tpinput;
+       lcp->lcd_upnext = (caddr_t)isop;
        IFDEBUG(D_CCONN)
                printf(
                "calling make_partial_x25_packet( 0x%x, 0x%x, 0x%x)\n",
                        &lcp->lcd_faddr, &lcp->lcd_laddr, 
                        isop->isop_socket->so_proto->pr_protocol); 
        ENDDEBUG
        IFDEBUG(D_CCONN)
                printf(
                "calling make_partial_x25_packet( 0x%x, 0x%x, 0x%x)\n",
                        &lcp->lcd_faddr, &lcp->lcd_laddr, 
                        isop->isop_socket->so_proto->pr_protocol); 
        ENDDEBUG
-       return (make_partial_x25_packet(isop, lcp, m) ||
-                pk_connect(lcp, &lcp->lcd_faddr));
+       if ((error = make_partial_x25_packet(isop, lcp, m)) == 0)
+               error = pk_connect(lcp, &lcp->lcd_faddr);
+       return error;
 }
 
 /*
 }
 
 /*
@@ -533,33 +540,52 @@ make_partial_x25_packet(isop, lcp)
        struct mbuf *m;
 
 
        struct mbuf *m;
 
 
-       MGET(m, MT_DATA, M_WAITOK);
-       if (m == 0)
-               return ENOBUFS;
-       buf = mtod(m, caddr_t);
-       ptr = buf;
        IFDEBUG(D_CCONN)
                printf("make_partial_x25_packet(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
                        isop->isop_laddr, isop->isop_faddr, proto, m, flag);
        ENDDEBUG
        IFDEBUG(D_CCONN)
                printf("make_partial_x25_packet(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
                        isop->isop_laddr, isop->isop_faddr, proto, m, flag);
        ENDDEBUG
+       if (cons_use_udata) {
+               if (isop->isop_x25crud_len > 0) {
+                       /*
+                        *      The user specified something. Stick it in
+                        */
+                       bcopy(isop->isop_x25crud, lcp->lcd_faddr.x25_udata,
+                                       isop->isop_x25crud_len);
+                       lcp->lcd_faddr.x25_udlen = isop->isop_x25crud_len;
+               }
+       }
+
+       if (cons_use_facils == 0) {
+               lcp->lcd_facilities = 0;
+               return 0;
+       }
+       MGETHDR(m, MT_DATA, M_WAITOK);
+       if (m == 0)
+               return ENOBUFS;
+       buf = mtod(m, caddr_t);
+       ptr = buf;
        
        /* ptr now points to facil length (len of whole facil field in OCTETS */
        facil_len = ptr ++;
        
        /* ptr now points to facil length (len of whole facil field in OCTETS */
        facil_len = ptr ++;
+       m->m_len = 0;
+       pk_build_facilities(m, &lcp->lcd_faddr, 0);
 
        IFDEBUG(D_CADDR)
                printf("make_partial  calling: ptr 0x%x, len 0x%x\n", ptr, 
                                isop->isop_laddr->siso_addr.isoa_len);
        ENDDEBUG
        if (cons_use_facils) {
 
        IFDEBUG(D_CADDR)
                printf("make_partial  calling: ptr 0x%x, len 0x%x\n", ptr, 
                                isop->isop_laddr->siso_addr.isoa_len);
        ENDDEBUG
        if (cons_use_facils) {
+               *ptr++ = 0;      /* Marker to separate X.25 facitilies from CCITT ones */
+               *ptr++ = 0x0f;
                *ptr = 0xcb; /* calling facility code */
                ptr ++;
                ptr ++; /* leave room for facil param len (in OCTETS + 1) */
                ptr ++; /* leave room for the facil param len (in nibbles),
                *ptr = 0xcb; /* calling facility code */
                ptr ++;
                ptr ++; /* leave room for facil param len (in OCTETS + 1) */
                ptr ++; /* leave room for the facil param len (in nibbles),
-                               * high two bits of which indicate full/partial NSAP
-                               */
+                                * high two bits of which indicate full/partial NSAP
+                                */
                len = isop->isop_laddr->siso_addr.isoa_len;
                bcopy( isop->isop_laddr->siso_data, ptr, len);
                len = isop->isop_laddr->siso_addr.isoa_len;
                bcopy( isop->isop_laddr->siso_data, ptr, len);
-               *(ptr-2) = len+2; /* facil param len in octets */
+               *(ptr-2) = len+1; /* facil param len in octets */
                *(ptr-1) = len<<1; /* facil param len in nibbles */
                ptr += len;
 
                *(ptr-1) = len<<1; /* facil param len in nibbles */
                ptr += len;
 
@@ -571,11 +597,11 @@ make_partial_x25_packet(isop, lcp)
                ptr ++;
                ptr ++; /* leave room for facil param len (in OCTETS + 1) */
                ptr ++; /* leave room for the facil param len (in nibbles),
                ptr ++;
                ptr ++; /* leave room for facil param len (in OCTETS + 1) */
                ptr ++; /* leave room for the facil param len (in nibbles),
-                               * high two bits of which indicate full/partial NSAP
-                               */
+                                * high two bits of which indicate full/partial NSAP
+                                */
                len = isop->isop_faddr->siso_nlen;
                bcopy(isop->isop_faddr->siso_data, ptr, len);
                len = isop->isop_faddr->siso_nlen;
                bcopy(isop->isop_faddr->siso_data, ptr, len);
-               *(ptr-2) = len+2; /* facil param len = addr len + 1 for each of these
+               *(ptr-2) = len+1; /* facil param len = addr len + 1 for each of these
                                                  * two length fields, in octets */
                *(ptr-1) = len<<1; /* facil param len in nibbles */
                ptr += len;
                                                  * two length fields, in octets */
                *(ptr-1) = len<<1; /* facil param len in nibbles */
                ptr += len;
@@ -585,17 +611,6 @@ make_partial_x25_packet(isop, lcp)
        if (*facil_len > MAX_FACILITIES)
                return E_CO_PNA_LONG;
 
        if (*facil_len > MAX_FACILITIES)
                return E_CO_PNA_LONG;
 
-       if (cons_use_udata) {
-               if (isop->isop_x25crud_len > 0) {
-                       /*
-                        *      The user specified something. Stick it in
-                        */
-                       bcopy(isop->isop_x25crud, lcp->lcd_faddr.x25_udata,
-                                       isop->isop_x25crud_len);
-                       lcp->lcd_faddr.x25_udlen = isop->isop_x25crud_len;
-               }
-       }
-
        buflen = (int)(ptr - buf);
 
        IFDEBUG(D_CDUMP_REQ)
        buflen = (int)(ptr - buf);
 
        IFDEBUG(D_CDUMP_REQ)
@@ -619,7 +634,7 @@ make_partial_x25_packet(isop, lcp)
        if (buflen > MHLEN)
                return E_CO_PNA_LONG;
 
        if (buflen > MHLEN)
                return E_CO_PNA_LONG;
 
-       m->m_len = buflen;
+       m->m_pkthdr.len = m->m_len = buflen;
        lcp->lcd_facilities = m;
        return  0;
 }
        lcp->lcd_facilities = m;
        return  0;
 }
@@ -677,10 +692,15 @@ NSAPtoDTE(siso, sx25)
                dtelen = out - sx25->x25_addr;
                *out++ = 0;
        } else {
                dtelen = out - sx25->x25_addr;
                *out++ = 0;
        } else {
-               register struct rtentry *rt = rtalloc1(siso, 1);
                /* error = iso_8208snparesolve(addr, x121string, &x121strlen);*/
                /* error = iso_8208snparesolve(addr, x121string, &x121strlen);*/
-
-               if (rt) {
+               register struct rtentry *rt;
+               extern struct sockaddr_iso blank_siso;
+               struct sockaddr_iso nsiso;
+
+               nsiso = blank_siso;
+               bcopy(nsiso.siso_data, siso->siso_data,
+                               nsiso.siso_nlen = siso->siso_nlen);
+               if (rt = rtalloc1(&nsiso, 1)) {
                        register struct sockaddr_x25 *sxx =
                                                        (struct sockaddr_x25 *)rt->rt_gateway;
                        register char *in = sxx->x25_addr;
                        register struct sockaddr_x25 *sxx =
                                                        (struct sockaddr_x25 *)rt->rt_gateway;
                        register char *in = sxx->x25_addr;
@@ -704,16 +724,16 @@ NSAPtoDTE(siso, sx25)
  *     Creates and NSAP in the sockaddr_iso (addr) from the
  *  x.25 facility found at buf - 1.
  * RETURNS:
  *     Creates and NSAP in the sockaddr_iso (addr) from the
  *  x.25 facility found at buf - 1.
  * RETURNS:
- *  length of parameter if ok, -1 if error.
+ *  0 if ok, -1 if error.
  */
 
 Static int
 FACILtoNSAP(addr, buf)
  */
 
 Static int
 FACILtoNSAP(addr, buf)
-       u_char          *buf;
+       register u_char                 *buf;
        register struct sockaddr_iso *addr;
 {
        register struct sockaddr_iso *addr;
 {
-       int len_in_nibbles, param_len = *buf++;
-       u_char                  buf_len; /* in bytes */
+       int                     len_in_nibbles = *++buf & 0x3f;
+       u_char          buf_len = (len_in_nibbles + 1) >> 1;; /* in bytes */
 
        IFDEBUG(D_CADDR)
                printf("FACILtoNSAP( 0x%x, 0x%x, 0x%x )\n", 
 
        IFDEBUG(D_CADDR)
                printf("FACILtoNSAP( 0x%x, 0x%x, 0x%x )\n", 
@@ -721,7 +741,6 @@ FACILtoNSAP(addr, buf)
        ENDDEBUG
 
        len_in_nibbles = *buf & 0x3f;
        ENDDEBUG
 
        len_in_nibbles = *buf & 0x3f;
-       buf_len = (len_in_nibbles + 1) >> 1;
        /* despite the fact that X.25 makes us put a length in nibbles
         * here, the NSAP-addrs are always in full octets
         */
        /* despite the fact that X.25 makes us put a length in nibbles
         * here, the NSAP-addrs are always in full octets
         */
@@ -743,10 +762,10 @@ FACILtoNSAP(addr, buf)
                /* Rather than blow away the connection, just ignore and use
                   NSAP from DTE */;
        }
                /* Rather than blow away the connection, just ignore and use
                   NSAP from DTE */;
        }
-       return param_len;
+       return 0;
 }
 
 }
 
-static
+Static
 init_siso(siso)
 register struct sockaddr_iso *siso;
 {
 init_siso(siso)
 register struct sockaddr_iso *siso;
 {
@@ -780,15 +799,17 @@ DTEtoNSAP(addr, sx)
 
 
        init_siso(addr);
 
 
        init_siso(addr);
-       src_len = strlen(sx->x25_addr);
        in = sx->x25_addr;
        in = sx->x25_addr;
-       out = addr->siso_data + 1;
-       if (*in == '0' && (src_len & 1 == 0)) {
+       src_len = strlen(in);
+       addr->siso_nlen = (src_len + 3) / 2;
+       out = addr->siso_data;
+       *out++ = 0x37;
+       if (src_len & 1) {
                pad_tail = 0xf;
                src_len++;
        }
                pad_tail = 0xf;
                src_len++;
        }
-       for (first = 0; src_len > 0; src_len --) {
-               first |= *in++;
+       for (first = 0; src_len > 0; src_len--) {
+               first |= 0xf & *in++;
                if (src_len & 1) {
                        *out++ = first;
                        first = 0;
                if (src_len & 1) {
                        *out++ = first;
                        first = 0;
@@ -808,15 +829,13 @@ DTEtoNSAP(addr, sx)
  *  0 if ok, E* otherwise.
  */
 
  *  0 if ok, E* otherwise.
  */
 
-static int
+Static int
 parse_facil(lcp, isop, buf, buf_len)
        caddr_t                 buf;
        u_char                  buf_len; /* in bytes */
        struct                  isopcb *isop;
        struct                  pklcd *lcp;
 {
 parse_facil(lcp, isop, buf, buf_len)
        caddr_t                 buf;
        u_char                  buf_len; /* in bytes */
        struct                  isopcb *isop;
        struct                  pklcd *lcp;
 {
-       register struct sockaddr_iso *called = isop->isop_laddr;
-       register struct sockaddr_iso *calling = isop->isop_faddr;
        register int    i;
        register u_char         *ptr = (u_char *)buf;
        u_char                  *ptr_lim, *facil_lim;
        register int    i;
        register u_char         *ptr = (u_char *)buf;
        u_char                  *ptr_lim, *facil_lim;
@@ -824,7 +843,7 @@ parse_facil(lcp, isop, buf, buf_len)
 
        IFDEBUG(D_CADDR)
                printf("parse_facil(0x%x, 0x%x, 0x%x, 0x%x)\n", 
 
        IFDEBUG(D_CADDR)
                printf("parse_facil(0x%x, 0x%x, 0x%x, 0x%x)\n", 
-                       buf, buf_len, called, calling);
+                       lcp, isop, buf, buf_len);
                dump_buf(buf, buf_len);
        ENDDEBUG
 
                dump_buf(buf, buf_len);
        ENDDEBUG
 
@@ -846,7 +865,7 @@ parse_facil(lcp, isop, buf, buf_len)
                printf("parse_facils: facil length is  0x%x\n", (int) facil_len);
        ENDDEBUG
 
                printf("parse_facils: facil length is  0x%x\n", (int) facil_len);
        ENDDEBUG
 
-       while (ptr <= facil_lim) {
+       while (ptr < facil_lim) {
                /* get NSAP addresses from facilities */
                switch (*ptr++) {
                        case 0xcb:
                /* get NSAP addresses from facilities */
                switch (*ptr++) {
                        case 0xcb:
@@ -879,6 +898,7 @@ parse_facil(lcp, isop, buf, buf_len)
                                                (example of intelligent protocol design) */
                        case 0x04:      /* charging info : requesting service */
                        case 0x08:      /* called line addr modified notification */
                                                (example of intelligent protocol design) */
                        case 0x04:      /* charging info : requesting service */
                        case 0x08:      /* called line addr modified notification */
+                       case 0x00:  /* marker to indicate beginning of CCITT facils */
                                facil_param_len = 1;
                                break;
 
                                facil_param_len = 1;
                                break;
 
@@ -891,21 +911,23 @@ parse_facil(lcp, isop, buf, buf_len)
                                facil_param_len = 2;
                                break;
 
                                facil_param_len = 2;
                                break;
 
-                               /* don't have any 3 octets */
-                               /*
-                               facil_param_len = 3;
-                               */
                        default:
                                printf(
                        default:
                                printf(
-"BOGUS FACILITY CODE facil_len 0x%x *facil_len 0x%x, ptr 0x%x *ptr 0x%x\n",
-                                       ptr, facil_len, ptr - 1, ptr[-1]);
-                               /* facil that we don't handle */
-                               return E_CO_HLI_REJI;
+"BOGUS FACILITY CODE facil_lim 0x%x facil_len %d, ptr 0x%x *ptr 0x%x\n",
+                                       facil_lim, facil_len, ptr - 1, ptr[-1]);
+                               /* facil that we don't handle
+                               return E_CO_HLI_REJI; */
+                               switch (ptr[-1] & 0xc0) {
+                               case 0x00:      facil_param_len = 1; break;
+                               case 0x40:      facil_param_len = 2; break;
+                               case 0x80:      facil_param_len = 3; break;
+                               case 0xc0:      facil_param_len = 0; break;
+                               }
                }
                if (facil_param_len == -1)
                        return E_CO_REG_ICDA;
                if (facil_param_len == 0) /* variable length */ 
                }
                if (facil_param_len == -1)
                        return E_CO_REG_ICDA;
                if (facil_param_len == 0) /* variable length */ 
-                       facil_param_len = (int)*ptr; /* 1 + the real facil param */
+                       facil_param_len = (int)*ptr++; /* 1 + the real facil param */
                ptr += facil_param_len;
        }
        return 0;
                ptr += facil_param_len;
        }
        return 0;