149268Sbostic /*- 2*63222Sbostic * Copyright (c) 1991, 1993 3*63222Sbostic * The Regents of the University of California. All rights reserved. 449268Sbostic * 549268Sbostic * %sccs.include.redist.c% 649268Sbostic * 7*63222Sbostic * @(#)iso_pcb.c 8.1 (Berkeley) 06/10/93 849268Sbostic */ 949268Sbostic 1036389Ssklower /*********************************************************** 1136389Ssklower Copyright IBM Corporation 1987 1236389Ssklower 1336389Ssklower All Rights Reserved 1436389Ssklower 1536389Ssklower Permission to use, copy, modify, and distribute this software and its 1636389Ssklower documentation for any purpose and without fee is hereby granted, 1736389Ssklower provided that the above copyright notice appear in all copies and that 1836389Ssklower both that copyright notice and this permission notice appear in 1936389Ssklower supporting documentation, and that the name of IBM not be 2036389Ssklower used in advertising or publicity pertaining to distribution of the 2136389Ssklower software without specific, written prior permission. 2236389Ssklower 2336389Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 2436389Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 2536389Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 2636389Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 2736389Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 2836389Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2936389Ssklower SOFTWARE. 3036389Ssklower 3136389Ssklower ******************************************************************/ 3236389Ssklower 3336389Ssklower /* 3436389Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 3536389Ssklower */ 3636389Ssklower /* 3736389Ssklower * $Header: iso_pcb.c,v 4.5 88/06/29 14:59:56 hagens Exp $ 3836389Ssklower * $Source: /usr/argo/sys/netiso/RCS/iso_pcb.c,v $ 3936389Ssklower * 4036389Ssklower * Iso address family net-layer(s) pcb stuff. NEH 1/29/87 4136389Ssklower */ 4238477Ssklower 4336389Ssklower #ifdef ISO 4436389Ssklower 4556533Sbostic #include <sys/param.h> 4656533Sbostic #include <sys/systm.h> 4756533Sbostic #include <sys/mbuf.h> 4856533Sbostic #include <sys/socket.h> 4956533Sbostic #include <sys/socketvar.h> 5056533Sbostic #include <sys/errno.h> 5150235Ssklower 5256533Sbostic #include <netiso/argo_debug.h> 5356533Sbostic #include <netiso/iso.h> 5456533Sbostic #include <netiso/clnp.h> 5556533Sbostic #include <netinet/in_systm.h> 5656533Sbostic #include <net/if.h> 5756533Sbostic #include <net/route.h> 5856533Sbostic #include <netiso/iso_pcb.h> 5956533Sbostic #include <netiso/iso_var.h> 6056533Sbostic #include <sys/protosw.h> 6136389Ssklower 6248737Ssklower #ifdef TPCONS 6356533Sbostic #include <netccitt/x25.h> 6456533Sbostic #include <netccitt/pk.h> 6556533Sbostic #include <netccitt/pk_var.h> 6648737Ssklower #endif 6748737Ssklower 6836389Ssklower #define PCBNULL (struct isopcb *)0 6936389Ssklower struct iso_addr zeroiso_addr = { 7036389Ssklower 0 7136389Ssklower }; 7236389Ssklower 7336389Ssklower 7436389Ssklower /* 7536389Ssklower * FUNCTION: iso_pcballoc 7636389Ssklower * 7736389Ssklower * PURPOSE: creates an isopcb structure in an mbuf, 7836389Ssklower * with socket (so), and 7936389Ssklower * puts it in the queue with head (head) 8036389Ssklower * 8136389Ssklower * RETURNS: 0 if OK, ENOBUFS if can't alloc the necessary mbuf 8236389Ssklower */ 8336389Ssklower int 8436389Ssklower iso_pcballoc(so, head) 8536389Ssklower struct socket *so; 8636389Ssklower struct isopcb *head; 8736389Ssklower { 8836389Ssklower register struct isopcb *isop; 8936389Ssklower 9036389Ssklower IFDEBUG(D_ISO) 9136389Ssklower printf("iso_pcballoc(so 0x%x)\n", so); 9236389Ssklower ENDDEBUG 9337469Ssklower MALLOC(isop, struct isopcb *, sizeof(*isop), M_PCB, M_NOWAIT); 9437469Ssklower if (isop == NULL) 9536389Ssklower return ENOBUFS; 9637469Ssklower bzero((caddr_t)isop, sizeof(*isop)); 9736389Ssklower isop->isop_head = head; 9836389Ssklower isop->isop_socket = so; 9936389Ssklower insque(isop, head); 10048737Ssklower if (so) 10148737Ssklower so->so_pcb = (caddr_t)isop; 10236389Ssklower return 0; 10336389Ssklower } 10436389Ssklower 10536389Ssklower /* 10636389Ssklower * FUNCTION: iso_pcbbind 10736389Ssklower * 10836389Ssklower * PURPOSE: binds the address given in *(nam) to the socket 10936389Ssklower * specified by the isopcb in *(isop) 11036389Ssklower * If the given address is zero, it makes sure the 11136389Ssklower * address isn't already in use and if it's got a network 11236389Ssklower * portion, we look for an interface with that network 11336389Ssklower * address. If the address given is zero, we allocate 11436389Ssklower * a port and stuff it in the (nam) structure. 11536389Ssklower * 11636389Ssklower * RETURNS: errno E* or 0 if ok. 11736389Ssklower * 11836389Ssklower * SIDE EFFECTS: increments head->isop_lport if it allocates a port # 11936389Ssklower * 12036389Ssklower * NOTES: 12136389Ssklower */ 12237469Ssklower #define satosiso(sa) ((struct sockaddr_iso *)(sa)) 12336389Ssklower int 12436389Ssklower iso_pcbbind(isop, nam) 12536389Ssklower register struct isopcb *isop; 12636389Ssklower struct mbuf *nam; 12736389Ssklower { 12836389Ssklower register struct isopcb *head = isop->isop_head; 12936389Ssklower register struct sockaddr_iso *siso; 13037469Ssklower struct iso_ifaddr *ia; 13137469Ssklower union { 13237469Ssklower char data[2]; 13337469Ssklower u_short s; 13437469Ssklower } suf; 13536389Ssklower 13636389Ssklower IFDEBUG(D_ISO) 13736389Ssklower printf("iso_pcbbind(isop 0x%x, nam 0x%x)\n", isop, nam); 13836389Ssklower ENDDEBUG 13937469Ssklower suf.s = 0; 14036389Ssklower if (iso_ifaddr == 0) /* any interfaces attached? */ 14136389Ssklower return EADDRNOTAVAIL; 14237469Ssklower if (isop->isop_laddr) /* already bound */ 14336389Ssklower return EADDRINUSE; 14437469Ssklower if(nam == (struct mbuf *)0) { 14537469Ssklower isop->isop_laddr = &isop->isop_sladdr; 14638841Ssklower isop->isop_sladdr.siso_len = sizeof(struct sockaddr_iso); 14738841Ssklower isop->isop_sladdr.siso_family = AF_ISO; 14838841Ssklower isop->isop_sladdr.siso_tlen = 2; 14937469Ssklower isop->isop_sladdr.siso_nlen = 0; 15038841Ssklower isop->isop_sladdr.siso_slen = 0; 15138841Ssklower isop->isop_sladdr.siso_plen = 0; 15236389Ssklower goto noname; 15337469Ssklower } 15436389Ssklower siso = mtod(nam, struct sockaddr_iso *); 15536389Ssklower IFDEBUG(D_ISO) 15636389Ssklower printf("iso_pcbbind(name len 0x%x)\n", nam->m_len); 15736389Ssklower printf("The address is %s\n", clnp_iso_addrp(&siso->siso_addr)); 15836389Ssklower ENDDEBUG 15936389Ssklower /* 16036389Ssklower * We would like sort of length check but since some OSI addrs 16136389Ssklower * do not have fixed length, we can't really do much. 16236389Ssklower * The ONLY thing we can say is that an osi addr has to have 16336389Ssklower * at LEAST an afi and one more byte and had better fit into 16436389Ssklower * a struct iso_addr. 16536389Ssklower * However, in fact the size of the whole thing is a struct 16636389Ssklower * sockaddr_iso, so probably this is what we should check for. 16736389Ssklower */ 16837469Ssklower if( (nam->m_len < 2) || (nam->m_len < siso->siso_len)) { 16936389Ssklower return ENAMETOOLONG; 17036389Ssklower } 17137469Ssklower if (siso->siso_nlen) { 17236389Ssklower /* non-zero net addr- better match one of our interfaces */ 17336389Ssklower IFDEBUG(D_ISO) 17436389Ssklower printf("iso_pcbbind: bind to NOT zeroisoaddr\n"); 17536389Ssklower ENDDEBUG 17637469Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) 17737469Ssklower if (SAME_ISOADDR(siso, &ia->ia_addr)) 17837469Ssklower break; 17937469Ssklower if (ia == 0) 18036389Ssklower return EADDRNOTAVAIL; 18136389Ssklower } 18237469Ssklower if (siso->siso_len <= sizeof (isop->isop_sladdr)) { 18337469Ssklower isop->isop_laddr = &isop->isop_sladdr; 18437469Ssklower } else { 18537469Ssklower if ((nam = m_copy(nam, 0, (int)M_COPYALL)) == 0) 18637469Ssklower return ENOBUFS; 18737469Ssklower isop->isop_laddr = mtod(nam, struct sockaddr_iso *); 18837469Ssklower } 18937469Ssklower bcopy((caddr_t)siso, (caddr_t)isop->isop_laddr, siso->siso_len); 19053230Ssklower if (siso->siso_tlen == 0) 19153230Ssklower goto noname; 19253230Ssklower if ((isop->isop_socket->so_options & SO_REUSEADDR) == 0 && 19353230Ssklower iso_pcblookup(head, 0, (caddr_t)0, isop->isop_laddr)) 19453230Ssklower return EADDRINUSE; 19553230Ssklower if (siso->siso_tlen <= 2) { 19653230Ssklower bcopy(TSEL(siso), suf.data, sizeof(suf.data)); 19753230Ssklower suf.s = ntohs(suf.s); 19853230Ssklower if((suf.s < ISO_PORT_RESERVED) && 19950235Ssklower (isop->isop_socket->so_state && SS_PRIV) == 0) 20036389Ssklower return EACCES; 20137469Ssklower } else { 20237469Ssklower register char *cp; 20336389Ssklower noname: 20437469Ssklower cp = TSEL(isop->isop_laddr); 20536389Ssklower IFDEBUG(D_ISO) 20636389Ssklower printf("iso_pcbbind noname\n"); 20736389Ssklower ENDDEBUG 20836389Ssklower do { 20936389Ssklower if (head->isop_lport++ < ISO_PORT_RESERVED || 21036389Ssklower head->isop_lport > ISO_PORT_USERRESERVED) 21136389Ssklower head->isop_lport = ISO_PORT_RESERVED; 21253230Ssklower suf.s = htons(head->isop_lport); 21337469Ssklower cp[0] = suf.data[0]; 21437469Ssklower cp[1] = suf.data[1]; 21537469Ssklower } while (iso_pcblookup(head, 0, (caddr_t)0, isop->isop_laddr)); 21637469Ssklower } 21736389Ssklower IFDEBUG(D_ISO) 21836389Ssklower printf("iso_pcbbind returns 0, suf 0x%x\n", suf); 21936389Ssklower ENDDEBUG 22036389Ssklower return 0; 22136389Ssklower } 22236389Ssklower /* 22336389Ssklower * FUNCTION: iso_pcbconnect 22436389Ssklower * 22536389Ssklower * PURPOSE: Make the isopcb (isop) look like it's connected. 22636389Ssklower * In other words, give it the peer address given in 22736389Ssklower * the mbuf * (nam). Make sure such a combination 22836389Ssklower * of local, peer addresses doesn't already exist 22936389Ssklower * for this protocol. Internet mentality prevails here, 23036389Ssklower * wherein a src,dst pair uniquely identifies a connection. 23136389Ssklower * Both net address and port must be specified in argument 23236389Ssklower * (nam). 23336389Ssklower * If we don't have a local address for this socket yet, 23436389Ssklower * we pick one by calling iso_pcbbind(). 23536389Ssklower * 23636389Ssklower * RETURNS: errno E* or 0 if ok. 23736389Ssklower * 23836389Ssklower * SIDE EFFECTS: Looks up a route, which may cause one to be left 23936389Ssklower * in the isopcb. 24036389Ssklower * 24136389Ssklower * NOTES: 24236389Ssklower */ 24336389Ssklower int 24436389Ssklower iso_pcbconnect(isop, nam) 24537469Ssklower register struct isopcb *isop; 24636389Ssklower struct mbuf *nam; 24736389Ssklower { 24836389Ssklower register struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *); 24937469Ssklower int local_zero, error = 0; 25037469Ssklower struct iso_ifaddr *ia; 25136389Ssklower 25236389Ssklower IFDEBUG(D_ISO) 25337469Ssklower printf("iso_pcbconnect(isop 0x%x sock 0x%x nam 0x%x", 25437469Ssklower isop, isop->isop_socket, nam); 25537469Ssklower printf("nam->m_len 0x%x), addr:\n", nam->m_len); 25636389Ssklower dump_isoaddr(siso); 25736389Ssklower ENDDEBUG 25837469Ssklower if (nam->m_len < siso->siso_len) 25937469Ssklower return EINVAL; 26036389Ssklower if (siso->siso_family != AF_ISO) 26136389Ssklower return EAFNOSUPPORT; 26238477Ssklower if (siso->siso_nlen == 0) { 26338477Ssklower if (ia = iso_ifaddr) { 26438477Ssklower int nlen = ia->ia_addr.siso_nlen; 26538477Ssklower ovbcopy(TSEL(siso), nlen + TSEL(siso), 26638841Ssklower siso->siso_plen + siso->siso_tlen + siso->siso_slen); 26738477Ssklower bcopy((caddr_t)&ia->ia_addr.siso_addr, 26838477Ssklower (caddr_t)&siso->siso_addr, nlen + 1); 26938477Ssklower /* includes siso->siso_nlen = nlen; */ 27038477Ssklower } else 27138477Ssklower return EADDRNOTAVAIL; 27238477Ssklower } 27337469Ssklower /* 27437469Ssklower * Local zero means either not bound, or bound to a TSEL, but no 27537469Ssklower * particular local interface. So, if we want to send somebody 27637469Ssklower * we need to choose a return address. 27736389Ssklower */ 27837469Ssklower local_zero = 27937469Ssklower ((isop->isop_laddr == 0) || (isop->isop_laddr->siso_nlen == 0)); 28036389Ssklower if (local_zero) { 28137469Ssklower int flags; 28236389Ssklower 28336389Ssklower IFDEBUG(D_ISO) 28436389Ssklower printf("iso_pcbconnect localzero 1\n"); 28536389Ssklower ENDDEBUG 28636389Ssklower /* 28736389Ssklower * If route is known or can be allocated now, 28836389Ssklower * our src addr is taken from the i/f, else punt. 28936389Ssklower */ 29037469Ssklower flags = isop->isop_socket->so_options & SO_DONTROUTE; 29137469Ssklower if (error = clnp_route(&siso->siso_addr, &isop->isop_route, flags, 29237469Ssklower (struct sockaddr **)0, &ia)) 29337469Ssklower return error; 29436389Ssklower IFDEBUG(D_ISO) 29537469Ssklower printf("iso_pcbconnect localzero 2, ro->ro_rt 0x%x", 29637469Ssklower isop->isop_route.ro_rt); 29737469Ssklower printf(" ia 0x%x\n", ia); 29836389Ssklower ENDDEBUG 29936389Ssklower } 30036389Ssklower IFDEBUG(D_ISO) 30136389Ssklower printf("in iso_pcbconnect before lookup isop 0x%x isop->sock 0x%x\n", 30236389Ssklower isop, isop->isop_socket); 30336389Ssklower ENDDEBUG 30436389Ssklower if (local_zero) { 30537469Ssklower int nlen, tlen, totlen; caddr_t oldtsel, newtsel; 30637469Ssklower siso = isop->isop_laddr; 30738841Ssklower if (siso == 0 || siso->siso_tlen == 0) 30836389Ssklower (void)iso_pcbbind(isop, (struct mbuf *)0); 30937469Ssklower /* 31037469Ssklower * Here we have problem of squezeing in a definite network address 31137469Ssklower * into an existing sockaddr_iso, which in fact may not have room 31237469Ssklower * for it. This gets messy. 31337469Ssklower */ 31437469Ssklower siso = isop->isop_laddr; 31537469Ssklower oldtsel = TSEL(siso); 31638841Ssklower tlen = siso->siso_tlen; 31737469Ssklower nlen = ia->ia_addr.siso_nlen; 31837469Ssklower totlen = tlen + nlen + _offsetof(struct sockaddr_iso, siso_data[0]); 31937469Ssklower if ((siso == &isop->isop_sladdr) && 32037469Ssklower (totlen > sizeof(isop->isop_sladdr))) { 32137469Ssklower struct mbuf *m = m_get(MT_SONAME, M_DONTWAIT); 32237469Ssklower if (m == 0) 32337469Ssklower return ENOBUFS; 32437469Ssklower m->m_len = totlen; 32537469Ssklower isop->isop_laddr = siso = mtod(m, struct sockaddr_iso *); 32637469Ssklower } 32737469Ssklower siso->siso_nlen = ia->ia_addr.siso_nlen; 32837469Ssklower newtsel = TSEL(siso); 32937469Ssklower ovbcopy(oldtsel, newtsel, tlen); 33037469Ssklower bcopy(ia->ia_addr.siso_data, siso->siso_data, nlen); 33138841Ssklower siso->siso_tlen = tlen; 33237469Ssklower siso->siso_family = AF_ISO; 33337469Ssklower siso->siso_len = totlen; 33437469Ssklower siso = mtod(nam, struct sockaddr_iso *); 33536389Ssklower } 33636389Ssklower IFDEBUG(D_ISO) 33736389Ssklower printf("in iso_pcbconnect before bcopy isop 0x%x isop->sock 0x%x\n", 33836389Ssklower isop, isop->isop_socket); 33936389Ssklower ENDDEBUG 34037469Ssklower /* 34137469Ssklower * If we had to allocate space to a previous big foreign address, 34237469Ssklower * and for some reason we didn't free it, we reuse it knowing 34337469Ssklower * that is going to be big enough, as sockaddrs are delivered in 34437469Ssklower * 128 byte mbufs. 34537469Ssklower * If the foreign address is small enough, we use default space; 34637469Ssklower * otherwise, we grab an mbuf to copy into. 34737469Ssklower */ 34837469Ssklower if (isop->isop_faddr == 0 || isop->isop_faddr == &isop->isop_sfaddr) { 34937469Ssklower if (siso->siso_len <= sizeof(isop->isop_sfaddr)) 35037469Ssklower isop->isop_faddr = &isop->isop_sfaddr; 35137469Ssklower else { 35237469Ssklower struct mbuf *m = m_get(MT_SONAME, M_DONTWAIT); 35337469Ssklower if (m == 0) 35437469Ssklower return ENOBUFS; 35537469Ssklower isop->isop_faddr = mtod(m, struct sockaddr_iso *); 35637469Ssklower } 35737469Ssklower } 35837469Ssklower bcopy((caddr_t)siso, (caddr_t)isop->isop_faddr, siso->siso_len); 35936389Ssklower IFDEBUG(D_ISO) 36036389Ssklower printf("in iso_pcbconnect after bcopy isop 0x%x isop->sock 0x%x\n", 36136389Ssklower isop, isop->isop_socket); 36236389Ssklower printf("iso_pcbconnect connected to addr:\n"); 36337469Ssklower dump_isoaddr(isop->isop_faddr); 36436389Ssklower printf("iso_pcbconnect end: src addr:\n"); 36537469Ssklower dump_isoaddr(isop->isop_laddr); 36636389Ssklower ENDDEBUG 36736389Ssklower return 0; 36836389Ssklower } 36936389Ssklower 37036389Ssklower /* 37136389Ssklower * FUNCTION: iso_pcbdisconnect() 37236389Ssklower * 37336389Ssklower * PURPOSE: washes away the peer address info so the socket 37436389Ssklower * appears to be disconnected. 37536389Ssklower * If there's no file descriptor associated with the socket 37636389Ssklower * it detaches the pcb. 37736389Ssklower * 37836389Ssklower * RETURNS: Nada. 37936389Ssklower * 38036389Ssklower * SIDE EFFECTS: May detach the pcb. 38136389Ssklower * 38236389Ssklower * NOTES: 38336389Ssklower */ 38436389Ssklower void 38536389Ssklower iso_pcbdisconnect(isop) 38636389Ssklower struct isopcb *isop; 38736389Ssklower { 38836389Ssklower void iso_pcbdetach(); 38939934Ssklower register struct sockaddr_iso *siso; 39036389Ssklower 39136389Ssklower IFDEBUG(D_ISO) 39236389Ssklower printf("iso_pcbdisconnect(isop 0x%x)\n", isop); 39336389Ssklower ENDDEBUG 39437469Ssklower /* 39537469Ssklower * Preserver binding infnormation if already bound. 39637469Ssklower */ 39739934Ssklower if ((siso = isop->isop_laddr) && siso->siso_nlen && siso->siso_tlen) { 39839934Ssklower caddr_t otsel = TSEL(siso); 39939934Ssklower siso->siso_nlen = 0; 40039934Ssklower ovbcopy(otsel, TSEL(siso), siso->siso_tlen); 40139934Ssklower } 40237469Ssklower if (isop->isop_faddr && isop->isop_faddr != &isop->isop_sfaddr) 40337469Ssklower m_freem(dtom(isop->isop_faddr)); 40437469Ssklower isop->isop_faddr = 0; 40536389Ssklower if (isop->isop_socket->so_state & SS_NOFDREF) 40636389Ssklower iso_pcbdetach(isop); 40736389Ssklower } 40836389Ssklower 40936389Ssklower /* 41036389Ssklower * FUNCTION: iso_pcbdetach 41136389Ssklower * 41236389Ssklower * PURPOSE: detach the pcb at *(isop) from it's socket and free 41336389Ssklower * the mbufs associated with the pcb.. 41436389Ssklower * Dequeues (isop) from its head. 41536389Ssklower * 41636389Ssklower * RETURNS: Nada. 41736389Ssklower * 41836389Ssklower * SIDE EFFECTS: 41936389Ssklower * 42036389Ssklower * NOTES: 42136389Ssklower */ 42236389Ssklower void 42336389Ssklower iso_pcbdetach(isop) 42436389Ssklower struct isopcb *isop; 42536389Ssklower { 42636389Ssklower struct socket *so = isop->isop_socket; 42736389Ssklower 42836389Ssklower IFDEBUG(D_ISO) 42936389Ssklower printf("iso_pcbdetach(isop 0x%x socket 0x%x so 0x%x)\n", 43036389Ssklower isop, isop->isop_socket, so); 43136389Ssklower ENDDEBUG 43248737Ssklower #ifdef TPCONS 43350648Ssklower if (isop->isop_chan) { 43448737Ssklower register struct pklcd *lcp = (struct pklcd *)isop->isop_chan; 43548737Ssklower if (--isop->isop_refcnt > 0) 43648737Ssklower return; 43750648Ssklower if (lcp && lcp->lcd_state == DATA_TRANSFER) { 43850648Ssklower lcp->lcd_upper = 0; 43950648Ssklower lcp->lcd_upnext = 0; 44048737Ssklower pk_disconnect(lcp); 44150648Ssklower } 44248737Ssklower isop->isop_chan = 0; 44348737Ssklower } 44448737Ssklower #endif 44548737Ssklower if (so) { /* in the x.25 domain, we sometimes have no socket */ 44636389Ssklower so->so_pcb = 0; 44736389Ssklower sofree(so); 44836389Ssklower } 44936389Ssklower IFDEBUG(D_ISO) 45036389Ssklower printf("iso_pcbdetach 2 \n"); 45136389Ssklower ENDDEBUG 45236389Ssklower if (isop->isop_options) 45336389Ssklower (void)m_free(isop->isop_options); 45436389Ssklower IFDEBUG(D_ISO) 45536389Ssklower printf("iso_pcbdetach 3 \n"); 45636389Ssklower ENDDEBUG 45736389Ssklower if (isop->isop_route.ro_rt) 45836389Ssklower rtfree(isop->isop_route.ro_rt); 45936389Ssklower IFDEBUG(D_ISO) 46036389Ssklower printf("iso_pcbdetach 3.1\n"); 46136389Ssklower ENDDEBUG 46236389Ssklower if (isop->isop_clnpcache != NULL) { 46336389Ssklower struct clnp_cache *clcp = 46436389Ssklower mtod(isop->isop_clnpcache, struct clnp_cache *); 46536389Ssklower IFDEBUG(D_ISO) 46636389Ssklower printf("iso_pcbdetach 3.2: clcp 0x%x freeing clc_hdr x%x\n", 46736389Ssklower clcp, clcp->clc_hdr); 46836389Ssklower ENDDEBUG 46936389Ssklower if (clcp->clc_hdr != NULL) 47036389Ssklower m_free(clcp->clc_hdr); 47136389Ssklower IFDEBUG(D_ISO) 47236389Ssklower printf("iso_pcbdetach 3.3: freeing cache x%x\n", 47336389Ssklower isop->isop_clnpcache); 47436389Ssklower ENDDEBUG 47536389Ssklower m_free(isop->isop_clnpcache); 47636389Ssklower } 47736389Ssklower IFDEBUG(D_ISO) 47836389Ssklower printf("iso_pcbdetach 4 \n"); 47936389Ssklower ENDDEBUG 48036389Ssklower remque(isop); 48136389Ssklower IFDEBUG(D_ISO) 48236389Ssklower printf("iso_pcbdetach 5 \n"); 48336389Ssklower ENDDEBUG 48437469Ssklower if (isop->isop_laddr && (isop->isop_laddr != &isop->isop_sladdr)) 48537469Ssklower m_freem(dtom(isop->isop_laddr)); 48640951Ssklower free((caddr_t)isop, M_PCB); 48736389Ssklower } 48836389Ssklower 48936389Ssklower 49036389Ssklower /* 49136389Ssklower * FUNCTION: iso_pcbnotify 49236389Ssklower * 49336389Ssklower * PURPOSE: notify all connections in this protocol's queue (head) 49436389Ssklower * that have peer address (dst) of the problem (errno) 49536389Ssklower * by calling (notify) on the connections' isopcbs. 49636389Ssklower * 49736389Ssklower * RETURNS: Rien. 49836389Ssklower * 49936389Ssklower * SIDE EFFECTS: 50036389Ssklower * 50136389Ssklower * NOTES: (notify) is called at splimp! 50236389Ssklower */ 50336389Ssklower void 50439934Ssklower iso_pcbnotify(head, siso, errno, notify) 50536389Ssklower struct isopcb *head; 50639934Ssklower register struct sockaddr_iso *siso; 50736389Ssklower int errno, (*notify)(); 50836389Ssklower { 50939934Ssklower register struct isopcb *isop; 51036389Ssklower int s = splimp(); 51136389Ssklower 51236389Ssklower IFDEBUG(D_ISO) 51336389Ssklower printf("iso_pcbnotify(head 0x%x, notify 0x%x) dst:\n", head, notify); 51436389Ssklower ENDDEBUG 51539934Ssklower for (isop = head->isop_next; isop != head; isop = isop->isop_next) { 51639934Ssklower if (isop->isop_socket == 0 || isop->isop_faddr == 0 || 51739934Ssklower !SAME_ISOADDR(siso, isop->isop_faddr)) { 51836389Ssklower IFDEBUG(D_ISO) 51936389Ssklower printf("iso_pcbnotify: CONTINUE isop 0x%x, sock 0x%x\n" , 52036389Ssklower isop, isop->isop_socket); 52139934Ssklower printf("addrmatch cmp'd with (0x%x):\n", isop->isop_faddr); 52237469Ssklower dump_isoaddr(isop->isop_faddr); 52336389Ssklower ENDDEBUG 52436389Ssklower continue; 52536389Ssklower } 52636389Ssklower if (errno) 52736389Ssklower isop->isop_socket->so_error = errno; 52836389Ssklower if (notify) 52939934Ssklower (*notify)(isop); 53036389Ssklower } 53136389Ssklower splx(s); 53236389Ssklower IFDEBUG(D_ISO) 53336389Ssklower printf("END OF iso_pcbnotify\n" ); 53436389Ssklower ENDDEBUG 53536389Ssklower } 53636389Ssklower 53736389Ssklower 53836389Ssklower /* 53936389Ssklower * FUNCTION: iso_pcblookup 54036389Ssklower * 54136389Ssklower * PURPOSE: looks for a given combination of (faddr), (fport), 54236389Ssklower * (lport), (laddr) in the queue named by (head). 54336389Ssklower * Argument (flags) is ignored. 54436389Ssklower * 54536389Ssklower * RETURNS: ptr to the isopcb if it finds a connection matching 54636389Ssklower * these arguments, o.w. returns zero. 54736389Ssklower * 54836389Ssklower * SIDE EFFECTS: 54936389Ssklower * 55036389Ssklower * NOTES: 55136389Ssklower */ 55236389Ssklower struct isopcb * 55337469Ssklower iso_pcblookup(head, fportlen, fport, laddr) 55436389Ssklower struct isopcb *head; 55537469Ssklower register struct sockaddr_iso *laddr; 55637469Ssklower caddr_t fport; 55737469Ssklower int fportlen; 55836389Ssklower { 55936389Ssklower register struct isopcb *isop; 56037469Ssklower register caddr_t lp = TSEL(laddr); 56138841Ssklower unsigned int llen = laddr->siso_tlen; 56236389Ssklower 56336389Ssklower IFDEBUG(D_ISO) 56437469Ssklower printf("iso_pcblookup(head 0x%x laddr 0x%x fport 0x%x)\n", 56537469Ssklower head, laddr, fport); 56636389Ssklower ENDDEBUG 56736389Ssklower for (isop = head->isop_next; isop != head; isop = isop->isop_next) { 56837469Ssklower if (isop->isop_laddr == 0 || isop->isop_laddr == laddr) 56936389Ssklower continue; 57038841Ssklower if (isop->isop_laddr->siso_tlen != llen) 57136389Ssklower continue; 57237469Ssklower if (bcmp(lp, TSEL(isop->isop_laddr), llen)) 57337469Ssklower continue; 57437469Ssklower if (fportlen && isop->isop_faddr && 57537469Ssklower bcmp(fport, TSEL(isop->isop_faddr), (unsigned)fportlen)) 57637469Ssklower continue; 57736389Ssklower /* PHASE2 57836389Ssklower * addrmatch1 should be iso_addrmatch(a, b, mask) 57936389Ssklower * where mask is taken from isop->isop_laddrmask (new field) 58036389Ssklower * isop_lnetmask will also be available in isop 58136389Ssklower if (laddr != &zeroiso_addr && 58236389Ssklower !iso_addrmatch1(laddr, &(isop->isop_laddr.siso_addr))) 58336389Ssklower continue; 58437469Ssklower */ 58537469Ssklower if (laddr->siso_nlen && (!SAME_ISOADDR(laddr, isop->isop_laddr))) 58637469Ssklower continue; 58736389Ssklower return (isop); 58836389Ssklower } 58936389Ssklower return (struct isopcb *)0; 59036389Ssklower } 59160359Sbostic #endif /* ISO */ 592