Commit | Line | Data |
---|---|---|
7bcd1bb8 KB |
1 | /*- |
2 | * Copyright (c) 1991 The Regents of the University of California. | |
3 | * All rights reserved. | |
4 | * | |
5 | * %sccs.include.redist.c% | |
6 | * | |
01acbfa1 | 7 | * @(#)iso_pcb.c 7.11 (Berkeley) %G% |
7bcd1bb8 KB |
8 | */ |
9 | ||
627d3292 KS |
10 | /*********************************************************** |
11 | Copyright IBM Corporation 1987 | |
12 | ||
13 | All Rights Reserved | |
14 | ||
15 | Permission to use, copy, modify, and distribute this software and its | |
16 | documentation for any purpose and without fee is hereby granted, | |
17 | provided that the above copyright notice appear in all copies and that | |
18 | both that copyright notice and this permission notice appear in | |
19 | supporting documentation, and that the name of IBM not be | |
20 | used in advertising or publicity pertaining to distribution of the | |
21 | software without specific, written prior permission. | |
22 | ||
23 | IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING | |
24 | ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL | |
25 | IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR | |
26 | ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, | |
27 | WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | |
28 | ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS | |
29 | SOFTWARE. | |
30 | ||
31 | ******************************************************************/ | |
32 | ||
33 | /* | |
34 | * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison | |
35 | */ | |
36 | /* | |
37 | * $Header: iso_pcb.c,v 4.5 88/06/29 14:59:56 hagens Exp $ | |
38 | * $Source: /usr/argo/sys/netiso/RCS/iso_pcb.c,v $ | |
39 | * | |
40 | * Iso address family net-layer(s) pcb stuff. NEH 1/29/87 | |
41 | */ | |
510a846b | 42 | |
627d3292 KS |
43 | #ifdef ISO |
44 | ||
45 | #include "param.h" | |
46 | #include "systm.h" | |
627d3292 | 47 | #include "mbuf.h" |
a50e2bc0 KS |
48 | #include "socket.h" |
49 | #include "socketvar.h" | |
6929d5df KS |
50 | #include "errno.h" |
51 | ||
a50e2bc0 KS |
52 | #include "argo_debug.h" |
53 | #include "iso.h" | |
54 | #include "clnp.h" | |
627d3292 KS |
55 | #include "../netinet/in_systm.h" |
56 | #include "../net/if.h" | |
57 | #include "../net/route.h" | |
a50e2bc0 KS |
58 | #include "iso_pcb.h" |
59 | #include "iso_var.h" | |
627d3292 KS |
60 | #include "protosw.h" |
61 | ||
77d3b1ec KS |
62 | #ifdef TPCONS |
63 | #include "../netccitt/x25.h" | |
64 | #include "../netccitt/pk.h" | |
65 | #include "../netccitt/pk_var.h" | |
66 | #endif | |
67 | ||
627d3292 KS |
68 | #define PCBNULL (struct isopcb *)0 |
69 | struct iso_addr zeroiso_addr = { | |
70 | 0 | |
71 | }; | |
72 | ||
73 | ||
74 | /* | |
75 | * FUNCTION: iso_pcballoc | |
76 | * | |
77 | * PURPOSE: creates an isopcb structure in an mbuf, | |
78 | * with socket (so), and | |
79 | * puts it in the queue with head (head) | |
80 | * | |
81 | * RETURNS: 0 if OK, ENOBUFS if can't alloc the necessary mbuf | |
82 | */ | |
83 | int | |
84 | iso_pcballoc(so, head) | |
85 | struct socket *so; | |
86 | struct isopcb *head; | |
87 | { | |
627d3292 KS |
88 | register struct isopcb *isop; |
89 | ||
90 | IFDEBUG(D_ISO) | |
91 | printf("iso_pcballoc(so 0x%x)\n", so); | |
92 | ENDDEBUG | |
a50e2bc0 KS |
93 | MALLOC(isop, struct isopcb *, sizeof(*isop), M_PCB, M_NOWAIT); |
94 | if (isop == NULL) | |
627d3292 | 95 | return ENOBUFS; |
a50e2bc0 | 96 | bzero((caddr_t)isop, sizeof(*isop)); |
627d3292 KS |
97 | isop->isop_head = head; |
98 | isop->isop_socket = so; | |
99 | insque(isop, head); | |
77d3b1ec KS |
100 | if (so) |
101 | so->so_pcb = (caddr_t)isop; | |
627d3292 KS |
102 | return 0; |
103 | } | |
104 | ||
105 | /* | |
106 | * FUNCTION: iso_pcbbind | |
107 | * | |
108 | * PURPOSE: binds the address given in *(nam) to the socket | |
109 | * specified by the isopcb in *(isop) | |
110 | * If the given address is zero, it makes sure the | |
111 | * address isn't already in use and if it's got a network | |
112 | * portion, we look for an interface with that network | |
113 | * address. If the address given is zero, we allocate | |
114 | * a port and stuff it in the (nam) structure. | |
115 | * | |
116 | * RETURNS: errno E* or 0 if ok. | |
117 | * | |
118 | * SIDE EFFECTS: increments head->isop_lport if it allocates a port # | |
119 | * | |
120 | * NOTES: | |
121 | */ | |
a50e2bc0 | 122 | #define satosiso(sa) ((struct sockaddr_iso *)(sa)) |
627d3292 KS |
123 | int |
124 | iso_pcbbind(isop, nam) | |
125 | register struct isopcb *isop; | |
126 | struct mbuf *nam; | |
127 | { | |
128 | register struct isopcb *head = isop->isop_head; | |
129 | register struct sockaddr_iso *siso; | |
a50e2bc0 KS |
130 | struct iso_ifaddr *ia; |
131 | union { | |
132 | char data[2]; | |
133 | u_short s; | |
134 | } suf; | |
627d3292 KS |
135 | |
136 | IFDEBUG(D_ISO) | |
137 | printf("iso_pcbbind(isop 0x%x, nam 0x%x)\n", isop, nam); | |
138 | ENDDEBUG | |
a50e2bc0 | 139 | suf.s = 0; |
627d3292 KS |
140 | if (iso_ifaddr == 0) /* any interfaces attached? */ |
141 | return EADDRNOTAVAIL; | |
a50e2bc0 | 142 | if (isop->isop_laddr) /* already bound */ |
627d3292 | 143 | return EADDRINUSE; |
a50e2bc0 KS |
144 | if(nam == (struct mbuf *)0) { |
145 | isop->isop_laddr = &isop->isop_sladdr; | |
a50e2bc0 | 146 | isop->isop_sladdr.siso_len = sizeof(struct sockaddr_iso); |
44f52ea5 KS |
147 | isop->isop_sladdr.siso_family = AF_ISO; |
148 | isop->isop_sladdr.siso_tlen = 2; | |
149 | isop->isop_sladdr.siso_nlen = 0; | |
150 | isop->isop_sladdr.siso_slen = 0; | |
151 | isop->isop_sladdr.siso_plen = 0; | |
627d3292 | 152 | goto noname; |
a50e2bc0 | 153 | } |
627d3292 KS |
154 | siso = mtod(nam, struct sockaddr_iso *); |
155 | IFDEBUG(D_ISO) | |
156 | printf("iso_pcbbind(name len 0x%x)\n", nam->m_len); | |
157 | printf("The address is %s\n", clnp_iso_addrp(&siso->siso_addr)); | |
158 | ENDDEBUG | |
159 | /* | |
160 | * We would like sort of length check but since some OSI addrs | |
161 | * do not have fixed length, we can't really do much. | |
162 | * The ONLY thing we can say is that an osi addr has to have | |
163 | * at LEAST an afi and one more byte and had better fit into | |
164 | * a struct iso_addr. | |
165 | * However, in fact the size of the whole thing is a struct | |
166 | * sockaddr_iso, so probably this is what we should check for. | |
167 | */ | |
a50e2bc0 | 168 | if( (nam->m_len < 2) || (nam->m_len < siso->siso_len)) { |
627d3292 KS |
169 | return ENAMETOOLONG; |
170 | } | |
44f52ea5 | 171 | if (siso->siso_tlen) { |
a50e2bc0 KS |
172 | register char *cp = TSEL(siso); |
173 | suf.data[0] = cp[0]; | |
174 | suf.data[1] = cp[1]; | |
175 | } | |
176 | if (siso->siso_nlen) { | |
627d3292 KS |
177 | /* non-zero net addr- better match one of our interfaces */ |
178 | IFDEBUG(D_ISO) | |
179 | printf("iso_pcbbind: bind to NOT zeroisoaddr\n"); | |
180 | ENDDEBUG | |
a50e2bc0 KS |
181 | for (ia = iso_ifaddr; ia; ia = ia->ia_next) |
182 | if (SAME_ISOADDR(siso, &ia->ia_addr)) | |
183 | break; | |
184 | if (ia == 0) | |
627d3292 | 185 | return EADDRNOTAVAIL; |
627d3292 | 186 | } |
a50e2bc0 KS |
187 | if (siso->siso_len <= sizeof (isop->isop_sladdr)) { |
188 | isop->isop_laddr = &isop->isop_sladdr; | |
189 | } else { | |
190 | if ((nam = m_copy(nam, 0, (int)M_COPYALL)) == 0) | |
191 | return ENOBUFS; | |
192 | isop->isop_laddr = mtod(nam, struct sockaddr_iso *); | |
193 | } | |
194 | bcopy((caddr_t)siso, (caddr_t)isop->isop_laddr, siso->siso_len); | |
c61c8804 | 195 | if (suf.s || siso->siso_tlen != 2) { |
44f52ea5 | 196 | if((suf.s < ISO_PORT_RESERVED) && (siso->siso_tlen <= 2) && |
6929d5df | 197 | (isop->isop_socket->so_state && SS_PRIV) == 0) |
627d3292 KS |
198 | return EACCES; |
199 | if ((isop->isop_socket->so_options & SO_REUSEADDR) == 0 && | |
a50e2bc0 | 200 | iso_pcblookup(head, 0, (caddr_t)0, isop->isop_laddr)) |
627d3292 | 201 | return EADDRINUSE; |
a50e2bc0 KS |
202 | } else { |
203 | register char *cp; | |
627d3292 | 204 | noname: |
a50e2bc0 | 205 | cp = TSEL(isop->isop_laddr); |
627d3292 KS |
206 | IFDEBUG(D_ISO) |
207 | printf("iso_pcbbind noname\n"); | |
208 | ENDDEBUG | |
627d3292 KS |
209 | do { |
210 | if (head->isop_lport++ < ISO_PORT_RESERVED || | |
211 | head->isop_lport > ISO_PORT_USERRESERVED) | |
212 | head->isop_lport = ISO_PORT_RESERVED; | |
a50e2bc0 KS |
213 | suf.s = head->isop_lport; |
214 | cp[0] = suf.data[0]; | |
215 | cp[1] = suf.data[1]; | |
216 | } while (iso_pcblookup(head, 0, (caddr_t)0, isop->isop_laddr)); | |
217 | } | |
627d3292 KS |
218 | IFDEBUG(D_ISO) |
219 | printf("iso_pcbbind returns 0, suf 0x%x\n", suf); | |
220 | ENDDEBUG | |
221 | return 0; | |
222 | } | |
627d3292 KS |
223 | /* |
224 | * FUNCTION: iso_pcbconnect | |
225 | * | |
226 | * PURPOSE: Make the isopcb (isop) look like it's connected. | |
227 | * In other words, give it the peer address given in | |
228 | * the mbuf * (nam). Make sure such a combination | |
229 | * of local, peer addresses doesn't already exist | |
230 | * for this protocol. Internet mentality prevails here, | |
231 | * wherein a src,dst pair uniquely identifies a connection. | |
232 | * Both net address and port must be specified in argument | |
233 | * (nam). | |
234 | * If we don't have a local address for this socket yet, | |
235 | * we pick one by calling iso_pcbbind(). | |
236 | * | |
237 | * RETURNS: errno E* or 0 if ok. | |
238 | * | |
239 | * SIDE EFFECTS: Looks up a route, which may cause one to be left | |
240 | * in the isopcb. | |
241 | * | |
242 | * NOTES: | |
243 | */ | |
627d3292 KS |
244 | int |
245 | iso_pcbconnect(isop, nam) | |
a50e2bc0 | 246 | register struct isopcb *isop; |
627d3292 KS |
247 | struct mbuf *nam; |
248 | { | |
627d3292 | 249 | register struct sockaddr_iso *siso = mtod(nam, struct sockaddr_iso *); |
a50e2bc0 KS |
250 | int local_zero, error = 0; |
251 | struct iso_ifaddr *ia; | |
627d3292 KS |
252 | |
253 | IFDEBUG(D_ISO) | |
a50e2bc0 KS |
254 | printf("iso_pcbconnect(isop 0x%x sock 0x%x nam 0x%x", |
255 | isop, isop->isop_socket, nam); | |
256 | printf("nam->m_len 0x%x), addr:\n", nam->m_len); | |
627d3292 KS |
257 | dump_isoaddr(siso); |
258 | ENDDEBUG | |
a50e2bc0 KS |
259 | if (nam->m_len < siso->siso_len) |
260 | return EINVAL; | |
627d3292 KS |
261 | if (siso->siso_family != AF_ISO) |
262 | return EAFNOSUPPORT; | |
510a846b KS |
263 | if (siso->siso_nlen == 0) { |
264 | if (ia = iso_ifaddr) { | |
265 | int nlen = ia->ia_addr.siso_nlen; | |
266 | ovbcopy(TSEL(siso), nlen + TSEL(siso), | |
44f52ea5 | 267 | siso->siso_plen + siso->siso_tlen + siso->siso_slen); |
510a846b KS |
268 | bcopy((caddr_t)&ia->ia_addr.siso_addr, |
269 | (caddr_t)&siso->siso_addr, nlen + 1); | |
270 | /* includes siso->siso_nlen = nlen; */ | |
271 | } else | |
272 | return EADDRNOTAVAIL; | |
273 | } | |
a50e2bc0 KS |
274 | /* |
275 | * Local zero means either not bound, or bound to a TSEL, but no | |
276 | * particular local interface. So, if we want to send somebody | |
277 | * we need to choose a return address. | |
627d3292 | 278 | */ |
a50e2bc0 KS |
279 | local_zero = |
280 | ((isop->isop_laddr == 0) || (isop->isop_laddr->siso_nlen == 0)); | |
627d3292 | 281 | if (local_zero) { |
a50e2bc0 | 282 | int flags; |
627d3292 KS |
283 | |
284 | IFDEBUG(D_ISO) | |
285 | printf("iso_pcbconnect localzero 1\n"); | |
286 | ENDDEBUG | |
627d3292 KS |
287 | /* |
288 | * If route is known or can be allocated now, | |
289 | * our src addr is taken from the i/f, else punt. | |
290 | */ | |
a50e2bc0 KS |
291 | flags = isop->isop_socket->so_options & SO_DONTROUTE; |
292 | if (error = clnp_route(&siso->siso_addr, &isop->isop_route, flags, | |
293 | (struct sockaddr **)0, &ia)) | |
294 | return error; | |
627d3292 | 295 | IFDEBUG(D_ISO) |
a50e2bc0 KS |
296 | printf("iso_pcbconnect localzero 2, ro->ro_rt 0x%x", |
297 | isop->isop_route.ro_rt); | |
298 | printf(" ia 0x%x\n", ia); | |
627d3292 | 299 | ENDDEBUG |
627d3292 KS |
300 | } |
301 | IFDEBUG(D_ISO) | |
302 | printf("in iso_pcbconnect before lookup isop 0x%x isop->sock 0x%x\n", | |
303 | isop, isop->isop_socket); | |
304 | ENDDEBUG | |
305 | if (local_zero) { | |
a50e2bc0 KS |
306 | int nlen, tlen, totlen; caddr_t oldtsel, newtsel; |
307 | siso = isop->isop_laddr; | |
44f52ea5 | 308 | if (siso == 0 || siso->siso_tlen == 0) |
627d3292 | 309 | (void)iso_pcbbind(isop, (struct mbuf *)0); |
a50e2bc0 KS |
310 | /* |
311 | * Here we have problem of squezeing in a definite network address | |
312 | * into an existing sockaddr_iso, which in fact may not have room | |
313 | * for it. This gets messy. | |
314 | */ | |
315 | siso = isop->isop_laddr; | |
316 | oldtsel = TSEL(siso); | |
44f52ea5 | 317 | tlen = siso->siso_tlen; |
a50e2bc0 KS |
318 | nlen = ia->ia_addr.siso_nlen; |
319 | totlen = tlen + nlen + _offsetof(struct sockaddr_iso, siso_data[0]); | |
320 | if ((siso == &isop->isop_sladdr) && | |
321 | (totlen > sizeof(isop->isop_sladdr))) { | |
322 | struct mbuf *m = m_get(MT_SONAME, M_DONTWAIT); | |
323 | if (m == 0) | |
324 | return ENOBUFS; | |
325 | m->m_len = totlen; | |
326 | isop->isop_laddr = siso = mtod(m, struct sockaddr_iso *); | |
327 | } | |
328 | siso->siso_nlen = ia->ia_addr.siso_nlen; | |
329 | newtsel = TSEL(siso); | |
330 | ovbcopy(oldtsel, newtsel, tlen); | |
331 | bcopy(ia->ia_addr.siso_data, siso->siso_data, nlen); | |
44f52ea5 | 332 | siso->siso_tlen = tlen; |
a50e2bc0 KS |
333 | siso->siso_family = AF_ISO; |
334 | siso->siso_len = totlen; | |
335 | siso = mtod(nam, struct sockaddr_iso *); | |
627d3292 | 336 | } |
627d3292 KS |
337 | IFDEBUG(D_ISO) |
338 | printf("in iso_pcbconnect before bcopy isop 0x%x isop->sock 0x%x\n", | |
339 | isop, isop->isop_socket); | |
340 | ENDDEBUG | |
a50e2bc0 KS |
341 | /* |
342 | * If we had to allocate space to a previous big foreign address, | |
343 | * and for some reason we didn't free it, we reuse it knowing | |
344 | * that is going to be big enough, as sockaddrs are delivered in | |
345 | * 128 byte mbufs. | |
346 | * If the foreign address is small enough, we use default space; | |
347 | * otherwise, we grab an mbuf to copy into. | |
348 | */ | |
349 | if (isop->isop_faddr == 0 || isop->isop_faddr == &isop->isop_sfaddr) { | |
350 | if (siso->siso_len <= sizeof(isop->isop_sfaddr)) | |
351 | isop->isop_faddr = &isop->isop_sfaddr; | |
352 | else { | |
353 | struct mbuf *m = m_get(MT_SONAME, M_DONTWAIT); | |
354 | if (m == 0) | |
355 | return ENOBUFS; | |
356 | isop->isop_faddr = mtod(m, struct sockaddr_iso *); | |
357 | } | |
358 | } | |
359 | bcopy((caddr_t)siso, (caddr_t)isop->isop_faddr, siso->siso_len); | |
627d3292 KS |
360 | IFDEBUG(D_ISO) |
361 | printf("in iso_pcbconnect after bcopy isop 0x%x isop->sock 0x%x\n", | |
362 | isop, isop->isop_socket); | |
627d3292 | 363 | printf("iso_pcbconnect connected to addr:\n"); |
a50e2bc0 | 364 | dump_isoaddr(isop->isop_faddr); |
627d3292 | 365 | printf("iso_pcbconnect end: src addr:\n"); |
a50e2bc0 | 366 | dump_isoaddr(isop->isop_laddr); |
627d3292 KS |
367 | ENDDEBUG |
368 | return 0; | |
369 | } | |
370 | ||
371 | /* | |
372 | * FUNCTION: iso_pcbdisconnect() | |
373 | * | |
374 | * PURPOSE: washes away the peer address info so the socket | |
375 | * appears to be disconnected. | |
376 | * If there's no file descriptor associated with the socket | |
377 | * it detaches the pcb. | |
378 | * | |
379 | * RETURNS: Nada. | |
380 | * | |
381 | * SIDE EFFECTS: May detach the pcb. | |
382 | * | |
383 | * NOTES: | |
384 | */ | |
385 | void | |
386 | iso_pcbdisconnect(isop) | |
387 | struct isopcb *isop; | |
388 | { | |
389 | void iso_pcbdetach(); | |
c61c8804 | 390 | register struct sockaddr_iso *siso; |
627d3292 KS |
391 | |
392 | IFDEBUG(D_ISO) | |
393 | printf("iso_pcbdisconnect(isop 0x%x)\n", isop); | |
394 | ENDDEBUG | |
a50e2bc0 KS |
395 | /* |
396 | * Preserver binding infnormation if already bound. | |
397 | */ | |
c61c8804 KS |
398 | if ((siso = isop->isop_laddr) && siso->siso_nlen && siso->siso_tlen) { |
399 | caddr_t otsel = TSEL(siso); | |
400 | siso->siso_nlen = 0; | |
401 | ovbcopy(otsel, TSEL(siso), siso->siso_tlen); | |
402 | } | |
a50e2bc0 KS |
403 | if (isop->isop_faddr && isop->isop_faddr != &isop->isop_sfaddr) |
404 | m_freem(dtom(isop->isop_faddr)); | |
405 | isop->isop_faddr = 0; | |
627d3292 KS |
406 | if (isop->isop_socket->so_state & SS_NOFDREF) |
407 | iso_pcbdetach(isop); | |
408 | } | |
409 | ||
410 | /* | |
411 | * FUNCTION: iso_pcbdetach | |
412 | * | |
413 | * PURPOSE: detach the pcb at *(isop) from it's socket and free | |
414 | * the mbufs associated with the pcb.. | |
415 | * Dequeues (isop) from its head. | |
416 | * | |
417 | * RETURNS: Nada. | |
418 | * | |
419 | * SIDE EFFECTS: | |
420 | * | |
421 | * NOTES: | |
422 | */ | |
423 | void | |
424 | iso_pcbdetach(isop) | |
425 | struct isopcb *isop; | |
426 | { | |
427 | struct socket *so = isop->isop_socket; | |
428 | ||
429 | IFDEBUG(D_ISO) | |
430 | printf("iso_pcbdetach(isop 0x%x socket 0x%x so 0x%x)\n", | |
431 | isop, isop->isop_socket, so); | |
432 | ENDDEBUG | |
77d3b1ec | 433 | #ifdef TPCONS |
01acbfa1 | 434 | if (isop->isop_chan) { |
77d3b1ec KS |
435 | register struct pklcd *lcp = (struct pklcd *)isop->isop_chan; |
436 | if (--isop->isop_refcnt > 0) | |
437 | return; | |
01acbfa1 KS |
438 | if (lcp && lcp->lcd_state == DATA_TRANSFER) { |
439 | lcp->lcd_upper = 0; | |
440 | lcp->lcd_upnext = 0; | |
77d3b1ec | 441 | pk_disconnect(lcp); |
01acbfa1 | 442 | } |
77d3b1ec KS |
443 | isop->isop_chan = 0; |
444 | } | |
445 | #endif | |
446 | if (so) { /* in the x.25 domain, we sometimes have no socket */ | |
627d3292 KS |
447 | so->so_pcb = 0; |
448 | sofree(so); | |
449 | } | |
450 | IFDEBUG(D_ISO) | |
451 | printf("iso_pcbdetach 2 \n"); | |
452 | ENDDEBUG | |
453 | if (isop->isop_options) | |
454 | (void)m_free(isop->isop_options); | |
455 | IFDEBUG(D_ISO) | |
456 | printf("iso_pcbdetach 3 \n"); | |
457 | ENDDEBUG | |
458 | if (isop->isop_route.ro_rt) | |
459 | rtfree(isop->isop_route.ro_rt); | |
460 | IFDEBUG(D_ISO) | |
461 | printf("iso_pcbdetach 3.1\n"); | |
462 | ENDDEBUG | |
463 | if (isop->isop_clnpcache != NULL) { | |
464 | struct clnp_cache *clcp = | |
465 | mtod(isop->isop_clnpcache, struct clnp_cache *); | |
466 | IFDEBUG(D_ISO) | |
467 | printf("iso_pcbdetach 3.2: clcp 0x%x freeing clc_hdr x%x\n", | |
468 | clcp, clcp->clc_hdr); | |
469 | ENDDEBUG | |
470 | if (clcp->clc_hdr != NULL) | |
471 | m_free(clcp->clc_hdr); | |
472 | IFDEBUG(D_ISO) | |
473 | printf("iso_pcbdetach 3.3: freeing cache x%x\n", | |
474 | isop->isop_clnpcache); | |
475 | ENDDEBUG | |
476 | m_free(isop->isop_clnpcache); | |
477 | } | |
478 | IFDEBUG(D_ISO) | |
479 | printf("iso_pcbdetach 4 \n"); | |
480 | ENDDEBUG | |
481 | remque(isop); | |
482 | IFDEBUG(D_ISO) | |
483 | printf("iso_pcbdetach 5 \n"); | |
484 | ENDDEBUG | |
a50e2bc0 KS |
485 | if (isop->isop_laddr && (isop->isop_laddr != &isop->isop_sladdr)) |
486 | m_freem(dtom(isop->isop_laddr)); | |
ad85902c | 487 | free((caddr_t)isop, M_PCB); |
627d3292 KS |
488 | } |
489 | ||
627d3292 KS |
490 | |
491 | /* | |
492 | * FUNCTION: iso_pcbnotify | |
493 | * | |
494 | * PURPOSE: notify all connections in this protocol's queue (head) | |
495 | * that have peer address (dst) of the problem (errno) | |
496 | * by calling (notify) on the connections' isopcbs. | |
497 | * | |
498 | * RETURNS: Rien. | |
499 | * | |
500 | * SIDE EFFECTS: | |
501 | * | |
502 | * NOTES: (notify) is called at splimp! | |
503 | */ | |
504 | void | |
c61c8804 | 505 | iso_pcbnotify(head, siso, errno, notify) |
627d3292 | 506 | struct isopcb *head; |
c61c8804 | 507 | register struct sockaddr_iso *siso; |
627d3292 KS |
508 | int errno, (*notify)(); |
509 | { | |
c61c8804 | 510 | register struct isopcb *isop; |
627d3292 KS |
511 | int s = splimp(); |
512 | ||
513 | IFDEBUG(D_ISO) | |
514 | printf("iso_pcbnotify(head 0x%x, notify 0x%x) dst:\n", head, notify); | |
515 | ENDDEBUG | |
c61c8804 KS |
516 | for (isop = head->isop_next; isop != head; isop = isop->isop_next) { |
517 | if (isop->isop_socket == 0 || isop->isop_faddr == 0 || | |
518 | !SAME_ISOADDR(siso, isop->isop_faddr)) { | |
627d3292 KS |
519 | IFDEBUG(D_ISO) |
520 | printf("iso_pcbnotify: CONTINUE isop 0x%x, sock 0x%x\n" , | |
521 | isop, isop->isop_socket); | |
c61c8804 | 522 | printf("addrmatch cmp'd with (0x%x):\n", isop->isop_faddr); |
a50e2bc0 | 523 | dump_isoaddr(isop->isop_faddr); |
627d3292 | 524 | ENDDEBUG |
627d3292 KS |
525 | continue; |
526 | } | |
527 | if (errno) | |
528 | isop->isop_socket->so_error = errno; | |
627d3292 | 529 | if (notify) |
c61c8804 | 530 | (*notify)(isop); |
627d3292 KS |
531 | } |
532 | splx(s); | |
533 | IFDEBUG(D_ISO) | |
534 | printf("END OF iso_pcbnotify\n" ); | |
535 | ENDDEBUG | |
536 | } | |
537 | ||
538 | ||
539 | /* | |
540 | * FUNCTION: iso_pcblookup | |
541 | * | |
542 | * PURPOSE: looks for a given combination of (faddr), (fport), | |
543 | * (lport), (laddr) in the queue named by (head). | |
544 | * Argument (flags) is ignored. | |
545 | * | |
546 | * RETURNS: ptr to the isopcb if it finds a connection matching | |
547 | * these arguments, o.w. returns zero. | |
548 | * | |
549 | * SIDE EFFECTS: | |
550 | * | |
551 | * NOTES: | |
552 | */ | |
553 | struct isopcb * | |
a50e2bc0 | 554 | iso_pcblookup(head, fportlen, fport, laddr) |
627d3292 | 555 | struct isopcb *head; |
a50e2bc0 KS |
556 | register struct sockaddr_iso *laddr; |
557 | caddr_t fport; | |
558 | int fportlen; | |
627d3292 KS |
559 | { |
560 | register struct isopcb *isop; | |
a50e2bc0 | 561 | register caddr_t lp = TSEL(laddr); |
44f52ea5 | 562 | unsigned int llen = laddr->siso_tlen; |
627d3292 KS |
563 | |
564 | IFDEBUG(D_ISO) | |
a50e2bc0 KS |
565 | printf("iso_pcblookup(head 0x%x laddr 0x%x fport 0x%x)\n", |
566 | head, laddr, fport); | |
627d3292 KS |
567 | ENDDEBUG |
568 | for (isop = head->isop_next; isop != head; isop = isop->isop_next) { | |
a50e2bc0 KS |
569 | if (isop->isop_laddr == 0 || isop->isop_laddr == laddr) |
570 | continue; | |
44f52ea5 | 571 | if (isop->isop_laddr->siso_tlen != llen) |
627d3292 | 572 | continue; |
a50e2bc0 KS |
573 | if (bcmp(lp, TSEL(isop->isop_laddr), llen)) |
574 | continue; | |
575 | if (fportlen && isop->isop_faddr && | |
576 | bcmp(fport, TSEL(isop->isop_faddr), (unsigned)fportlen)) | |
627d3292 KS |
577 | continue; |
578 | /* PHASE2 | |
579 | * addrmatch1 should be iso_addrmatch(a, b, mask) | |
580 | * where mask is taken from isop->isop_laddrmask (new field) | |
581 | * isop_lnetmask will also be available in isop | |
627d3292 KS |
582 | if (laddr != &zeroiso_addr && |
583 | !iso_addrmatch1(laddr, &(isop->isop_laddr.siso_addr))) | |
584 | continue; | |
a50e2bc0 KS |
585 | */ |
586 | if (laddr->siso_nlen && (!SAME_ISOADDR(laddr, isop->isop_laddr))) | |
587 | continue; | |
627d3292 KS |
588 | return (isop); |
589 | } | |
590 | return (struct isopcb *)0; | |
591 | } | |
592 | #endif ISO |