BSD 4_4_Lite2 release
[unix-history] / usr / src / sys / netiso / iso_pcb.c
index 46de8ca..722bed9 100644 (file)
@@ -1,3 +1,38 @@
+/*-
+ * Copyright (c) 1991, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ *     @(#)iso_pcb.c   8.3 (Berkeley) 7/19/94
+ */
+
 /***********************************************************
                Copyright IBM Corporation 1987
 
 /***********************************************************
                Copyright IBM Corporation 1987
 
@@ -27,32 +62,34 @@ SOFTWARE.
 /*
  * $Header: iso_pcb.c,v 4.5 88/06/29 14:59:56 hagens Exp $
  * $Source: /usr/argo/sys/netiso/RCS/iso_pcb.c,v $
 /*
  * $Header: iso_pcb.c,v 4.5 88/06/29 14:59:56 hagens Exp $
  * $Source: /usr/argo/sys/netiso/RCS/iso_pcb.c,v $
- *     @(#)iso_pcb.c   7.4 (Berkeley) %G%
  *
  * Iso address family net-layer(s) pcb stuff. NEH 1/29/87
  */
 
  *
  * Iso address family net-layer(s) pcb stuff. NEH 1/29/87
  */
 
-#ifndef lint
-static char *rcsid = "$Header: iso_pcb.c,v 4.5 88/06/29 14:59:56 hagens Exp $";
-#endif
-
 #ifdef ISO
 
 #ifdef ISO
 
-#include "param.h"
-#include "systm.h"
-#include "user.h"
-#include "mbuf.h"
-#include "socket.h"
-#include "socketvar.h"
-#include "argo_debug.h"
-#include "iso.h"
-#include "clnp.h"
-#include "../netinet/in_systm.h"
-#include "../net/if.h"
-#include "../net/route.h"
-#include "iso_pcb.h"
-#include "iso_var.h"
-#include "protosw.h"
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/errno.h>
+
+#include <netiso/argo_debug.h>
+#include <netiso/iso.h>
+#include <netiso/clnp.h>
+#include <netinet/in_systm.h>
+#include <net/if.h>
+#include <net/route.h>
+#include <netiso/iso_pcb.h>
+#include <netiso/iso_var.h>
+#include <sys/protosw.h>
+
+#ifdef TPCONS
+#include <netccitt/x25.h>
+#include <netccitt/pk.h>
+#include <netccitt/pk_var.h>
+#endif
 
 #define PCBNULL (struct isopcb *)0
 struct iso_addr zeroiso_addr = {
 
 #define PCBNULL (struct isopcb *)0
 struct iso_addr zeroiso_addr = {
@@ -86,7 +123,8 @@ iso_pcballoc(so, head)
        isop->isop_head = head;
        isop->isop_socket = so;
        insque(isop, head);
        isop->isop_head = head;
        isop->isop_socket = so;
        insque(isop, head);
-       so->so_pcb = (caddr_t)isop;
+       if (so)
+               so->so_pcb = (caddr_t)isop;
        return 0;
 }
        
        return 0;
 }
        
@@ -131,10 +169,12 @@ iso_pcbbind(isop, nam)
                return EADDRINUSE;
        if(nam == (struct mbuf *)0) {
                isop->isop_laddr = &isop->isop_sladdr;
                return EADDRINUSE;
        if(nam == (struct mbuf *)0) {
                isop->isop_laddr = &isop->isop_sladdr;
-               isop->isop_sladdr.siso_tsuffixlen = 2;
-               isop->isop_sladdr.siso_nlen = 0;
-               isop->isop_sladdr.siso_family = AF_ISO;
                isop->isop_sladdr.siso_len = sizeof(struct sockaddr_iso);
                isop->isop_sladdr.siso_len = sizeof(struct sockaddr_iso);
+               isop->isop_sladdr.siso_family = AF_ISO;
+               isop->isop_sladdr.siso_tlen = 2;
+               isop->isop_sladdr.siso_nlen = 0;
+               isop->isop_sladdr.siso_slen = 0;
+               isop->isop_sladdr.siso_plen = 0;
                goto noname;
        }
        siso = mtod(nam, struct sockaddr_iso *);
                goto noname;
        }
        siso = mtod(nam, struct sockaddr_iso *);
