1*49268Sbostic /*- 2*49268Sbostic * Copyright (c) 1991 The Regents of the University of California. 3*49268Sbostic * All rights reserved. 4*49268Sbostic * 5*49268Sbostic * %sccs.include.redist.c% 6*49268Sbostic * 7*49268Sbostic * @(#)iso_pcb.c 7.9 (Berkeley) 05/06/91 8*49268Sbostic */ 9*49268Sbostic 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 4536389Ssklower #include "param.h" 4636389Ssklower #include "systm.h" 4736389Ssklower #include "user.h" 4836389Ssklower #include "mbuf.h" 4937469Ssklower #include "socket.h" 5037469Ssklower #include "socketvar.h" 5137469Ssklower #include "argo_debug.h" 5237469Ssklower #include "iso.h" 5337469Ssklower #include "clnp.h" 5436389Ssklower #include "../netinet/in_systm.h" 5536389Ssklower #include "../net/if.h" 5636389Ssklower #include "../net/route.h" 5737469Ssklower #include "iso_pcb.h" 5837469Ssklower #include "iso_var.h" 5936389Ssklower #include "protosw.h" 6036389Ssklower 6148737Ssklower #ifdef TPCONS 6248737Ssklower #include "../netccitt/x25.h" 6348737Ssklower #include "../netccitt/pk.h" 6448737Ssklower #include "../netccitt/pk_var.h" 6548737Ssklower #endif 6648737Ssklower 6736389Ssklower #define PCBNULL (struct isopcb *)0 6836389Ssklower struct iso_addr zeroiso_addr = { 6936389Ssklower 0 7036389Ssklower }; 7136389Ssklower 7236389Ssklower 7336389Ssklower /* 7436389Ssklower * FUNCTION: iso_pcballoc 7536389Ssklower * 7636389Ssklower * PURPOSE: creates an isopcb structure in an mbuf, 7736389Ssklower * with socket (so), and 7836389Ssklower * puts it in the queue with head (head) 7936389Ssklower * 8036389Ssklower * RETURNS: 0 if OK, ENOBUFS if can't alloc the necessary mbuf 8136389Ssklower */ 8236389Ssklower int 8336389Ssklower iso_pcballoc(so, head) 8436389Ssklower struct socket *so; 8536389Ssklower struct isopcb *head; 8636389Ssklower { 8736389Ssklower register struct isopcb *isop; 8836389Ssklower 8936389Ssklower IFDEBUG(D_ISO) 9036389Ssklower printf("iso_pcballoc(so 0x%x)\n", so); 9136389Ssklower ENDDEBUG 9237469Ssklower MALLOC(isop, struct isopcb *, sizeof(*isop), M_PCB, M_NOWAIT); 9337469Ssklower if (isop == NULL) 9436389Ssklower return ENOBUFS; 9537469Ssklower bzero((caddr_t)isop, sizeof(*isop)); 9636389Ssklower isop->isop_head = head; 9736389Ssklower isop->isop_socket = so; 9836389Ssklower insque(isop, head); 9948737Ssklower if (so) 10048737Ssklower so->so_pcb = (caddr_t)isop; 10136389Ssklower return 0; 10236389Ssklower } 10336389Ssklower 10436389Ssklower /* 10536389Ssklower * FUNCTION: iso_pcbbind 10636389Ssklower * 10736389Ssklower * PURPOSE: binds the address given in *(nam) to the socket 10836389Ssklower * specified by the isopcb in *(isop) 10936389Ssklower * If the given address is zero, it makes sure the 11036389Ssklower * address isn't already in use and if it's got a network 11136389Ssklower * portion, we look for an interface with that network 11236389Ssklower * address. If the address given is zero, we allocate 11336389Ssklower * a port and stuff it in the (nam) structure. 11436389Ssklower * 11536389Ssklower * RETURNS: errno E* or 0 if ok. 11636389Ssklower * 11736389Ssklower * SIDE EFFECTS: increments head->isop_lport if it allocates a port # 11836389Ssklower * 11936389Ssklower * NOTES: 12036389Ssklower */ 12137469Ssklower #define satosiso(sa) ((struct sockaddr_iso *)(sa)) 12236389Ssklower int 12336389Ssklower iso_pcbbind(isop, nam) 12436389Ssklower register struct isopcb *isop; 12536389Ssklower struct mbuf *nam; 12636389Ssklower { 12736389Ssklower register struct isopcb *head = isop->isop_head; 12836389Ssklower register struct sockaddr_iso *siso; 12937469Ssklower struct iso_ifaddr *ia; 13037469Ssklower union { 13137469Ssklower char data[2]; 13237469Ssklower u_short s; 13337469Ssklower } suf; 13436389Ssklower 13536389Ssklower IFDEBUG(D_ISO) 13636389Ssklower printf("iso_pcbbind(isop 0x%x, nam 0x%x)\n", isop, nam); 13736389Ssklower ENDDEBUG 13837469Ssklower suf.s = 0; 13936389Ssklower if (iso_ifaddr == 0) /* any interfaces attached? */ 14036389Ssklower return EADDRNOTAVAIL; 14137469Ssklower if (isop->isop_laddr) /* already bound */ 14236389Ssklower return EADDRINUSE; 14337469Ssklower if(nam == (struct mbuf *)0) { 14437469Ssklower isop->isop_laddr = &isop->isop_sladdr; 14538841Ssklower isop->isop_sladdr.siso_len = sizeof(struct sockaddr_iso); 14638841Ssklower isop->isop_sladdr.siso_family = AF_ISO; 14738841Ssklower isop->isop_sladdr.siso_tlen = 2; 14837469Ssklower isop->isop_sladdr.siso_nlen = 0; 14938841Ssklower isop->isop_sladdr.siso_slen = 0; 15038841Ssklower isop->isop_sladdr.siso_plen = 0; 15136389Ssklower goto noname; 15237469Ssklower } 15336389Ssklower siso = mtod(nam, struct sockaddr_iso *); 15436389Ssklower IFDEBUG(D_ISO) 15536389Ssklower printf("iso_pcbbind(name len 0x%x)\n", nam->m_len); 15636389Ssklower printf("The address is %s\n", clnp_iso_addrp(&siso->siso_addr)); 15736389Ssklower ENDDEBUG 15836389Ssklower /* 15936389Ssklower * We would like sort of length check but since some OSI addrs 16036389Ssklower * do not have fixed length, we can't really do much. 16136389Ssklower * The ONLY thing we can say is that an osi addr has to have 16236389Ssklower * at LEAST an afi and one more byte and had better fit into 16336389Ssklower * a struct iso_addr. 16436389Ssklower * However, in fact the size of the whole thing is a struct 16536389Ssklower * sockaddr_iso, so probably this is what we should check for. 16636389Ssklower */ 16737469Ssklower if( (nam->m_len < 2) || (nam->m_len < siso->siso_len)) { 16836389Ssklower return ENAMETOOLONG; 16936389Ssklower } 17038841Ssklower if (siso->siso_tlen) { 17137469Ssklower register char *cp = TSEL(siso); 17237469Ssklower suf.data[0] = cp[0]; 17337469Ssklower suf.data[1] = cp[1]; 17437469Ssklower } 17537469Ssklower if (siso->siso_nlen) { 17636389Ssklower /* non-zero net addr- better match one of our interfaces */ 17736389Ssklower IFDEBUG(D_ISO) 17836389Ssklower printf("iso_pcbbind: bind to NOT zeroisoaddr\n"); 17936389Ssklower ENDDEBUG 18037469Ssklower for (ia = iso_ifaddr; ia; ia = ia->ia_next) 18137469Ssklower if (SAME_ISOADDR(siso, &ia->ia_addr)) 18237469Ssklower break; 18337469Ssklower if (ia == 0) 18436389Ssklower return EADDRNOTAVAIL; 18536389Ssklower } 18637469Ssklower if (siso->siso_len <= sizeof (isop->isop_sladdr)) { 18737469Ssklower isop->isop_laddr = &isop->isop_sladdr; 18837469Ssklower } else { 18937469Ssklower if ((nam = m_copy(nam, 0, (int)M_COPYALL)) == 0) 19037469Ssklower return ENOBUFS; 19137469Ssklower isop->isop_laddr = mtod(nam, struct sockaddr_iso *); 19237469Ssklower } 19337469Ssklower bcopy((caddr_t)siso, (caddr_t)isop->isop_laddr, siso->siso_len); 19439934Ssklower if (suf.s || siso->siso_tlen != 2) { 19538841Ssklower if((suf.s < ISO_PORT_RESERVED) && (siso->siso_tlen <= 2) && 19637469Ssklower (u.u_uid != 0)) 19736389Ssklower return EACCES; 19836389Ssklower if ((isop->isop_socket->so_options & SO_REUSEADDR) == 0 && 19937469Ssklower iso_pcblookup(head, 0, (caddr_t)0, isop->isop_laddr)) 20036389Ssklower return EADDRINUSE; 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; 21237469Ssklower suf.s = 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 43348737Ssklower if (isop->isop_refcnt) { 43448737Ssklower register struct pklcd *lcp = (struct pklcd *)isop->isop_chan; 43548737Ssklower if (--isop->isop_refcnt > 0) 43648737Ssklower return; 43748737Ssklower if (lcp && lcp->lcd_state == DATA_TRANSFER) 43848737Ssklower pk_disconnect(lcp); 43948737Ssklower isop->isop_chan = 0; 44048737Ssklower } 44148737Ssklower #endif 44248737Ssklower if (so) { /* in the x.25 domain, we sometimes have no socket */ 44336389Ssklower so->so_pcb = 0; 44436389Ssklower sofree(so); 44536389Ssklower } 44636389Ssklower IFDEBUG(D_ISO) 44736389Ssklower printf("iso_pcbdetach 2 \n"); 44836389Ssklower ENDDEBUG 44936389Ssklower if (isop->isop_options) 45036389Ssklower (void)m_free(isop->isop_options); 45136389Ssklower IFDEBUG(D_ISO) 45236389Ssklower printf("iso_pcbdetach 3 \n"); 45336389Ssklower ENDDEBUG 45436389Ssklower if (isop->isop_route.ro_rt) 45536389Ssklower rtfree(isop->isop_route.ro_rt); 45636389Ssklower IFDEBUG(D_ISO) 45736389Ssklower printf("iso_pcbdetach 3.1\n"); 45836389Ssklower ENDDEBUG 45936389Ssklower if (isop->isop_clnpcache != NULL) { 46036389Ssklower struct clnp_cache *clcp = 46136389Ssklower mtod(isop->isop_clnpcache, struct clnp_cache *); 46236389Ssklower IFDEBUG(D_ISO) 46336389Ssklower printf("iso_pcbdetach 3.2: clcp 0x%x freeing clc_hdr x%x\n", 46436389Ssklower clcp, clcp->clc_hdr); 46536389Ssklower ENDDEBUG 46636389Ssklower if (clcp->clc_hdr != NULL) 46736389Ssklower m_free(clcp->clc_hdr); 46836389Ssklower IFDEBUG(D_ISO) 46936389Ssklower printf("iso_pcbdetach 3.3: freeing cache x%x\n", 47036389Ssklower isop->isop_clnpcache); 47136389Ssklower ENDDEBUG 47236389Ssklower m_free(isop->isop_clnpcache); 47336389Ssklower } 47436389Ssklower IFDEBUG(D_ISO) 47536389Ssklower printf("iso_pcbdetach 4 \n"); 47636389Ssklower ENDDEBUG 47736389Ssklower remque(isop); 47836389Ssklower IFDEBUG(D_ISO) 47936389Ssklower printf("iso_pcbdetach 5 \n"); 48036389Ssklower ENDDEBUG 48137469Ssklower if (isop->isop_laddr && (isop->isop_laddr != &isop->isop_sladdr)) 48237469Ssklower m_freem(dtom(isop->isop_laddr)); 48340951Ssklower free((caddr_t)isop, M_PCB); 48436389Ssklower } 48536389Ssklower 48636389Ssklower 48736389Ssklower /* 48836389Ssklower * FUNCTION: iso_pcbnotify 48936389Ssklower * 49036389Ssklower * PURPOSE: notify all connections in this protocol's queue (head) 49136389Ssklower * that have peer address (dst) of the problem (errno) 49236389Ssklower * by calling (notify) on the connections' isopcbs. 49336389Ssklower * 49436389Ssklower * RETURNS: Rien. 49536389Ssklower * 49636389Ssklower * SIDE EFFECTS: 49736389Ssklower * 49836389Ssklower * NOTES: (notify) is called at splimp! 49936389Ssklower */ 50036389Ssklower void 50139934Ssklower iso_pcbnotify(head, siso, errno, notify) 50236389Ssklower struct isopcb *head; 50339934Ssklower register struct sockaddr_iso *siso; 50436389Ssklower int errno, (*notify)(); 50536389Ssklower { 50639934Ssklower register struct isopcb *isop; 50736389Ssklower int s = splimp(); 50836389Ssklower 50936389Ssklower IFDEBUG(D_ISO) 51036389Ssklower printf("iso_pcbnotify(head 0x%x, notify 0x%x) dst:\n", head, notify); 51136389Ssklower ENDDEBUG 51239934Ssklower for (isop = head->isop_next; isop != head; isop = isop->isop_next) { 51339934Ssklower if (isop->isop_socket == 0 || isop->isop_faddr == 0 || 51439934Ssklower !SAME_ISOADDR(siso, isop->isop_faddr)) { 51536389Ssklower IFDEBUG(D_ISO) 51636389Ssklower printf("iso_pcbnotify: CONTINUE isop 0x%x, sock 0x%x\n" , 51736389Ssklower isop, isop->isop_socket); 51839934Ssklower printf("addrmatch cmp'd with (0x%x):\n", isop->isop_faddr); 51937469Ssklower dump_isoaddr(isop->isop_faddr); 52036389Ssklower ENDDEBUG 52136389Ssklower continue; 52236389Ssklower } 52336389Ssklower if (errno) 52436389Ssklower isop->isop_socket->so_error = errno; 52536389Ssklower if (notify) 52639934Ssklower (*notify)(isop); 52736389Ssklower } 52836389Ssklower splx(s); 52936389Ssklower IFDEBUG(D_ISO) 53036389Ssklower printf("END OF iso_pcbnotify\n" ); 53136389Ssklower ENDDEBUG 53236389Ssklower } 53336389Ssklower 53436389Ssklower 53536389Ssklower /* 53636389Ssklower * FUNCTION: iso_pcblookup 53736389Ssklower * 53836389Ssklower * PURPOSE: looks for a given combination of (faddr), (fport), 53936389Ssklower * (lport), (laddr) in the queue named by (head). 54036389Ssklower * Argument (flags) is ignored. 54136389Ssklower * 54236389Ssklower * RETURNS: ptr to the isopcb if it finds a connection matching 54336389Ssklower * these arguments, o.w. returns zero. 54436389Ssklower * 54536389Ssklower * SIDE EFFECTS: 54636389Ssklower * 54736389Ssklower * NOTES: 54836389Ssklower */ 54936389Ssklower struct isopcb * 55037469Ssklower iso_pcblookup(head, fportlen, fport, laddr) 55136389Ssklower struct isopcb *head; 55237469Ssklower register struct sockaddr_iso *laddr; 55337469Ssklower caddr_t fport; 55437469Ssklower int fportlen; 55536389Ssklower { 55636389Ssklower register struct isopcb *isop; 55737469Ssklower register caddr_t lp = TSEL(laddr); 55838841Ssklower unsigned int llen = laddr->siso_tlen; 55936389Ssklower 56036389Ssklower IFDEBUG(D_ISO) 56137469Ssklower printf("iso_pcblookup(head 0x%x laddr 0x%x fport 0x%x)\n", 56237469Ssklower head, laddr, fport); 56336389Ssklower ENDDEBUG 56436389Ssklower for (isop = head->isop_next; isop != head; isop = isop->isop_next) { 56537469Ssklower if (isop->isop_laddr == 0 || isop->isop_laddr == laddr) 56636389Ssklower continue; 56738841Ssklower if (isop->isop_laddr->siso_tlen != llen) 56836389Ssklower continue; 56937469Ssklower if (bcmp(lp, TSEL(isop->isop_laddr), llen)) 57037469Ssklower continue; 57137469Ssklower if (fportlen && isop->isop_faddr && 57237469Ssklower bcmp(fport, TSEL(isop->isop_faddr), (unsigned)fportlen)) 57337469Ssklower continue; 57436389Ssklower /* PHASE2 57536389Ssklower * addrmatch1 should be iso_addrmatch(a, b, mask) 57636389Ssklower * where mask is taken from isop->isop_laddrmask (new field) 57736389Ssklower * isop_lnetmask will also be available in isop 57836389Ssklower if (laddr != &zeroiso_addr && 57936389Ssklower !iso_addrmatch1(laddr, &(isop->isop_laddr.siso_addr))) 58036389Ssklower continue; 58137469Ssklower */ 58237469Ssklower if (laddr->siso_nlen && (!SAME_ISOADDR(laddr, isop->isop_laddr))) 58337469Ssklower continue; 58436389Ssklower return (isop); 58536389Ssklower } 58636389Ssklower return (struct isopcb *)0; 58736389Ssklower } 58836389Ssklower #endif ISO 589