136389Ssklower /*********************************************************** 236389Ssklower Copyright IBM Corporation 1987 336389Ssklower 436389Ssklower All Rights Reserved 536389Ssklower 636389Ssklower Permission to use, copy, modify, and distribute this software and its 736389Ssklower documentation for any purpose and without fee is hereby granted, 836389Ssklower provided that the above copyright notice appear in all copies and that 936389Ssklower both that copyright notice and this permission notice appear in 1036389Ssklower supporting documentation, and that the name of IBM not be 1136389Ssklower used in advertising or publicity pertaining to distribution of the 1236389Ssklower software without specific, written prior permission. 1336389Ssklower 1436389Ssklower IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 1536389Ssklower ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 1636389Ssklower IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 1736389Ssklower ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 1836389Ssklower WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 1936389Ssklower ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 2036389Ssklower SOFTWARE. 2136389Ssklower 2236389Ssklower ******************************************************************/ 2336389Ssklower 2436389Ssklower /* 2536389Ssklower * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison 2636389Ssklower */ 2736389Ssklower /* 2836389Ssklower * $Header: iso_pcb.c,v 4.5 88/06/29 14:59:56 hagens Exp $ 2936389Ssklower * $Source: /usr/argo/sys/netiso/RCS/iso_pcb.c,v $ 30*48737Ssklower * @(#)iso_pcb.c 7.8 (Berkeley) 04/26/91 3136389Ssklower * 3236389Ssklower * Iso address family net-layer(s) pcb stuff. NEH 1/29/87 3336389Ssklower */ 3438477Ssklower 3536389Ssklower #ifndef lint 3636389Ssklower static char *rcsid = "$Header: iso_pcb.c,v 4.5 88/06/29 14:59:56 hagens Exp $"; 3736389Ssklower #endif 3836389Ssklower 3936389Ssklower #ifdef ISO 4036389Ssklower 4136389Ssklower #include "param.h" 4236389Ssklower #include "systm.h" 4336389Ssklower #include "user.h" 4436389Ssklower #include "mbuf.h" 4537469Ssklower #include "socket.h" 4637469Ssklower #include "socketvar.h" 4737469Ssklower #include "argo_debug.h" 4837469Ssklower #include "iso.h" 4937469Ssklower #include "clnp.h" 5036389Ssklower #include "../netinet/in_systm.h" 5136389Ssklower #include "../net/if.h" 5236389Ssklower #include "../net/route.h" 5337469Ssklower #include "iso_pcb.h" 5437469Ssklower #include "iso_var.h" 5536389Ssklower #include "protosw.h" 5636389Ssklower 57*48737Ssklower #ifdef TPCONS 58*48737Ssklower #include "../netccitt/x25.h" 59*48737Ssklower #include "../netccitt/pk.h" 60*48737Ssklower #include "../netccitt/pk_var.h" 61*48737Ssklower #endif 62*48737Ssklower 6336389Ssklower #define PCBNULL (struct isopcb *)0 6436389Ssklower struct iso_addr zeroiso_addr = { 6536389Ssklower 0 6636389Ssklower }; 6736389Ssklower 6836389Ssklower 6936389Ssklower /* 7036389Ssklower * FUNCTION: iso_pcballoc 7136389Ssklower * 7236389Ssklower * PURPOSE: creates an isopcb structure in an mbuf, 7336389Ssklower * with socket (so), and 7436389Ssklower * puts it in the queue with head (head) 7536389Ssklower * 7636389Ssklower * RETURNS: 0 if OK, ENOBUFS if can't alloc the necessary mbuf 7736389Ssklower */ 7836389Ssklower int 7936389Ssklower iso_pcballoc(so, head) 8036389Ssklower struct socket *so; 8136389Ssklower struct isopcb *head; 8236389Ssklower { 8336389Ssklower register struct isopcb *isop; 8436389Ssklower 8536389Ssklower IFDEBUG(D_ISO) 8636389Ssklower printf("iso_pcballoc(so 0x%x)\n", so); 8736389Ssklower ENDDEBUG 8837469Ssklower MALLOC(isop, struct isopcb *, sizeof(*isop), M_PCB, M_NOWAIT); 8937469Ssklower if (isop == NULL) 9036389Ssklower return ENOBUFS; 9137469Ssklower bzero((caddr_t)isop, sizeof(*isop)); 9236389Ssklower isop->isop_head = head; 9336389Ssklower isop->isop_socket = so; 9436389Ssklower insque(isop, head); 95*48737Ssklower if (so) 96*48737Ssklower so->so_pcb = (caddr_t)isop; 9736389Ssklower return 0; 9836389Ssklower } 9936389Ssklower 10036389Ssklower /* 10136389Ssklower * FUNCTION: iso_pcbbind 10236389Ssklower * 10336389Ssklower * PURPOSE: binds the address given in *(nam) to the socket 10436389Ssklower * specified by the isopcb in *(isop) 10536389Ssklower * If the given address is zero, it makes sure the 10636389Ssklower * address isn't already in use and if it's got a network 10736389Ssklower * portion, we look for an interface with that network 10836389Ssklower * address. If the address given is zero, we allocate 10936389Ssklower * a port and stuff it in the (nam) structure. 11036389Ssklower * 11136389Ssklower * RETURNS: errno E* or 0 if ok. 11236389Ssklower * 11336389Ssklower * SIDE EFFECTS: increments head->isop_lport if it allocates a port # 11436389Ssklower * 11536389Ssklower * NOTES: 11636389Ssklower */ 11737469Ssklower #define satosiso(sa) ((struct sockaddr_iso *)(sa)) 11836389Ssklower int 11936389Ssklower iso_pcbbind(isop, nam) 12036389Ssklower register struct isopcb *isop; 12136389Ssklower struct mbuf *nam; 12236389Ssklower { 12336389Ssklower register struct isopcb *head = isop->isop_head; 12436389Ssklower register struct sockaddr_iso *siso; 12537469Ssklower struct iso_ifaddr *ia; 12637469Ssklower union { 12737469Ssklower char data[2]; 12837469Ssklower u_short s; 12937469Ssklower } suf; 13036389Ssklower 13136389Ssklower IFDEBUG(D_ISO) 13236389Ssklower printf("iso_pcbbind(isop 0x%x, nam 0x%x)\n", isop, nam); 13336389Ssklower ENDDEBUG 13437469Ssklower suf.s = 0; 13536389Ssklower if (iso_ifaddr == 0) /* any interfaces attached? */ 13636389Ssklower return EADDRNOTAVAIL; 13737469Ssklower if (isop->isop_laddr) /* already bound */ 13836389Ssklower return EADDRINUSE; 13937469Ssklower if(nam == (struct mbuf *)0) { 14037469Ssklower isop->isop_laddr = &isop->isop_sladdr; 14138841Ssklower isop->isop_sladdr.siso_len = sizeof(struct sockaddr_iso); 14238841Ssklower isop->isop_sladdr.siso_family = AF_ISO; 14338841Ssklower isop->isop_sladdr.siso_tlen = 2; 14437469Ssklower isop->isop_sladdr.siso_nlen = 0; 14538841Ssklower isop->isop_sladdr.siso_slen = 0; 14638841Ssklower isop->isop_sladdr.siso_plen = 0; 14736389Ssklower goto noname; 14837469Ssklower } 14936389Ssklower siso = mtod(nam, struct sockaddr_iso *); 15036389Ssklower IFDEBUG(D_ISO) 15136389Ssklower printf("iso_pcbbind(name len 0x%x)\n", nam->m_len); 15236389Ssklower printf("The address is %s\n", clnp_iso_addrp(&siso->siso_addr)); 15336389Ssklower ENDDEBUG 15436389Ssklower /* 15536389Ssklower * We would like sort of length check but since some OSI addrs 15636389Ssklower * do not have fixed length, we can't really do much. 15736389Ssklower * The ONLY thing we can say is that an osi addr has to have 15836389Ssklower * at LEAST an afi and one more byte and had better fit into 15936389Ssklower * a struct iso_addr. 16036389Ssklower * However, in fact the size of the whole thing is a struct 16136389Ssklower * sockaddr_iso, so probably this is what we should check for. 16236389Ssklower */ 16337469Ssklower if( (nam->m_len < 2) || (nam->m_len < siso->siso_len)) { 16436389Ssklower return ENAMETOOLONG; 16536389Ssklower } 16638841Ssklower if (siso->siso_tlen) { 16737469Ssklower register char *cp = TSEL(siso); 16837469Ssklower suf.data[0] = cp[0]; 16937469Ssklower suf.data[1] = cp[1]; 17037469Ssklower } 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); 19039934Ssklower if (suf.s || siso->siso_tlen != 2) { 19138841Ssklower if((suf.s < ISO_PORT_RESERVED) && (siso->siso_tlen <= 2) && 19237469Ssklower (u.u_uid != 0)) 19336389Ssklower return EACCES; 19436389Ssklower if ((isop->isop_socket->so_options & SO_REUSEADDR) == 0 && 19537469Ssklower iso_pcblookup(head, 0, (caddr_t)0, isop->isop_laddr)) 19636389Ssklower return EADDRINUSE; 19737469Ssklower } else { 19837469Ssklower register char *cp; 19936389Ssklower noname: 20037469Ssklower cp = TSEL(isop->isop_laddr); 20136389Ssklower IFDEBUG(D_ISO) 20236389Ssklower printf("iso_pcbbind noname\n"); 20336389Ssklower ENDDEBUG 20436389Ssklower do { 20536389Ssklower if (head->isop_lport++ < ISO_PORT_RESERVED || 20636389Ssklower head->isop_lport > ISO_PORT_USERRESERVED) 20736389Ssklower head->isop_lport = ISO_PORT_RESERVED; 20837469Ssklower suf.s = head->isop_lport; 20937469Ssklower cp[0] = suf.data[0]; 21037469Ssklower cp[1] = suf.data[1]; 21137469Ssklower } while (iso_pcblookup(head, 0, (caddr_t)0, isop->isop_laddr)); 21237469Ssklower } 21336389Ssklower IFDEBUG(D_ISO) 21436389Ssklower printf("iso_pcbbind returns 0, suf 0x%x\n", suf); 21536389Ssklower ENDDEBUG 21636389Ssklower return 0; 21736389Ssklower } 21836389Ssklower /* 21936389Ssklower * FUNCTION: iso_pcbconnect 22036389Ssklower * 22136389Ssklower * PURPOSE: Make the isopcb (isop) look like it's connected. 22236389Ssklower * In other words, give it the peer address given in 22336389Ssklower * the mbuf * (nam). Make sure such a combination 22436389Ssklower * of local, peer addresses doesn't already exist 22536389Ssklower * for this protocol. Internet mentality prevails here, 22636389Ssklower * wherein a src,dst pair uniquely identifies a connection. 22736389Ssklower * Both net address and port must be specified in argument 22836389Ssklower * (nam). 22936389Ssklower * If we don't have a local address for this socket yet, 23036389Ssklower * we pick one by calling iso_pcbbind(). 23136389Ssklower * 23236389Ssklower * RETURNS: errno E* or 0 if ok. 23336389Ssklower * 23436389Ssklower * SIDE EFFECTS: Looks up a route, which may cause one to be left 23536389Ssklower * in the isopcb. 23636389Ssklower * 23736389Ssklower * NOTES: 23836389Ssklower */ 23936389Ssklower int 24036389Ssklower iso_pcbconnect(isop, nam) 24137469Ssklower register struct isopcb *isop; 24236389Ssklower struct mbuf *nam; 24336389Ssklower { 24436389Ssklower register struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *); 24537469Ssklower int local_zero, error = 0; 24637469Ssklower struct iso_ifaddr *ia; 24736389Ssklower 24836389Ssklower IFDEBUG(D_ISO) 24937469Ssklower printf("iso_pcbconnect(isop 0x%x sock 0x%x nam 0x%x", 25037469Ssklower isop, isop->isop_socket, nam); 25137469Ssklower printf("nam->m_len 0x%x), addr:\n", nam->m_len); 25236389Ssklower dump_isoaddr(siso); 25336389Ssklower ENDDEBUG 25437469Ssklower if (nam->m_len < siso->siso_len) 25537469Ssklower return EINVAL; 25636389Ssklower if (siso->siso_family != AF_ISO) 25736389Ssklower return EAFNOSUPPORT; 25838477Ssklower if (siso->siso_nlen == 0) { 25938477Ssklower if (ia = iso_ifaddr) { 26038477Ssklower int nlen = ia->ia_addr.siso_nlen; 26138477Ssklower ovbcopy(TSEL(siso), nlen + TSEL(siso), 26238841Ssklower siso->siso_plen + siso->siso_tlen + siso->siso_slen); 26338477Ssklower bcopy((caddr_t)&ia->ia_addr.siso_addr, 26438477Ssklower (caddr_t)&siso->siso_addr, nlen + 1); 26538477Ssklower /* includes siso->siso_nlen = nlen; */ 26638477Ssklower } else 26738477Ssklower return EADDRNOTAVAIL; 26838477Ssklower } 26937469Ssklower /* 27037469Ssklower * Local zero means either not bound, or bound to a TSEL, but no 27137469Ssklower * particular local interface. So, if we want to send somebody 27237469Ssklower * we need to choose a return address. 27336389Ssklower */ 27437469Ssklower local_zero = 27537469Ssklower ((isop->isop_laddr == 0) || (isop->isop_laddr->siso_nlen == 0)); 27636389Ssklower if (local_zero) { 27737469Ssklower int flags; 27836389Ssklower 27936389Ssklower IFDEBUG(D_ISO) 28036389Ssklower printf("iso_pcbconnect localzero 1\n"); 28136389Ssklower ENDDEBUG 28236389Ssklower /* 28336389Ssklower * If route is known or can be allocated now, 28436389Ssklower * our src addr is taken from the i/f, else punt. 28536389Ssklower */ 28637469Ssklower flags = isop->isop_socket->so_options & SO_DONTROUTE; 28737469Ssklower if (error = clnp_route(&siso->siso_addr, &isop->isop_route, flags, 28837469Ssklower (struct sockaddr **)0, &ia)) 28937469Ssklower return error; 29036389Ssklower IFDEBUG(D_ISO) 29137469Ssklower printf("iso_pcbconnect localzero 2, ro->ro_rt 0x%x", 29237469Ssklower isop->isop_route.ro_rt); 29337469Ssklower printf(" ia 0x%x\n", ia); 29436389Ssklower ENDDEBUG 29536389Ssklower } 29636389Ssklower IFDEBUG(D_ISO) 29736389Ssklower printf("in iso_pcbconnect before lookup isop 0x%x isop->sock 0x%x\n", 29836389Ssklower isop, isop->isop_socket); 29936389Ssklower ENDDEBUG 30036389Ssklower if (local_zero) { 30137469Ssklower int nlen, tlen, totlen; caddr_t oldtsel, newtsel; 30237469Ssklower siso = isop->isop_laddr; 30338841Ssklower if (siso == 0 || siso->siso_tlen == 0) 30436389Ssklower (void)iso_pcbbind(isop, (struct mbuf *)0); 30537469Ssklower /* 30637469Ssklower * Here we have problem of squezeing in a definite network address 30737469Ssklower * into an existing sockaddr_iso, which in fact may not have room 30837469Ssklower * for it. This gets messy. 30937469Ssklower */ 31037469Ssklower siso = isop->isop_laddr; 31137469Ssklower oldtsel = TSEL(siso); 31238841Ssklower tlen = siso->siso_tlen; 31337469Ssklower nlen = ia->ia_addr.siso_nlen; 31437469Ssklower totlen = tlen + nlen + _offsetof(struct sockaddr_iso, siso_data[0]); 31537469Ssklower if ((siso == &isop->isop_sladdr) && 31637469Ssklower (totlen > sizeof(isop->isop_sladdr))) { 31737469Ssklower struct mbuf *m = m_get(MT_SONAME, M_DONTWAIT); 31837469Ssklower if (m == 0) 31937469Ssklower return ENOBUFS; 32037469Ssklower m->m_len = totlen; 32137469Ssklower isop->isop_laddr = siso = mtod(m, struct sockaddr_iso *); 32237469Ssklower } 32337469Ssklower siso->siso_nlen = ia->ia_addr.siso_nlen; 32437469Ssklower newtsel = TSEL(siso); 32537469Ssklower ovbcopy(oldtsel, newtsel, tlen); 32637469Ssklower bcopy(ia->ia_addr.siso_data, siso->siso_data, nlen); 32738841Ssklower siso->siso_tlen = tlen; 32837469Ssklower siso->siso_family = AF_ISO; 32937469Ssklower siso->siso_len = totlen; 33037469Ssklower siso = mtod(nam, struct sockaddr_iso *); 33136389Ssklower } 33236389Ssklower IFDEBUG(D_ISO) 33336389Ssklower printf("in iso_pcbconnect before bcopy isop 0x%x isop->sock 0x%x\n", 33436389Ssklower isop, isop->isop_socket); 33536389Ssklower ENDDEBUG 33637469Ssklower /* 33737469Ssklower * If we had to allocate space to a previous big foreign address, 33837469Ssklower * and for some reason we didn't free it, we reuse it knowing 33937469Ssklower * that is going to be big enough, as sockaddrs are delivered in 34037469Ssklower * 128 byte mbufs. 34137469Ssklower * If the foreign address is small enough, we use default space; 34237469Ssklower * otherwise, we grab an mbuf to copy into. 34337469Ssklower */ 34437469Ssklower if (isop->isop_faddr == 0 || isop->isop_faddr == &isop->isop_sfaddr) { 34537469Ssklower if (siso->siso_len <= sizeof(isop->isop_sfaddr)) 34637469Ssklower isop->isop_faddr = &isop->isop_sfaddr; 34737469Ssklower else { 34837469Ssklower struct mbuf *m = m_get(MT_SONAME, M_DONTWAIT); 34937469Ssklower if (m == 0) 35037469Ssklower return ENOBUFS; 35137469Ssklower isop->isop_faddr = mtod(m, struct sockaddr_iso *); 35237469Ssklower } 35337469Ssklower } 35437469Ssklower bcopy((caddr_t)siso, (caddr_t)isop->isop_faddr, siso->siso_len); 35536389Ssklower IFDEBUG(D_ISO) 35636389Ssklower printf("in iso_pcbconnect after bcopy isop 0x%x isop->sock 0x%x\n", 35736389Ssklower isop, isop->isop_socket); 35836389Ssklower printf("iso_pcbconnect connected to addr:\n"); 35937469Ssklower dump_isoaddr(isop->isop_faddr); 36036389Ssklower printf("iso_pcbconnect end: src addr:\n"); 36137469Ssklower dump_isoaddr(isop->isop_laddr); 36236389Ssklower ENDDEBUG 36336389Ssklower return 0; 36436389Ssklower } 36536389Ssklower 36636389Ssklower /* 36736389Ssklower * FUNCTION: iso_pcbdisconnect() 36836389Ssklower * 36936389Ssklower * PURPOSE: washes away the peer address info so the socket 37036389Ssklower * appears to be disconnected. 37136389Ssklower * If there's no file descriptor associated with the socket 37236389Ssklower * it detaches the pcb. 37336389Ssklower * 37436389Ssklower * RETURNS: Nada. 37536389Ssklower * 37636389Ssklower * SIDE EFFECTS: May detach the pcb. 37736389Ssklower * 37836389Ssklower * NOTES: 37936389Ssklower */ 38036389Ssklower void 38136389Ssklower iso_pcbdisconnect(isop) 38236389Ssklower struct isopcb *isop; 38336389Ssklower { 38436389Ssklower void iso_pcbdetach(); 38539934Ssklower register struct sockaddr_iso *siso; 38636389Ssklower 38736389Ssklower IFDEBUG(D_ISO) 38836389Ssklower printf("iso_pcbdisconnect(isop 0x%x)\n", isop); 38936389Ssklower ENDDEBUG 39037469Ssklower /* 39137469Ssklower * Preserver binding infnormation if already bound. 39237469Ssklower */ 39339934Ssklower if ((siso = isop->isop_laddr) && siso->siso_nlen && siso->siso_tlen) { 39439934Ssklower caddr_t otsel = TSEL(siso); 39539934Ssklower siso->siso_nlen = 0; 39639934Ssklower ovbcopy(otsel, TSEL(siso), siso->siso_tlen); 39739934Ssklower } 39837469Ssklower if (isop->isop_faddr && isop->isop_faddr != &isop->isop_sfaddr) 39937469Ssklower m_freem(dtom(isop->isop_faddr)); 40037469Ssklower isop->isop_faddr = 0; 40136389Ssklower if (isop->isop_socket->so_state & SS_NOFDREF) 40236389Ssklower iso_pcbdetach(isop); 40336389Ssklower } 40436389Ssklower 40536389Ssklower /* 40636389Ssklower * FUNCTION: iso_pcbdetach 40736389Ssklower * 40836389Ssklower * PURPOSE: detach the pcb at *(isop) from it's socket and free 40936389Ssklower * the mbufs associated with the pcb.. 41036389Ssklower * Dequeues (isop) from its head. 41136389Ssklower * 41236389Ssklower * RETURNS: Nada. 41336389Ssklower * 41436389Ssklower * SIDE EFFECTS: 41536389Ssklower * 41636389Ssklower * NOTES: 41736389Ssklower */ 41836389Ssklower void 41936389Ssklower iso_pcbdetach(isop) 42036389Ssklower struct isopcb *isop; 42136389Ssklower { 42236389Ssklower struct socket *so = isop->isop_socket; 42336389Ssklower 42436389Ssklower IFDEBUG(D_ISO) 42536389Ssklower printf("iso_pcbdetach(isop 0x%x socket 0x%x so 0x%x)\n", 42636389Ssklower isop, isop->isop_socket, so); 42736389Ssklower ENDDEBUG 428*48737Ssklower #ifdef TPCONS 429*48737Ssklower if (isop->isop_refcnt) { 430*48737Ssklower register struct pklcd *lcp = (struct pklcd *)isop->isop_chan; 431*48737Ssklower if (--isop->isop_refcnt > 0) 432*48737Ssklower return; 433*48737Ssklower if (lcp && lcp->lcd_state == DATA_TRANSFER) 434*48737Ssklower pk_disconnect(lcp); 435*48737Ssklower isop->isop_chan = 0; 436*48737Ssklower } 437*48737Ssklower #endif 438*48737Ssklower if (so) { /* in the x.25 domain, we sometimes have no socket */ 43936389Ssklower so->so_pcb = 0; 44036389Ssklower sofree(so); 44136389Ssklower } 44236389Ssklower IFDEBUG(D_ISO) 44336389Ssklower printf("iso_pcbdetach 2 \n"); 44436389Ssklower ENDDEBUG 44536389Ssklower if (isop->isop_options) 44636389Ssklower (void)m_free(isop->isop_options); 44736389Ssklower IFDEBUG(D_ISO) 44836389Ssklower printf("iso_pcbdetach 3 \n"); 44936389Ssklower ENDDEBUG 45036389Ssklower if (isop->isop_route.ro_rt) 45136389Ssklower rtfree(isop->isop_route.ro_rt); 45236389Ssklower IFDEBUG(D_ISO) 45336389Ssklower printf("iso_pcbdetach 3.1\n"); 45436389Ssklower ENDDEBUG 45536389Ssklower if (isop->isop_clnpcache != NULL) { 45636389Ssklower struct clnp_cache *clcp = 45736389Ssklower mtod(isop->isop_clnpcache, struct clnp_cache *); 45836389Ssklower IFDEBUG(D_ISO) 45936389Ssklower printf("iso_pcbdetach 3.2: clcp 0x%x freeing clc_hdr x%x\n", 46036389Ssklower clcp, clcp->clc_hdr); 46136389Ssklower ENDDEBUG 46236389Ssklower if (clcp->clc_hdr != NULL) 46336389Ssklower m_free(clcp->clc_hdr); 46436389Ssklower IFDEBUG(D_ISO) 46536389Ssklower printf("iso_pcbdetach 3.3: freeing cache x%x\n", 46636389Ssklower isop->isop_clnpcache); 46736389Ssklower ENDDEBUG 46836389Ssklower m_free(isop->isop_clnpcache); 46936389Ssklower } 47036389Ssklower IFDEBUG(D_ISO) 47136389Ssklower printf("iso_pcbdetach 4 \n"); 47236389Ssklower ENDDEBUG 47336389Ssklower remque(isop); 47436389Ssklower IFDEBUG(D_ISO) 47536389Ssklower printf("iso_pcbdetach 5 \n"); 47636389Ssklower ENDDEBUG 47737469Ssklower if (isop->isop_laddr && (isop->isop_laddr != &isop->isop_sladdr)) 47837469Ssklower m_freem(dtom(isop->isop_laddr)); 47940951Ssklower free((caddr_t)isop, M_PCB); 48036389Ssklower } 48136389Ssklower 48236389Ssklower 48336389Ssklower /* 48436389Ssklower * FUNCTION: iso_pcbnotify 48536389Ssklower * 48636389Ssklower * PURPOSE: notify all connections in this protocol's queue (head) 48736389Ssklower * that have peer address (dst) of the problem (errno) 48836389Ssklower * by calling (notify) on the connections' isopcbs. 48936389Ssklower * 49036389Ssklower * RETURNS: Rien. 49136389Ssklower * 49236389Ssklower * SIDE EFFECTS: 49336389Ssklower * 49436389Ssklower * NOTES: (notify) is called at splimp! 49536389Ssklower */ 49636389Ssklower void 49739934Ssklower iso_pcbnotify(head, siso, errno, notify) 49836389Ssklower struct isopcb *head; 49939934Ssklower register struct sockaddr_iso *siso; 50036389Ssklower int errno, (*notify)(); 50136389Ssklower { 50239934Ssklower register struct isopcb *isop; 50336389Ssklower int s = splimp(); 50436389Ssklower 50536389Ssklower IFDEBUG(D_ISO) 50636389Ssklower printf("iso_pcbnotify(head 0x%x, notify 0x%x) dst:\n", head, notify); 50736389Ssklower ENDDEBUG 50839934Ssklower for (isop = head->isop_next; isop != head; isop = isop->isop_next) { 50939934Ssklower if (isop->isop_socket == 0 || isop->isop_faddr == 0 || 51039934Ssklower !SAME_ISOADDR(siso, isop->isop_faddr)) { 51136389Ssklower IFDEBUG(D_ISO) 51236389Ssklower printf("iso_pcbnotify: CONTINUE isop 0x%x, sock 0x%x\n" , 51336389Ssklower isop, isop->isop_socket); 51439934Ssklower printf("addrmatch cmp'd with (0x%x):\n", isop->isop_faddr); 51537469Ssklower dump_isoaddr(isop->isop_faddr); 51636389Ssklower ENDDEBUG 51736389Ssklower continue; 51836389Ssklower } 51936389Ssklower if (errno) 52036389Ssklower isop->isop_socket->so_error = errno; 52136389Ssklower if (notify) 52239934Ssklower (*notify)(isop); 52336389Ssklower } 52436389Ssklower splx(s); 52536389Ssklower IFDEBUG(D_ISO) 52636389Ssklower printf("END OF iso_pcbnotify\n" ); 52736389Ssklower ENDDEBUG 52836389Ssklower } 52936389Ssklower 53036389Ssklower 53136389Ssklower /* 53236389Ssklower * FUNCTION: iso_pcblookup 53336389Ssklower * 53436389Ssklower * PURPOSE: looks for a given combination of (faddr), (fport), 53536389Ssklower * (lport), (laddr) in the queue named by (head). 53636389Ssklower * Argument (flags) is ignored. 53736389Ssklower * 53836389Ssklower * RETURNS: ptr to the isopcb if it finds a connection matching 53936389Ssklower * these arguments, o.w. returns zero. 54036389Ssklower * 54136389Ssklower * SIDE EFFECTS: 54236389Ssklower * 54336389Ssklower * NOTES: 54436389Ssklower */ 54536389Ssklower struct isopcb * 54637469Ssklower iso_pcblookup(head, fportlen, fport, laddr) 54736389Ssklower struct isopcb *head; 54837469Ssklower register struct sockaddr_iso *laddr; 54937469Ssklower caddr_t fport; 55037469Ssklower int fportlen; 55136389Ssklower { 55236389Ssklower register struct isopcb *isop; 55337469Ssklower register caddr_t lp = TSEL(laddr); 55438841Ssklower unsigned int llen = laddr->siso_tlen; 55536389Ssklower 55636389Ssklower IFDEBUG(D_ISO) 55737469Ssklower printf("iso_pcblookup(head 0x%x laddr 0x%x fport 0x%x)\n", 55837469Ssklower head, laddr, fport); 55936389Ssklower ENDDEBUG 56036389Ssklower for (isop = head->isop_next; isop != head; isop = isop->isop_next) { 56137469Ssklower if (isop->isop_laddr == 0 || isop->isop_laddr == laddr) 56236389Ssklower continue; 56338841Ssklower if (isop->isop_laddr->siso_tlen != llen) 56436389Ssklower continue; 56537469Ssklower if (bcmp(lp, TSEL(isop->isop_laddr), llen)) 56637469Ssklower continue; 56737469Ssklower if (fportlen && isop->isop_faddr && 56837469Ssklower bcmp(fport, TSEL(isop->isop_faddr), (unsigned)fportlen)) 56937469Ssklower continue; 57036389Ssklower /* PHASE2 57136389Ssklower * addrmatch1 should be iso_addrmatch(a, b, mask) 57236389Ssklower * where mask is taken from isop->isop_laddrmask (new field) 57336389Ssklower * isop_lnetmask will also be available in isop 57436389Ssklower if (laddr != &zeroiso_addr && 57536389Ssklower !iso_addrmatch1(laddr, &(isop->isop_laddr.siso_addr))) 57636389Ssklower continue; 57737469Ssklower */ 57837469Ssklower if (laddr->siso_nlen && (!SAME_ISOADDR(laddr, isop->isop_laddr))) 57937469Ssklower continue; 58036389Ssklower return (isop); 58136389Ssklower } 58236389Ssklower return (struct isopcb *)0; 58336389Ssklower } 58436389Ssklower #endif ISO 585