@@ -154,18 +194,13 @@ iso_pcbbind(isop, nam)
        if( (nam->m_len < 2) || (nam->m_len < siso->siso_len)) {
                        return ENAMETOOLONG;
        }
        if( (nam->m_len < 2) || (nam->m_len < siso->siso_len)) {
                        return ENAMETOOLONG;
        }
-       if (siso->siso_tsuffixlen) {
-                       register char *cp = TSEL(siso);
-                       suf.data[0] = cp[0];
-                       suf.data[1] = cp[1];
-       }
        if (siso->siso_nlen) {
                /* non-zero net addr- better match one of our interfaces */
                IFDEBUG(D_ISO)
                        printf("iso_pcbbind: bind to NOT zeroisoaddr\n");
                ENDDEBUG
                for (ia = iso_ifaddr; ia; ia = ia->ia_next) 
        if (siso->siso_nlen) {
                /* non-zero net addr- better match one of our interfaces */
                IFDEBUG(D_ISO)
                        printf("iso_pcbbind: bind to NOT zeroisoaddr\n");
                ENDDEBUG
                for (ia = iso_ifaddr; ia; ia = ia->ia_next) 
-                       if (SAME_ISOADDR(siso, &ia->ia_addr))
+                       if (SAME_ISOIFADDR(siso, &ia->ia_addr))
                                break;
                if (ia == 0)
                        return EADDRNOTAVAIL;
                                break;
                if (ia == 0)
                        return EADDRNOTAVAIL;
@@ -178,17 +213,22 @@ iso_pcbbind(isop, nam)
                isop->isop_laddr = mtod(nam, struct sockaddr_iso *);
        }
        bcopy((caddr_t)siso, (caddr_t)isop->isop_laddr, siso->siso_len);
                isop->isop_laddr = mtod(nam, struct sockaddr_iso *);
        }
        bcopy((caddr_t)siso, (caddr_t)isop->isop_laddr, siso->siso_len);
-       if (suf.s) {
-               if((suf.s < ISO_PORT_RESERVED) && (siso->siso_tsuffixlen <= 2) &&
-                  (u.u_uid != 0))
+       if (siso->siso_tlen == 0)
+               goto noname;
+       if ((isop->isop_socket->so_options & SO_REUSEADDR) == 0 &&
+               iso_pcblookup(head, 0, (caddr_t)0, isop->isop_laddr))
+               return EADDRINUSE;
+       if (siso->siso_tlen <= 2) {
+               bcopy(TSEL(siso), suf.data, sizeof(suf.data));
+               suf.s = ntohs(suf.s);
+               if((suf.s < ISO_PORT_RESERVED) &&
+                  (isop->isop_socket->so_state && SS_PRIV) == 0)
                        return EACCES;
                        return EACCES;
-               if ((isop->isop_socket->so_options & SO_REUSEADDR) == 0 &&
-                       iso_pcblookup(head, 0, (caddr_t)0, isop->isop_laddr))
-                       return EADDRINUSE;
        } else {
                register char *cp;
 noname:
                cp = TSEL(isop->isop_laddr);
        } else {
                register char *cp;
 noname:
                cp = TSEL(isop->isop_laddr);
+               isop->isop_laddr->siso_tlen = 2;
        IFDEBUG(D_ISO)
                printf("iso_pcbbind noname\n");
        ENDDEBUG
        IFDEBUG(D_ISO)
                printf("iso_pcbbind noname\n");
        ENDDEBUG
@@ -196,7 +236,7 @@ noname:
                        if (head->isop_lport++ < ISO_PORT_RESERVED ||
                            head->isop_lport > ISO_PORT_USERRESERVED)
                                head->isop_lport = ISO_PORT_RESERVED;
                        if (head->isop_lport++ < ISO_PORT_RESERVED ||
                            head->isop_lport > ISO_PORT_USERRESERVED)
                                head->isop_lport = ISO_PORT_RESERVED;
-                       suf.s = head->isop_lport;
+                       suf.s = htons(head->isop_lport);
                        cp[0] = suf.data[0];
                        cp[1] = suf.data[1];
                } while (iso_pcblookup(head, 0, (caddr_t)0, isop->isop_laddr));
                        cp[0] = suf.data[0];
                        cp[1] = suf.data[1];
                } while (iso_pcblookup(head, 0, (caddr_t)0, isop->isop_laddr));
