149268Sbostic /*-
263222Sbostic * Copyright (c) 1991, 1993
363222Sbostic * The Regents of the University of California. All rights reserved.
449268Sbostic *
549268Sbostic * %sccs.include.redist.c%
649268Sbostic *
7*67541Ssklower * @(#)iso_pcb.c 8.3 (Berkeley) 07/19/94
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
iso_pcballoc(so,head)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
iso_pcbbind(isop,nam)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)
17767464Ssklower if (SAME_ISOIFADDR(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);
205*67541Ssklower isop->isop_laddr->siso_tlen = 2;
20636389Ssklower IFDEBUG(D_ISO)
20736389Ssklower printf("iso_pcbbind noname\n");
20836389Ssklower ENDDEBUG
20936389Ssklower do {
21036389Ssklower if (head->isop_lport++ < ISO_PORT_RESERVED ||
21136389Ssklower head->isop_lport > ISO_PORT_USERRESERVED)
21236389Ssklower head->isop_lport = ISO_PORT_RESERVED;
21353230Ssklower suf.s = htons(head->isop_lport);
21437469Ssklower cp[0] = suf.data[0];
21537469Ssklower cp[1] = suf.data[1];
21637469Ssklower } while (iso_pcblookup(head, 0, (caddr_t)0, isop->isop_laddr));
21737469Ssklower }
21836389Ssklower IFDEBUG(D_ISO)
21936389Ssklower printf("iso_pcbbind returns 0, suf 0x%x\n", suf);
22036389Ssklower ENDDEBUG
22136389Ssklower return 0;
22236389Ssklower }
22336389Ssklower /*
22436389Ssklower * FUNCTION: iso_pcbconnect
22536389Ssklower *
22636389Ssklower * PURPOSE: Make the isopcb (isop) look like it's connected.
22736389Ssklower * In other words, give it the peer address given in
22836389Ssklower * the mbuf * (nam). Make sure such a combination
22936389Ssklower * of local, peer addresses doesn't already exist
23036389Ssklower * for this protocol. Internet mentality prevails here,
23136389Ssklower * wherein a src,dst pair uniquely identifies a connection.
23236389Ssklower * Both net address and port must be specified in argument
23336389Ssklower * (nam).
23436389Ssklower * If we don't have a local address for this socket yet,
23536389Ssklower * we pick one by calling iso_pcbbind().
23636389Ssklower *
23736389Ssklower * RETURNS: errno E* or 0 if ok.
23836389Ssklower *
23936389Ssklower * SIDE EFFECTS: Looks up a route, which may cause one to be left
24036389Ssklower * in the isopcb.
24136389Ssklower *
24236389Ssklower * NOTES:
24336389Ssklower */
24436389Ssklower int
iso_pcbconnect(isop,nam)24536389Ssklower iso_pcbconnect(isop, nam)
24637469Ssklower register struct isopcb *isop;
24736389Ssklower struct mbuf *nam;
24836389Ssklower {
24936389Ssklower register struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *);
25037469Ssklower int local_zero, error = 0;
25137469Ssklower struct iso_ifaddr *ia;
25236389Ssklower
25336389Ssklower IFDEBUG(D_ISO)
25437469Ssklower printf("iso_pcbconnect(isop 0x%x sock 0x%x nam 0x%x",
25537469Ssklower isop, isop->isop_socket, nam);
25637469Ssklower printf("nam->m_len 0x%x), addr:\n", nam->m_len);
25736389Ssklower dump_isoaddr(siso);
25836389Ssklower ENDDEBUG
25937469Ssklower if (nam->m_len < siso->siso_len)
26037469Ssklower return EINVAL;
26136389Ssklower if (siso->siso_family != AF_ISO)
26236389Ssklower return EAFNOSUPPORT;
26338477Ssklower if (siso->siso_nlen == 0) {
26438477Ssklower if (ia = iso_ifaddr) {
26538477Ssklower int nlen = ia->ia_addr.siso_nlen;
26638477Ssklower ovbcopy(TSEL(siso), nlen + TSEL(siso),
26738841Ssklower siso->siso_plen + siso->siso_tlen + siso->siso_slen);
26838477Ssklower bcopy((caddr_t)&ia->ia_addr.siso_addr,
26938477Ssklower (caddr_t)&siso->siso_addr, nlen + 1);
27038477Ssklower /* includes siso->siso_nlen = nlen; */
27138477Ssklower } else
27238477Ssklower return EADDRNOTAVAIL;
27338477Ssklower }
27437469Ssklower /*
27537469Ssklower * Local zero means either not bound, or bound to a TSEL, but no
27637469Ssklower * particular local interface. So, if we want to send somebody
27737469Ssklower * we need to choose a return address.
27836389Ssklower */
27937469Ssklower local_zero =
28037469Ssklower ((isop->isop_laddr == 0) || (isop->isop_laddr->siso_nlen == 0));
28136389Ssklower if (local_zero) {
28237469Ssklower int flags;
28336389Ssklower
28436389Ssklower IFDEBUG(D_ISO)
28536389Ssklower printf("iso_pcbconnect localzero 1\n");
28636389Ssklower ENDDEBUG
28736389Ssklower /*
28836389Ssklower * If route is known or can be allocated now,
28936389Ssklower * our src addr is taken from the i/f, else punt.
29036389Ssklower */
29137469Ssklower flags = isop->isop_socket->so_options & SO_DONTROUTE;
29237469Ssklower if (error = clnp_route(&siso->siso_addr, &isop->isop_route, flags,
29337469Ssklower (struct sockaddr **)0, &ia))
29437469Ssklower return error;
29536389Ssklower IFDEBUG(D_ISO)
29637469Ssklower printf("iso_pcbconnect localzero 2, ro->ro_rt 0x%x",
29737469Ssklower isop->isop_route.ro_rt);
29837469Ssklower printf(" ia 0x%x\n", ia);
29936389Ssklower ENDDEBUG
30036389Ssklower }
30136389Ssklower IFDEBUG(D_ISO)
30236389Ssklower printf("in iso_pcbconnect before lookup isop 0x%x isop->sock 0x%x\n",
30336389Ssklower isop, isop->isop_socket);
30436389Ssklower ENDDEBUG
30536389Ssklower if (local_zero) {
30637469Ssklower int nlen, tlen, totlen; caddr_t oldtsel, newtsel;
30737469Ssklower siso = isop->isop_laddr;
30838841Ssklower if (siso == 0 || siso->siso_tlen == 0)
30936389Ssklower (void)iso_pcbbind(isop, (struct mbuf *)0);
31037469Ssklower /*
31137469Ssklower * Here we have problem of squezeing in a definite network address
31237469Ssklower * into an existing sockaddr_iso, which in fact may not have room
31337469Ssklower * for it. This gets messy.
31437469Ssklower */
31537469Ssklower siso = isop->isop_laddr;
31637469Ssklower oldtsel = TSEL(siso);
31738841Ssklower tlen = siso->siso_tlen;
31837469Ssklower nlen = ia->ia_addr.siso_nlen;
31937469Ssklower totlen = tlen + nlen + _offsetof(struct sockaddr_iso, siso_data[0]);
32037469Ssklower if ((siso == &isop->isop_sladdr) &&
32137469Ssklower (totlen > sizeof(isop->isop_sladdr))) {
32237469Ssklower struct mbuf *m = m_get(MT_SONAME, M_DONTWAIT);
32337469Ssklower if (m == 0)
32437469Ssklower return ENOBUFS;
32537469Ssklower m->m_len = totlen;
32637469Ssklower isop->isop_laddr = siso = mtod(m, struct sockaddr_iso *);
32737469Ssklower }
32837469Ssklower siso->siso_nlen = ia->ia_addr.siso_nlen;
32937469Ssklower newtsel = TSEL(siso);
33037469Ssklower ovbcopy(oldtsel, newtsel, tlen);
33137469Ssklower bcopy(ia->ia_addr.siso_data, siso->siso_data, nlen);
33238841Ssklower siso->siso_tlen = tlen;
33337469Ssklower siso->siso_family = AF_ISO;
33437469Ssklower siso->siso_len = totlen;
33537469Ssklower siso = mtod(nam, struct sockaddr_iso *);
33636389Ssklower }
33736389Ssklower IFDEBUG(D_ISO)
33836389Ssklower printf("in iso_pcbconnect before bcopy isop 0x%x isop->sock 0x%x\n",
33936389Ssklower isop, isop->isop_socket);
34036389Ssklower ENDDEBUG
34137469Ssklower /*
34237469Ssklower * If we had to allocate space to a previous big foreign address,
34337469Ssklower * and for some reason we didn't free it, we reuse it knowing
34437469Ssklower * that is going to be big enough, as sockaddrs are delivered in
34537469Ssklower * 128 byte mbufs.
34637469Ssklower * If the foreign address is small enough, we use default space;
34737469Ssklower * otherwise, we grab an mbuf to copy into.
34837469Ssklower */
34937469Ssklower if (isop->isop_faddr == 0 || isop->isop_faddr == &isop->isop_sfaddr) {
35037469Ssklower if (siso->siso_len <= sizeof(isop->isop_sfaddr))
35137469Ssklower isop->isop_faddr = &isop->isop_sfaddr;
35237469Ssklower else {
35337469Ssklower struct mbuf *m = m_get(MT_SONAME, M_DONTWAIT);
35437469Ssklower if (m == 0)
35537469Ssklower return ENOBUFS;
35637469Ssklower isop->isop_faddr = mtod(m, struct sockaddr_iso *);
35737469Ssklower }
35837469Ssklower }
35937469Ssklower bcopy((caddr_t)siso, (caddr_t)isop->isop_faddr, siso->siso_len);
36036389Ssklower IFDEBUG(D_ISO)
36136389Ssklower printf("in iso_pcbconnect after bcopy isop 0x%x isop->sock 0x%x\n",
36236389Ssklower isop, isop->isop_socket);
36336389Ssklower printf("iso_pcbconnect connected to addr:\n");
36437469Ssklower dump_isoaddr(isop->isop_faddr);
36536389Ssklower printf("iso_pcbconnect end: src addr:\n");
36637469Ssklower dump_isoaddr(isop->isop_laddr);
36736389Ssklower ENDDEBUG
36836389Ssklower return 0;
36936389Ssklower }
37036389Ssklower
37136389Ssklower /*
37236389Ssklower * FUNCTION: iso_pcbdisconnect()
37336389Ssklower *
37436389Ssklower * PURPOSE: washes away the peer address info so the socket
37536389Ssklower * appears to be disconnected.
37636389Ssklower * If there's no file descriptor associated with the socket
37736389Ssklower * it detaches the pcb.
37836389Ssklower *
37936389Ssklower * RETURNS: Nada.
38036389Ssklower *
38136389Ssklower * SIDE EFFECTS: May detach the pcb.
38236389Ssklower *
38336389Ssklower * NOTES:
38436389Ssklower */
38536389Ssklower void
iso_pcbdisconnect(isop)38636389Ssklower iso_pcbdisconnect(isop)
38736389Ssklower struct isopcb *isop;
38836389Ssklower {
38936389Ssklower void iso_pcbdetach();
39039934Ssklower register struct sockaddr_iso *siso;
39136389Ssklower
39236389Ssklower IFDEBUG(D_ISO)
39336389Ssklower printf("iso_pcbdisconnect(isop 0x%x)\n", isop);
39436389Ssklower ENDDEBUG
39537469Ssklower /*
39637469Ssklower * Preserver binding infnormation if already bound.
39737469Ssklower */
39839934Ssklower if ((siso = isop->isop_laddr) && siso->siso_nlen && siso->siso_tlen) {
39939934Ssklower caddr_t otsel = TSEL(siso);
40039934Ssklower siso->siso_nlen = 0;
40139934Ssklower ovbcopy(otsel, TSEL(siso), siso->siso_tlen);
40239934Ssklower }
40337469Ssklower if (isop->isop_faddr && isop->isop_faddr != &isop->isop_sfaddr)
40437469Ssklower m_freem(dtom(isop->isop_faddr));
40537469Ssklower isop->isop_faddr = 0;
40636389Ssklower if (isop->isop_socket->so_state & SS_NOFDREF)
40736389Ssklower iso_pcbdetach(isop);
40836389Ssklower }
40936389Ssklower
41036389Ssklower /*
41136389Ssklower * FUNCTION: iso_pcbdetach
41236389Ssklower *
41336389Ssklower * PURPOSE: detach the pcb at *(isop) from it's socket and free
41436389Ssklower * the mbufs associated with the pcb..
41536389Ssklower * Dequeues (isop) from its head.
41636389Ssklower *
41736389Ssklower * RETURNS: Nada.
41836389Ssklower *
41936389Ssklower * SIDE EFFECTS:
42036389Ssklower *
42136389Ssklower * NOTES:
42236389Ssklower */
42336389Ssklower void
iso_pcbdetach(isop)42436389Ssklower iso_pcbdetach(isop)
42536389Ssklower struct isopcb *isop;
42636389Ssklower {
42736389Ssklower struct socket *so = isop->isop_socket;
42836389Ssklower
42936389Ssklower IFDEBUG(D_ISO)
43036389Ssklower printf("iso_pcbdetach(isop 0x%x socket 0x%x so 0x%x)\n",
43136389Ssklower isop, isop->isop_socket, so);
43236389Ssklower ENDDEBUG
43348737Ssklower #ifdef TPCONS
43450648Ssklower if (isop->isop_chan) {
43548737Ssklower register struct pklcd *lcp = (struct pklcd *)isop->isop_chan;
43648737Ssklower if (--isop->isop_refcnt > 0)
43748737Ssklower return;
43850648Ssklower if (lcp && lcp->lcd_state == DATA_TRANSFER) {
43950648Ssklower lcp->lcd_upper = 0;
44050648Ssklower lcp->lcd_upnext = 0;
44148737Ssklower pk_disconnect(lcp);
44250648Ssklower }
44348737Ssklower isop->isop_chan = 0;
44448737Ssklower }
44548737Ssklower #endif
44648737Ssklower if (so) { /* in the x.25 domain, we sometimes have no socket */
44736389Ssklower so->so_pcb = 0;
44836389Ssklower sofree(so);
44936389Ssklower }
45036389Ssklower IFDEBUG(D_ISO)
45136389Ssklower printf("iso_pcbdetach 2 \n");
45236389Ssklower ENDDEBUG
45336389Ssklower if (isop->isop_options)
45436389Ssklower (void)m_free(isop->isop_options);
45536389Ssklower IFDEBUG(D_ISO)
45636389Ssklower printf("iso_pcbdetach 3 \n");
45736389Ssklower ENDDEBUG
45836389Ssklower if (isop->isop_route.ro_rt)
45936389Ssklower rtfree(isop->isop_route.ro_rt);
46036389Ssklower IFDEBUG(D_ISO)
46136389Ssklower printf("iso_pcbdetach 3.1\n");
46236389Ssklower ENDDEBUG
46336389Ssklower if (isop->isop_clnpcache != NULL) {
46436389Ssklower struct clnp_cache *clcp =
46536389Ssklower mtod(isop->isop_clnpcache, struct clnp_cache *);
46636389Ssklower IFDEBUG(D_ISO)
46736389Ssklower printf("iso_pcbdetach 3.2: clcp 0x%x freeing clc_hdr x%x\n",
46836389Ssklower clcp, clcp->clc_hdr);
46936389Ssklower ENDDEBUG
47036389Ssklower if (clcp->clc_hdr != NULL)
47136389Ssklower m_free(clcp->clc_hdr);
47236389Ssklower IFDEBUG(D_ISO)
47336389Ssklower printf("iso_pcbdetach 3.3: freeing cache x%x\n",
47436389Ssklower isop->isop_clnpcache);
47536389Ssklower ENDDEBUG
47636389Ssklower m_free(isop->isop_clnpcache);
47736389Ssklower }
47836389Ssklower IFDEBUG(D_ISO)
47936389Ssklower printf("iso_pcbdetach 4 \n");
48036389Ssklower ENDDEBUG
48136389Ssklower remque(isop);
48236389Ssklower IFDEBUG(D_ISO)
48336389Ssklower printf("iso_pcbdetach 5 \n");
48436389Ssklower ENDDEBUG
48537469Ssklower if (isop->isop_laddr && (isop->isop_laddr != &isop->isop_sladdr))
48637469Ssklower m_freem(dtom(isop->isop_laddr));
48740951Ssklower free((caddr_t)isop, M_PCB);
48836389Ssklower }
48936389Ssklower
49036389Ssklower
49136389Ssklower /*
49236389Ssklower * FUNCTION: iso_pcbnotify
49336389Ssklower *
49436389Ssklower * PURPOSE: notify all connections in this protocol's queue (head)
49536389Ssklower * that have peer address (dst) of the problem (errno)
49636389Ssklower * by calling (notify) on the connections' isopcbs.
49736389Ssklower *
49836389Ssklower * RETURNS: Rien.
49936389Ssklower *
50036389Ssklower * SIDE EFFECTS:
50136389Ssklower *
50236389Ssklower * NOTES: (notify) is called at splimp!
50336389Ssklower */
50436389Ssklower void
iso_pcbnotify(head,siso,errno,notify)50539934Ssklower iso_pcbnotify(head, siso, errno, notify)
50636389Ssklower struct isopcb *head;
50739934Ssklower register struct sockaddr_iso *siso;
50836389Ssklower int errno, (*notify)();
50936389Ssklower {
51039934Ssklower register struct isopcb *isop;
51136389Ssklower int s = splimp();
51236389Ssklower
51336389Ssklower IFDEBUG(D_ISO)
51436389Ssklower printf("iso_pcbnotify(head 0x%x, notify 0x%x) dst:\n", head, notify);
51536389Ssklower ENDDEBUG
51639934Ssklower for (isop = head->isop_next; isop != head; isop = isop->isop_next) {
51739934Ssklower if (isop->isop_socket == 0 || isop->isop_faddr == 0 ||
51839934Ssklower !SAME_ISOADDR(siso, isop->isop_faddr)) {
51936389Ssklower IFDEBUG(D_ISO)
52036389Ssklower printf("iso_pcbnotify: CONTINUE isop 0x%x, sock 0x%x\n" ,
52136389Ssklower isop, isop->isop_socket);
52239934Ssklower printf("addrmatch cmp'd with (0x%x):\n", isop->isop_faddr);
52337469Ssklower dump_isoaddr(isop->isop_faddr);
52436389Ssklower ENDDEBUG
52536389Ssklower continue;
52636389Ssklower }
52736389Ssklower if (errno)
52836389Ssklower isop->isop_socket->so_error = errno;
52936389Ssklower if (notify)
53039934Ssklower (*notify)(isop);
53136389Ssklower }
53236389Ssklower splx(s);
53336389Ssklower IFDEBUG(D_ISO)
53436389Ssklower printf("END OF iso_pcbnotify\n" );
53536389Ssklower ENDDEBUG
53636389Ssklower }
53736389Ssklower
53836389Ssklower
53936389Ssklower /*
54036389Ssklower * FUNCTION: iso_pcblookup
54136389Ssklower *
54236389Ssklower * PURPOSE: looks for a given combination of (faddr), (fport),
54336389Ssklower * (lport), (laddr) in the queue named by (head).
54436389Ssklower * Argument (flags) is ignored.
54536389Ssklower *
54636389Ssklower * RETURNS: ptr to the isopcb if it finds a connection matching
54736389Ssklower * these arguments, o.w. returns zero.
54836389Ssklower *
54936389Ssklower * SIDE EFFECTS:
55036389Ssklower *
55136389Ssklower * NOTES:
55236389Ssklower */
55336389Ssklower struct isopcb *
iso_pcblookup(head,fportlen,fport,laddr)55437469Ssklower iso_pcblookup(head, fportlen, fport, laddr)
55536389Ssklower struct isopcb *head;
55637469Ssklower register struct sockaddr_iso *laddr;
55737469Ssklower caddr_t fport;
55837469Ssklower int fportlen;
55936389Ssklower {
56036389Ssklower register struct isopcb *isop;
56137469Ssklower register caddr_t lp = TSEL(laddr);
56238841Ssklower unsigned int llen = laddr->siso_tlen;
56336389Ssklower
56436389Ssklower IFDEBUG(D_ISO)
56537469Ssklower printf("iso_pcblookup(head 0x%x laddr 0x%x fport 0x%x)\n",
56637469Ssklower head, laddr, fport);
56736389Ssklower ENDDEBUG
56836389Ssklower for (isop = head->isop_next; isop != head; isop = isop->isop_next) {
56937469Ssklower if (isop->isop_laddr == 0 || isop->isop_laddr == laddr)
57036389Ssklower continue;
57138841Ssklower if (isop->isop_laddr->siso_tlen != llen)
57236389Ssklower continue;
57337469Ssklower if (bcmp(lp, TSEL(isop->isop_laddr), llen))
57437469Ssklower continue;
57537469Ssklower if (fportlen && isop->isop_faddr &&
57637469Ssklower bcmp(fport, TSEL(isop->isop_faddr), (unsigned)fportlen))
57737469Ssklower continue;
57836389Ssklower /* PHASE2
57936389Ssklower * addrmatch1 should be iso_addrmatch(a, b, mask)
58036389Ssklower * where mask is taken from isop->isop_laddrmask (new field)
58136389Ssklower * isop_lnetmask will also be available in isop
58236389Ssklower if (laddr != &zeroiso_addr &&
58336389Ssklower !iso_addrmatch1(laddr, &(isop->isop_laddr.siso_addr)))
58436389Ssklower continue;
58537469Ssklower */
58637469Ssklower if (laddr->siso_nlen && (!SAME_ISOADDR(laddr, isop->isop_laddr)))
58737469Ssklower continue;
58836389Ssklower return (isop);
58936389Ssklower }
59036389Ssklower return (struct isopcb *)0;
59136389Ssklower }
59260359Sbostic #endif /* ISO */
593