@@ -250,7 +290,7 @@ iso_pcbconnect(isop, nam)
                if (ia = iso_ifaddr) {
                        int nlen = ia->ia_addr.siso_nlen;
                        ovbcopy(TSEL(siso), nlen + TSEL(siso),
                if (ia = iso_ifaddr) {
                        int nlen = ia->ia_addr.siso_nlen;
                        ovbcopy(TSEL(siso), nlen + TSEL(siso),
-                               siso->siso_tsuffixlen + siso->siso_ssuffixlen);
+                               siso->siso_plen + siso->siso_tlen + siso->siso_slen);
                        bcopy((caddr_t)&ia->ia_addr.siso_addr,
                                  (caddr_t)&siso->siso_addr, nlen + 1);
                        /* includes siso->siso_nlen = nlen; */
                        bcopy((caddr_t)&ia->ia_addr.siso_addr,
                                  (caddr_t)&siso->siso_addr, nlen + 1);
                        /* includes siso->siso_nlen = nlen; */
@@ -291,7 +331,7 @@ iso_pcbconnect(isop, nam)
        if (local_zero) {
                int nlen, tlen, totlen; caddr_t oldtsel, newtsel;
                siso = isop->isop_laddr;
        if (local_zero) {
                int nlen, tlen, totlen; caddr_t oldtsel, newtsel;
                siso = isop->isop_laddr;
-               if (siso == 0 || siso->siso_tsuffixlen == 0)
+               if (siso == 0 || siso->siso_tlen == 0)
                        (void)iso_pcbbind(isop, (struct mbuf *)0);
                /*
                 * Here we have problem of squezeing in a definite network address
                        (void)iso_pcbbind(isop, (struct mbuf *)0);
                /*
                 * Here we have problem of squezeing in a definite network address
@@ -300,7 +340,7 @@ iso_pcbconnect(isop, nam)
                 */
                siso = isop->isop_laddr;
                oldtsel = TSEL(siso);
                 */
                siso = isop->isop_laddr;
                oldtsel = TSEL(siso);
-               tlen = siso->siso_tsuffixlen;
+               tlen = siso->siso_tlen;
                nlen = ia->ia_addr.siso_nlen;
                totlen = tlen + nlen + _offsetof(struct sockaddr_iso, siso_data[0]);
                if ((siso == &isop->isop_sladdr) &&
                nlen = ia->ia_addr.siso_nlen;
                totlen = tlen + nlen + _offsetof(struct sockaddr_iso, siso_data[0]);
                if ((siso == &isop->isop_sladdr) &&
@@ -315,7 +355,7 @@ iso_pcbconnect(isop, nam)
                newtsel = TSEL(siso);
                ovbcopy(oldtsel, newtsel, tlen);
                bcopy(ia->ia_addr.siso_data, siso->siso_data, nlen);
                newtsel = TSEL(siso);
                ovbcopy(oldtsel, newtsel, tlen);
                bcopy(ia->ia_addr.siso_data, siso->siso_data, nlen);
-               siso->siso_tsuffixlen = tlen;
+               siso->siso_tlen = tlen;
                siso->siso_family = AF_ISO;
                siso->siso_len = totlen;
                siso = mtod(nam, struct sockaddr_iso *);
                siso->siso_family = AF_ISO;
                siso->siso_len = totlen;
                siso = mtod(nam, struct sockaddr_iso *);
@@ -373,6 +413,7 @@ iso_pcbdisconnect(isop)
        struct isopcb *isop;
 {
        void iso_pcbdetach();
        struct isopcb *isop;
 {
        void iso_pcbdetach();
+       register struct sockaddr_iso *siso;
 
        IFDEBUG(D_ISO)
                printf("iso_pcbdisconnect(isop 0x%x)\n", isop);
 
        IFDEBUG(D_ISO)
                printf("iso_pcbdisconnect(isop 0x%x)\n", isop);
@@ -380,8 +421,11 @@ iso_pcbdisconnect(isop)
        /*
         * Preserver binding infnormation if already bound.
         */
        /*
         * Preserver binding infnormation if already bound.
         */
-       if (isop->isop_laddr && isop->isop_laddr->siso_nlen)
-               isop->isop_laddr->siso_nlen = 0;
+       if ((siso = isop->isop_laddr) && siso->siso_nlen && siso->siso_tlen) {
+               caddr_t otsel = TSEL(siso);
+               siso->siso_nlen = 0;
+               ovbcopy(otsel, TSEL(siso), siso->siso_tlen);
+       }
        if (isop->isop_faddr && isop->isop_faddr != &isop->isop_sfaddr)
                m_freem(dtom(isop->isop_faddr));
        isop->isop_faddr = 0;
        if (isop->isop_faddr && isop->isop_faddr != &isop->isop_sfaddr)
                m_freem(dtom(isop->isop_faddr));
        isop->isop_faddr = 0;
@@ -412,7 +456,20 @@ iso_pcbdetach(isop)
                printf("iso_pcbdetach(isop 0x%x socket 0x%x so 0x%x)\n", 
                        isop, isop->isop_socket, so);
        ENDDEBUG
                printf("iso_pcbdetach(isop 0x%x socket 0x%x so 0x%x)\n", 
                        isop, isop->isop_socket, so);
        ENDDEBUG
-       if (so ) { /* in the x.25 domain, we sometimes have no socket */
+#ifdef TPCONS
+       if (isop->isop_chan) {
+               register struct pklcd *lcp = (struct pklcd *)isop->isop_chan;
+               if (--isop->isop_refcnt > 0)
+                       return;
+               if (lcp && lcp->lcd_state == DATA_TRANSFER) {
+                       lcp->lcd_upper = 0;
+                       lcp->lcd_upnext = 0;
+                       pk_disconnect(lcp);
+               }
+               isop->isop_chan = 0;
+       }
+#endif
+       if (so) { /* in the x.25 domain, we sometimes have no socket */
                so->so_pcb = 0;
                sofree(so); 
        }
                so->so_pcb = 0;
                sofree(so); 
        }
@@ -453,42 +510,9 @@ iso_pcbdetach(isop)
        ENDDEBUG
        if (isop->isop_laddr && (isop->isop_laddr != &isop->isop_sladdr))
                m_freem(dtom(isop->isop_laddr));
        ENDDEBUG
        if (isop->isop_laddr && (isop->isop_laddr != &isop->isop_sladdr))
                m_freem(dtom(isop->isop_laddr));
-       free((caddr_t)isop, M_IFADDR);
-}
-
-#ifdef notdef
-/* NEEDED? */
-void
-iso_setsockaddr(isop, nam)
-       register struct isopcb *isop;
-       struct mbuf *nam;
-{
-       register struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *);
-       
-       nam->m_len = sizeof (*siso);
-       siso = mtod(nam, struct sockaddr_iso *);
-       bzero((caddr_t)siso, sizeof (*siso));
-       siso->siso_family = AF_ISO;
-       siso->siso_tsuffix = isop->isop_lport;
-       siso->siso_addr = isop->isop_laddr.siso_addr;
+       free((caddr_t)isop, M_PCB);
 }
 
 }
 
-/* NEEDED? */
-void
-iso_setpeeraddr(isop, nam)
-       register struct isopcb *isop;
-       struct mbuf *nam;
-{
-       register struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *);
-       
-       nam->m_len = sizeof (*siso);
-       siso = mtod(nam, struct sockaddr_iso *);
-       bzero((caddr_t)siso, sizeof (*siso));
-       siso->siso_family = AF_ISO;
-       siso->siso_tsuffix = isop->isop_fport;
-       siso->siso_addr = isop->isop_faddr.siso_addr;
-}
-#endif notdef
 
 /*
  * FUNCTION:           iso_pcbnotify
 
 /*
  * FUNCTION:           iso_pcbnotify
@@ -504,36 +528,32 @@ iso_setpeeraddr(isop, nam)
  * NOTES:                      (notify) is called at splimp!
  */
 void
  * NOTES:                      (notify) is called at splimp!
  */
 void
-iso_pcbnotify(head, dst, errno, notify)
+iso_pcbnotify(head, siso, errno, notify)
        struct isopcb *head;
        struct isopcb *head;
-       register struct iso_addr *dst;
+       register struct sockaddr_iso *siso;
        int errno, (*notify)();
 {
        int errno, (*notify)();
 {
-       register struct isopcb *isop, *oisop;
+       register struct isopcb *isop;
        int s = splimp();
 
        IFDEBUG(D_ISO)
                printf("iso_pcbnotify(head 0x%x, notify 0x%x) dst:\n", head, notify);
        ENDDEBUG
        int s = splimp();
 
        IFDEBUG(D_ISO)
                printf("iso_pcbnotify(head 0x%x, notify 0x%x) dst:\n", head, notify);
        ENDDEBUG
-       for (isop = head->isop_next; isop != head;) {
-               if (!iso_addrmatch1(&(isop->isop_faddr->siso_addr), dst) ||
-                   isop->isop_socket == 0) {
+       for (isop = head->isop_next; isop != head; isop = isop->isop_next) {
+               if (isop->isop_socket == 0 || isop->isop_faddr == 0 ||
+                       !SAME_ISOADDR(siso, isop->isop_faddr)) {
                        IFDEBUG(D_ISO)
                                printf("iso_pcbnotify: CONTINUE isop 0x%x, sock 0x%x\n" ,
                                        isop, isop->isop_socket);
                        IFDEBUG(D_ISO)
                                printf("iso_pcbnotify: CONTINUE isop 0x%x, sock 0x%x\n" ,
                                        isop, isop->isop_socket);
-                               printf("addrmatch cmp'd with (0x%x):\n",
-                                       &(isop->isop_faddr->siso_addr));
+                               printf("addrmatch cmp'd with (0x%x):\n", isop->isop_faddr);
                                dump_isoaddr(isop->isop_faddr);
                        ENDDEBUG
                                dump_isoaddr(isop->isop_faddr);
                        ENDDEBUG
-                       isop = isop->isop_next;
                        continue;
                }
                if (errno) 
                        isop->isop_socket->so_error = errno;
                        continue;
                }
                if (errno) 
                        isop->isop_socket->so_error = errno;
-               oisop = isop;
-               isop = isop->isop_next;
                if (notify)
                if (notify)
-                       (*notify)(oisop);
+                       (*notify)(isop);
        }
        splx(s);
        IFDEBUG(D_ISO)
        }
        splx(s);
        IFDEBUG(D_ISO)
@@ -565,7 +585,7 @@ iso_pcblookup(head, fportlen, fport, laddr)
 {
        register struct isopcb *isop;
        register caddr_t lp = TSEL(laddr);
 {
        register struct isopcb *isop;
        register caddr_t lp = TSEL(laddr);
-       unsigned int llen = laddr->siso_tsuffixlen;
+       unsigned int llen = laddr->siso_tlen;
 
        IFDEBUG(D_ISO)
                printf("iso_pcblookup(head 0x%x laddr 0x%x fport 0x%x)\n", 
 
        IFDEBUG(D_ISO)
                printf("iso_pcblookup(head 0x%x laddr 0x%x fport 0x%x)\n", 
@@ -574,7 +594,7 @@ iso_pcblookup(head, fportlen, fport, laddr)
        for (isop = head->isop_next; isop != head; isop = isop->isop_next) {
                if (isop->isop_laddr == 0 || isop->isop_laddr == laddr)
                        continue;
        for (isop = head->isop_next; isop != head; isop = isop->isop_next) {
                if (isop->isop_laddr == 0 || isop->isop_laddr == laddr)
                        continue;
-               if (isop->isop_laddr->siso_tsuffixlen != llen)
+               if (isop->isop_laddr->siso_tlen != llen)
                        continue;
                if (bcmp(lp, TSEL(isop->isop_laddr), llen))
                        continue;
                        continue;
                if (bcmp(lp, TSEL(isop->isop_laddr), llen))
                        continue;
@@ -595,4 +615,4 @@ iso_pcblookup(head, fportlen, fport, laddr)
        }
        return (struct isopcb *)0;
 }
        }
        return (struct isopcb *)0;
 }
-#endif ISO
+#endif /* ISO */