Initial import from FreeBSD RELENG_4:
[dragonfly.git] / sys / netproto / atm / atm_socket.c
1 /*
2  *
3  * ===================================
4  * HARP  |  Host ATM Research Platform
5  * ===================================
6  *
7  *
8  * This Host ATM Research Platform ("HARP") file (the "Software") is
9  * made available by Network Computing Services, Inc. ("NetworkCS")
10  * "AS IS".  NetworkCS does not provide maintenance, improvements or
11  * support of any kind.
12  *
13  * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14  * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15  * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16  * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17  * In no event shall NetworkCS be responsible for any damages, including
18  * but not limited to consequential damages, arising from or relating to
19  * any use of the Software or related support.
20  *
21  * Copyright 1994-1998 Network Computing Services, Inc.
22  *
23  * Copies of this Software may be made, however, the above copyright
24  * notice must be reproduced on all copies.
25  *
26  *      @(#) $FreeBSD: src/sys/netatm/atm_socket.c,v 1.4 1999/08/28 00:48:37 peter Exp $
27  *
28  */
29
30 /*
31  * Core ATM Services
32  * -----------------
33  *
34  * ATM common socket protocol processing
35  *
36  */
37
38 #include <netatm/kern_include.h>
39
40 #ifndef lint
41 __RCSID("@(#) $FreeBSD: src/sys/netatm/atm_socket.c,v 1.4 1999/08/28 00:48:37 peter Exp $");
42 #endif
43
44
45 /*
46  * Local functions
47  */
48
49
50 /*
51  * Local variables
52  */
53 static struct sp_info           atm_pcb_pool = {
54         "atm pcb pool",                 /* si_name */
55         sizeof(Atm_pcb),                /* si_blksiz */
56         10,                             /* si_blkcnt */
57         100                             /* si_maxallow */
58 };
59
60 static struct t_atm_cause       atm_sock_cause = {
61         T_ATM_ITU_CODING,
62         T_ATM_LOC_USER,
63         T_ATM_CAUSE_UNSPECIFIED_NORMAL,
64         {0, 0, 0, 0}
65 };
66
67
68 /*
69  * Allocate resources for a new ATM socket
70  *
71  * Called at splnet.
72  *
73  * Arguments:
74  *      so      pointer to socket
75  *      send    socket send buffer maximum
76  *      recv    socket receive buffer maximum
77  *
78  * Returns:
79  *      0       attach successful
80  *      errno   attach failed - reason indicated
81  *
82  */
83 int
84 atm_sock_attach(so, send, recv)
85         struct socket   *so;
86         u_long          send;
87         u_long          recv;
88 {
89         Atm_pcb         *atp = sotoatmpcb(so);
90         int             err;
91
92         /*
93          * Make sure initialization has happened
94          */
95         if (!atm_init)
96                 atm_initialize();
97
98         /*
99          * Make sure we're not already attached
100          */
101         if (atp)
102                 return (EISCONN);
103
104         /*
105          * Reserve socket buffer space, if not already done
106          */
107         if ((so->so_snd.sb_hiwat == 0) || (so->so_rcv.sb_hiwat == 0)) {
108                 err = soreserve(so, send, recv);
109                 if (err)
110                         return (err);
111         }
112
113         /*
114          * Allocate and initialize our control block
115          */
116         atp = (Atm_pcb *)atm_allocate(&atm_pcb_pool);
117         if (atp == NULL)
118                 return (ENOMEM);
119
120         atp->atp_socket = so;
121         so->so_pcb = (caddr_t)atp;
122         return (0);
123 }
124
125
126 /*
127  * Detach from socket and free resources
128  *
129  * Called at splnet.
130  *
131  * Arguments:
132  *      so      pointer to socket
133  *
134  * Returns:
135  *      0       detach successful
136  *      errno   detach failed - reason indicated
137  *
138  */
139 int
140 atm_sock_detach(so)
141         struct socket   *so;
142 {
143         Atm_pcb         *atp = sotoatmpcb(so);
144
145         /*
146          * Make sure we're still attached
147          */
148         if (atp == NULL)
149                 return (ENOTCONN);
150
151         /*
152          * Terminate any (possibly pending) connection
153          */
154         if (atp->atp_conn) {
155                 (void) atm_sock_disconnect(so);
156         }
157
158         /*
159          * Break links and free control blocks
160          */
161         so->so_pcb = NULL;
162         sofree(so);
163
164         atm_free((caddr_t)atp);
165
166         return (0);
167 }
168
169
170 /*
171  * Bind local address to socket
172  *
173  * Called at splnet.
174  *
175  * Arguments:
176  *      so      pointer to socket
177  *      addr    pointer to protocol address
178  *
179  * Returns:
180  *      0       request processed
181  *      errno   error processing request - reason indicated
182  *
183  */
184 int
185 atm_sock_bind(so, addr)
186         struct socket   *so;
187         struct sockaddr *addr;
188 {
189         Atm_pcb                 *atp = sotoatmpcb(so);
190         Atm_attributes          attr;
191         struct sockaddr_atm     *satm;
192         struct t_atm_sap_addr   *sapadr;
193         struct t_atm_sap_layer2 *sapl2;
194         struct t_atm_sap_layer3 *sapl3;
195         struct t_atm_sap_appl   *sapapl;
196
197         /*
198          * Make sure we're still attached
199          */
200         if (atp == NULL)
201                 return (ENOTCONN);
202
203         /*
204          * Can't change local address once we've started connection process
205          */
206         if (atp->atp_conn != NULL)
207                 return (EADDRNOTAVAIL);
208
209         /*
210          * Validate requested local address
211          */
212         satm = (struct sockaddr_atm *)addr;
213         if (satm->satm_family != AF_ATM)
214                 return (EAFNOSUPPORT);
215
216         sapadr = &satm->satm_addr.t_atm_sap_addr;
217         if (sapadr->SVE_tag_addr == T_ATM_PRESENT) {
218                 if (sapadr->address_format == T_ATM_ENDSYS_ADDR) {
219                         if (sapadr->SVE_tag_selector != T_ATM_PRESENT)
220                                 return (EINVAL);
221                 } else if (sapadr->address_format == T_ATM_E164_ADDR) {
222                         if (sapadr->SVE_tag_selector != T_ATM_ABSENT)
223                                 return (EINVAL);
224                 } else
225                         return (EINVAL);
226         } else if ((sapadr->SVE_tag_addr != T_ATM_ABSENT) &&
227                    (sapadr->SVE_tag_addr != T_ATM_ANY))
228                 return (EINVAL);
229         if (sapadr->address_length > ATM_ADDR_LEN)
230                 return (EINVAL);
231
232         sapl2 = &satm->satm_addr.t_atm_sap_layer2;
233         if (sapl2->SVE_tag == T_ATM_PRESENT) {
234                 if ((sapl2->ID_type != T_ATM_SIMPLE_ID) &&
235                     (sapl2->ID_type != T_ATM_USER_ID))
236                         return (EINVAL);
237         } else if ((sapl2->SVE_tag != T_ATM_ABSENT) &&
238                    (sapl2->SVE_tag != T_ATM_ANY))
239                 return (EINVAL);
240
241         sapl3 = &satm->satm_addr.t_atm_sap_layer3;
242         if (sapl3->SVE_tag == T_ATM_PRESENT) {
243                 if ((sapl3->ID_type != T_ATM_SIMPLE_ID) &&
244                     (sapl3->ID_type != T_ATM_IPI_ID) &&
245                     (sapl3->ID_type != T_ATM_SNAP_ID) &&
246                     (sapl3->ID_type != T_ATM_USER_ID))
247                         return (EINVAL);
248         } else if ((sapl3->SVE_tag != T_ATM_ABSENT) &&
249                    (sapl3->SVE_tag != T_ATM_ANY))
250                 return (EINVAL);
251
252         sapapl = &satm->satm_addr.t_atm_sap_appl;
253         if (sapapl->SVE_tag == T_ATM_PRESENT) {
254                 if ((sapapl->ID_type != T_ATM_ISO_APP_ID) &&
255                     (sapapl->ID_type != T_ATM_USER_APP_ID) &&
256                     (sapapl->ID_type != T_ATM_VENDOR_APP_ID))
257                         return (EINVAL);
258         } else if ((sapapl->SVE_tag != T_ATM_ABSENT) &&
259                    (sapapl->SVE_tag != T_ATM_ANY))
260                 return (EINVAL);
261
262         /*
263          * Create temporary attributes list so that we can check out the
264          * new bind parameters before we modify the socket's values;
265          */
266         attr = atp->atp_attr;
267         attr.called.tag = sapadr->SVE_tag_addr;
268         KM_COPY(&sapadr->address_format, &attr.called.addr, sizeof(Atm_addr));
269
270         attr.blli.tag_l2 = sapl2->SVE_tag;
271         if (sapl2->SVE_tag == T_ATM_PRESENT) {
272                 attr.blli.v.layer_2_protocol.ID_type = sapl2->ID_type;
273                 KM_COPY(&sapl2->ID, &attr.blli.v.layer_2_protocol.ID,
274                         sizeof(attr.blli.v.layer_2_protocol.ID));
275         }
276
277         attr.blli.tag_l3 = sapl3->SVE_tag;
278         if (sapl3->SVE_tag == T_ATM_PRESENT) {
279                 attr.blli.v.layer_3_protocol.ID_type = sapl3->ID_type;
280                 KM_COPY(&sapl3->ID, &attr.blli.v.layer_3_protocol.ID,
281                         sizeof(attr.blli.v.layer_3_protocol.ID));
282         }
283
284         attr.bhli.tag = sapapl->SVE_tag;
285         if (sapapl->SVE_tag == T_ATM_PRESENT) {
286                 attr.bhli.v.ID_type = sapapl->ID_type;
287                 KM_COPY(&sapapl->ID, &attr.bhli.v.ID,
288                         sizeof(attr.bhli.v.ID));
289         }
290
291         /*
292          * Make sure we have unique listening attributes
293          */
294         if (atm_cm_match(&attr, NULL) != NULL)
295                 return (EADDRINUSE);
296
297         /*
298          * Looks good, save new attributes
299          */
300         atp->atp_attr = attr;
301
302         return (0);
303 }
304
305
306 /*
307  * Listen for incoming connections
308  *
309  * Called at splnet.
310  *
311  * Arguments:
312  *      so      pointer to socket
313  *      epp     pointer to endpoint definition structure
314  *
315  * Returns:
316  *      0       request processed
317  *      errno   error processing request - reason indicated
318  *
319  */
320 int
321 atm_sock_listen(so, epp)
322         struct socket   *so;
323         Atm_endpoint    *epp;
324 {
325         Atm_pcb         *atp = sotoatmpcb(so);
326
327         /*
328          * Make sure we're still attached
329          */
330         if (atp == NULL)
331                 return (ENOTCONN);
332
333         /*
334          * Start listening for incoming calls
335          */
336         return (atm_cm_listen(epp, atp, &atp->atp_attr, &atp->atp_conn));
337 }
338
339
340 /*
341  * Connect socket to peer
342  *
343  * Called at splnet.
344  *
345  * Arguments:
346  *      so      pointer to socket
347  *      addr    pointer to protocol address
348  *      epp     pointer to endpoint definition structure
349  *
350  * Returns:
351  *      0       request processed
352  *      errno   error processing request - reason indicated
353  *
354  */
355 int
356 atm_sock_connect(so, addr, epp)
357         struct socket   *so;
358         struct sockaddr *addr;
359         Atm_endpoint    *epp;
360 {
361         Atm_pcb         *atp = sotoatmpcb(so);
362         struct sockaddr_atm     *satm;
363         struct t_atm_sap_addr   *sapadr;
364         struct t_atm_sap_layer2 *sapl2;
365         struct t_atm_sap_layer3 *sapl3;
366         struct t_atm_sap_appl   *sapapl;
367         int             err;
368
369         /*
370          * Make sure we're still attached
371          */
372         if (atp == NULL)
373                 return (ENOTCONN);
374
375         /*
376          * Validate requested peer address
377          */
378         satm = (struct sockaddr_atm *)addr;
379         if (satm->satm_family != AF_ATM)
380                 return (EAFNOSUPPORT);
381
382         sapadr = &satm->satm_addr.t_atm_sap_addr;
383         if (sapadr->SVE_tag_addr != T_ATM_PRESENT)
384                 return (EINVAL);
385         if (sapadr->address_format == T_ATM_ENDSYS_ADDR) {
386                 if (sapadr->SVE_tag_selector != T_ATM_PRESENT)
387                         return (EINVAL);
388         } else if (sapadr->address_format == T_ATM_E164_ADDR) {
389                 if (sapadr->SVE_tag_selector != T_ATM_ABSENT)
390                         return (EINVAL);
391         } else if (sapadr->address_format == T_ATM_PVC_ADDR) {
392                 if (sapadr->SVE_tag_selector != T_ATM_ABSENT)
393                         return (EINVAL);
394         } else
395                 return (EINVAL);
396         if (sapadr->address_length > ATM_ADDR_LEN)
397                 return (EINVAL);
398
399         sapl2 = &satm->satm_addr.t_atm_sap_layer2;
400         if (sapl2->SVE_tag == T_ATM_PRESENT) {
401                 if ((sapl2->ID_type != T_ATM_SIMPLE_ID) &&
402                     (sapl2->ID_type != T_ATM_USER_ID))
403                         return (EINVAL);
404         } else if (sapl2->SVE_tag != T_ATM_ABSENT)
405                 return (EINVAL);
406
407         sapl3 = &satm->satm_addr.t_atm_sap_layer3;
408         if (sapl3->SVE_tag == T_ATM_PRESENT) {
409                 if ((sapl3->ID_type != T_ATM_SIMPLE_ID) &&
410                     (sapl3->ID_type != T_ATM_IPI_ID) &&
411                     (sapl3->ID_type != T_ATM_SNAP_ID) &&
412                     (sapl3->ID_type != T_ATM_USER_ID))
413                         return (EINVAL);
414         } else if (sapl3->SVE_tag != T_ATM_ABSENT)
415                 return (EINVAL);
416
417         sapapl = &satm->satm_addr.t_atm_sap_appl;
418         if (sapapl->SVE_tag == T_ATM_PRESENT) {
419                 if ((sapapl->ID_type != T_ATM_ISO_APP_ID) &&
420                     (sapapl->ID_type != T_ATM_USER_APP_ID) &&
421                     (sapapl->ID_type != T_ATM_VENDOR_APP_ID))
422                         return (EINVAL);
423         } else if (sapapl->SVE_tag != T_ATM_ABSENT)
424                 return (EINVAL);
425
426         /*
427          * Select an outgoing network interface
428          */
429         if (atp->atp_attr.nif == NULL) {
430                 struct atm_pif  *pip;
431
432                 for (pip = atm_interface_head; pip != NULL;
433                                                 pip = pip->pif_next) {
434                         if (pip->pif_nif != NULL) {
435                                 atp->atp_attr.nif = pip->pif_nif;
436                                 break;
437                         }
438                 }
439                 if (atp->atp_attr.nif == NULL)
440                         return (ENXIO);
441         }
442
443         /*
444          * Set supplied connection attributes
445          */
446         atp->atp_attr.called.tag = T_ATM_PRESENT;
447         KM_COPY(&sapadr->address_format, &atp->atp_attr.called.addr,
448                         sizeof(Atm_addr));
449
450         atp->atp_attr.blli.tag_l2 = sapl2->SVE_tag;
451         if (sapl2->SVE_tag == T_ATM_PRESENT) {
452                 atp->atp_attr.blli.v.layer_2_protocol.ID_type = sapl2->ID_type;
453                 KM_COPY(&sapl2->ID, &atp->atp_attr.blli.v.layer_2_protocol.ID,
454                         sizeof(atp->atp_attr.blli.v.layer_2_protocol.ID));
455         }
456
457         atp->atp_attr.blli.tag_l3 = sapl3->SVE_tag;
458         if (sapl3->SVE_tag == T_ATM_PRESENT) {
459                 atp->atp_attr.blli.v.layer_3_protocol.ID_type = sapl3->ID_type;
460                 KM_COPY(&sapl3->ID, &atp->atp_attr.blli.v.layer_3_protocol.ID,
461                         sizeof(atp->atp_attr.blli.v.layer_3_protocol.ID));
462         }
463
464         atp->atp_attr.bhli.tag = sapapl->SVE_tag;
465         if (sapapl->SVE_tag == T_ATM_PRESENT) {
466                 atp->atp_attr.bhli.v.ID_type = sapapl->ID_type;
467                 KM_COPY(&sapapl->ID, &atp->atp_attr.bhli.v.ID,
468                         sizeof(atp->atp_attr.bhli.v.ID));
469         }
470
471         /*
472          * We're finally ready to initiate the ATM connection
473          */
474         soisconnecting(so);
475         atm_sock_stat.as_connreq[atp->atp_type]++;
476         err = atm_cm_connect(epp, atp, &atp->atp_attr, &atp->atp_conn);
477         if (err == 0) {
478                 /*
479                  * Connection is setup
480                  */
481                 atm_sock_stat.as_conncomp[atp->atp_type]++;
482                 soisconnected(so);
483
484         } else if (err == EINPROGRESS) {
485                 /*
486                  * We've got to wait for a connected event
487                  */
488                 err = 0;
489
490         } else {
491                 /*
492                  * Call failed...
493                  */
494                 atm_sock_stat.as_connfail[atp->atp_type]++;
495                 soisdisconnected(so);
496         }
497
498         return (err);
499 }
500
501
502 /*
503  * Disconnect connected socket
504  *
505  * Called at splnet.
506  *
507  * Arguments:
508  *      so      pointer to socket
509  *
510  * Returns:
511  *      0       request processed
512  *      errno   error processing request - reason indicated
513  *
514  */
515 int
516 atm_sock_disconnect(so)
517         struct socket   *so;
518 {
519         Atm_pcb         *atp = sotoatmpcb(so);
520         struct t_atm_cause      *cause;
521         int             err;
522
523         /*
524          * Make sure we're still attached
525          */
526         if (atp == NULL)
527                 return (ENOTCONN);
528
529         /*
530          * Release the ATM connection
531          */
532         if (atp->atp_conn) {
533                 if (atp->atp_attr.cause.tag == T_ATM_PRESENT)
534                         cause = &atp->atp_attr.cause.v;
535                 else
536                         cause = &atm_sock_cause;
537                 err = atm_cm_release(atp->atp_conn, cause);
538                 if (err)
539                         log(LOG_ERR, "atm_sock_disconnect: release fail (%d)\n",
540                                 err);
541                 atm_sock_stat.as_connrel[atp->atp_type]++;
542                 atp->atp_conn = NULL;
543         }
544
545         soisdisconnected(so);
546
547         return (0);
548 }
549
550
551 /*
552  * Retrieve local socket address
553  *
554  * Called at splnet.
555  *
556  * Arguments:
557  *      so      pointer to socket
558  *      addr    pointer to pointer to contain protocol address
559  *
560  * Returns:
561  *      0       request processed
562  *      errno   error processing request - reason indicated
563  *
564  */
565 int
566 atm_sock_sockaddr(so, addr)
567         struct socket   *so;
568         struct sockaddr **addr;
569 {
570         struct sockaddr_atm     *satm;
571         struct t_atm_sap_addr   *saddr;
572         Atm_pcb         *atp = sotoatmpcb(so);
573
574         /*
575          * Return local interface address, if known
576          */
577         satm = KM_ALLOC(sizeof *satm, M_SONAME, M_WAITOK);
578         if (satm == NULL)
579                 return (ENOMEM);
580
581         KM_ZERO(satm, sizeof(*satm));
582         satm->satm_family = AF_ATM;
583 #if (defined(BSD) && (BSD >= 199103))
584         satm->satm_len = sizeof(*satm);
585 #endif
586
587         saddr = &satm->satm_addr.t_atm_sap_addr;
588         if (atp->atp_attr.nif && atp->atp_attr.nif->nif_pif->pif_siginst) {
589                 saddr->SVE_tag_addr = T_ATM_PRESENT;
590                 ATM_ADDR_SEL_COPY(
591                         &atp->atp_attr.nif->nif_pif->pif_siginst->si_addr,
592                         atp->atp_attr.nif->nif_sel, saddr);
593                 if (saddr->address_format == T_ATM_ENDSYS_ADDR)
594                         saddr->SVE_tag_selector = T_ATM_PRESENT;
595                 else
596                         saddr->SVE_tag_selector = T_ATM_ABSENT;
597         } else {
598                 saddr->SVE_tag_addr = T_ATM_ABSENT;
599                 saddr->SVE_tag_selector = T_ATM_ABSENT;
600                 saddr->address_format = T_ATM_ABSENT;
601         }
602         satm->satm_addr.t_atm_sap_layer2.SVE_tag = T_ATM_ABSENT;
603         satm->satm_addr.t_atm_sap_layer3.SVE_tag = T_ATM_ABSENT;
604         satm->satm_addr.t_atm_sap_appl.SVE_tag = T_ATM_ABSENT;
605
606         *addr = (struct sockaddr *)satm;
607         return (0);
608 }
609
610
611 /*
612  * Retrieve peer socket address
613  *
614  * Called at splnet.
615  *
616  * Arguments:
617  *      so      pointer to socket
618  *      addr    pointer to pointer to contain protocol address
619  *
620  * Returns:
621  *      0       request processed
622  *      errno   error processing request - reason indicated
623  *
624  */
625 int
626 atm_sock_peeraddr(so, addr)
627         struct socket   *so;
628         struct sockaddr **addr;
629 {
630         struct sockaddr_atm     *satm;
631         struct t_atm_sap_addr   *saddr;
632         Atm_pcb         *atp = sotoatmpcb(so);
633         Atm_connvc      *cvp;
634
635         /*
636          * Return remote address, if known
637          */
638         satm = KM_ALLOC(sizeof *satm, M_SONAME, M_WAITOK);
639         if (satm == NULL)
640                 return (ENOMEM);
641
642         KM_ZERO(satm, sizeof(*satm));
643         satm->satm_family = AF_ATM;
644 #if (defined(BSD) && (BSD >= 199103))
645         satm->satm_len = sizeof(*satm);
646 #endif
647
648         saddr = &satm->satm_addr.t_atm_sap_addr;
649         if (so->so_state & SS_ISCONNECTED) {
650                 cvp = atp->atp_conn->co_connvc;
651                 saddr->SVE_tag_addr = T_ATM_PRESENT;
652                 if (cvp->cvc_flags & CVCF_CALLER) {
653                         ATM_ADDR_COPY(&cvp->cvc_attr.called.addr, saddr);
654                 } else {
655                         if (cvp->cvc_attr.calling.tag == T_ATM_PRESENT) {
656                                 ATM_ADDR_COPY(&cvp->cvc_attr.calling.addr,
657                                                         saddr);
658                         } else {
659                                 saddr->SVE_tag_addr = T_ATM_ABSENT;
660                                 saddr->address_format = T_ATM_ABSENT;
661                         }
662                 }
663                 if (saddr->address_format == T_ATM_ENDSYS_ADDR)
664                         saddr->SVE_tag_selector = T_ATM_PRESENT;
665                 else
666                         saddr->SVE_tag_selector = T_ATM_ABSENT;
667         } else {
668                 saddr->SVE_tag_addr = T_ATM_ABSENT;
669                 saddr->SVE_tag_selector = T_ATM_ABSENT;
670                 saddr->address_format = T_ATM_ABSENT;
671         }
672         satm->satm_addr.t_atm_sap_layer2.SVE_tag = T_ATM_ABSENT;
673         satm->satm_addr.t_atm_sap_layer3.SVE_tag = T_ATM_ABSENT;
674         satm->satm_addr.t_atm_sap_appl.SVE_tag = T_ATM_ABSENT;
675
676         *addr = (struct sockaddr *)satm;
677         return (0);
678 }
679
680
681 /*
682  * Common setsockopt processing
683  *
684  * Called at splnet.
685  *
686  * Arguments:
687  *      so      pointer to socket
688  *      sopt    pointer to socket option info
689  *      atp     pointer to ATM PCB
690  *
691  * Returns:
692  *      0       request processed
693  *      errno   error processing request - reason indicated
694  *
695  */
696 int
697 atm_sock_setopt(so, sopt, atp)
698         struct socket   *so;
699         struct sockopt  *sopt;
700         Atm_pcb         *atp;
701 {
702         int     err = 0;
703         union {
704                 struct t_atm_aal5       aal5;
705                 struct t_atm_traffic    trf;
706                 struct t_atm_bearer     brr;
707                 struct t_atm_bhli       bhl;
708                 struct t_atm_blli       bll;
709                 Atm_addr                addr;
710                 struct t_atm_cause      cau;
711                 struct t_atm_qos        qos;
712                 struct t_atm_transit    trn;
713                 struct t_atm_net_intf   nif;
714                 struct t_atm_llc        llc;
715                 struct t_atm_app_name   appn;
716         } p;
717
718 #define MAXVAL(bits)    ((1 << bits) - 1)
719 #define MAXMASK(bits)   (~MAXVAL(bits))
720
721         switch (sopt->sopt_name) {
722
723         case T_ATM_AAL5:
724                 err = sooptcopyin(sopt, &p.aal5, sizeof p.aal5, sizeof p.aal5);
725                 if (err)
726                         break;
727                 if ((p.aal5.forward_max_SDU_size != T_ATM_ABSENT) &&
728                     (p.aal5.forward_max_SDU_size & MAXMASK(16)))
729                         return (EINVAL);
730                 if ((p.aal5.backward_max_SDU_size != T_ATM_ABSENT) &&
731                     (p.aal5.backward_max_SDU_size & MAXMASK(16)))
732                         return (EINVAL);
733                 if ((p.aal5.SSCS_type != T_ATM_ABSENT) &&
734                     (p.aal5.SSCS_type != T_ATM_NULL) &&
735                     (p.aal5.SSCS_type != T_ATM_SSCS_SSCOP_REL) &&
736                     (p.aal5.SSCS_type != T_ATM_SSCS_SSCOP_UNREL) &&
737                     (p.aal5.SSCS_type != T_ATM_SSCS_FR))
738                         return (EINVAL);
739
740                 if ((p.aal5.forward_max_SDU_size == T_ATM_ABSENT) &&
741                     (p.aal5.backward_max_SDU_size == T_ATM_ABSENT) &&
742                     (p.aal5.SSCS_type == T_ATM_ABSENT))
743                         atp->atp_attr.aal.tag = T_ATM_ABSENT;
744                 else {
745                         atp->atp_attr.aal.tag = T_ATM_PRESENT;
746                         atp->atp_attr.aal.type = ATM_AAL5;
747                         atp->atp_attr.aal.v.aal5 = p.aal5;
748                 }
749                 break;
750
751         case T_ATM_TRAFFIC:
752                 err = sooptcopyin(sopt, &p.trf, sizeof p.trf, sizeof p.trf);
753                 if (err)
754                         break;
755                 if ((p.trf.forward.PCR_high_priority != T_ATM_ABSENT) &&
756                     (p.trf.forward.PCR_high_priority & MAXMASK(24)))
757                         return (EINVAL);
758                 if (p.trf.forward.PCR_all_traffic & MAXMASK(24))
759                         return (EINVAL);
760                 if ((p.trf.forward.SCR_high_priority != T_ATM_ABSENT) &&
761                     (p.trf.forward.SCR_high_priority & MAXMASK(24)))
762                         return (EINVAL);
763                 if ((p.trf.forward.SCR_all_traffic != T_ATM_ABSENT) &&
764                     (p.trf.forward.SCR_all_traffic & MAXMASK(24)))
765                         return (EINVAL);
766                 if ((p.trf.forward.MBS_high_priority != T_ATM_ABSENT) &&
767                     (p.trf.forward.MBS_high_priority & MAXMASK(24)))
768                         return (EINVAL);
769                 if ((p.trf.forward.MBS_all_traffic != T_ATM_ABSENT) &&
770                     (p.trf.forward.MBS_all_traffic & MAXMASK(24)))
771                         return (EINVAL);
772                 if ((p.trf.forward.tagging != T_YES) &&
773                     (p.trf.forward.tagging != T_NO))
774                         return (EINVAL);
775
776                 if ((p.trf.backward.PCR_high_priority != T_ATM_ABSENT) &&
777                     (p.trf.backward.PCR_high_priority & MAXMASK(24)))
778                         return (EINVAL);
779                 if (p.trf.backward.PCR_all_traffic & MAXMASK(24))
780                         return (EINVAL);
781                 if ((p.trf.backward.SCR_high_priority != T_ATM_ABSENT) &&
782                     (p.trf.backward.SCR_high_priority & MAXMASK(24)))
783                         return (EINVAL);
784                 if ((p.trf.backward.SCR_all_traffic != T_ATM_ABSENT) &&
785                     (p.trf.backward.SCR_all_traffic & MAXMASK(24)))
786                         return (EINVAL);
787                 if ((p.trf.backward.MBS_high_priority != T_ATM_ABSENT) &&
788                     (p.trf.backward.MBS_high_priority & MAXMASK(24)))
789                         return (EINVAL);
790                 if ((p.trf.backward.MBS_all_traffic != T_ATM_ABSENT) &&
791                     (p.trf.backward.MBS_all_traffic & MAXMASK(24)))
792                         return (EINVAL);
793                 if ((p.trf.backward.tagging != T_YES) &&
794                     (p.trf.backward.tagging != T_NO))
795                         return (EINVAL);
796                 if ((p.trf.best_effort != T_YES) &&
797                     (p.trf.best_effort != T_NO))
798                         return (EINVAL);
799
800                 atp->atp_attr.traffic.tag = T_ATM_PRESENT;
801                 atp->atp_attr.traffic.v = p.trf;
802                 break;
803
804         case T_ATM_BEARER_CAP:
805                 err = sooptcopyin(sopt, &p.brr, sizeof p.brr, sizeof p.brr);
806                 if (err)
807                         break;
808                 if ((p.brr.bearer_class != T_ATM_CLASS_A) &&
809                     (p.brr.bearer_class != T_ATM_CLASS_C) &&
810                     (p.brr.bearer_class != T_ATM_CLASS_X))
811                         return (EINVAL);
812                 if ((p.brr.traffic_type != T_ATM_NULL) &&
813                     (p.brr.traffic_type != T_ATM_CBR) &&
814                     (p.brr.traffic_type != T_ATM_VBR))
815                         return (EINVAL);
816                 if ((p.brr.timing_requirements != T_ATM_NULL) &&
817                     (p.brr.timing_requirements != T_ATM_END_TO_END) &&
818                     (p.brr.timing_requirements != T_ATM_NO_END_TO_END))
819                         return (EINVAL);
820                 if ((p.brr.clipping_susceptibility != T_NO) &&
821                     (p.brr.clipping_susceptibility != T_YES))
822                         return (EINVAL);
823                 if ((p.brr.connection_configuration != T_ATM_1_TO_1) &&
824                     (p.brr.connection_configuration != T_ATM_1_TO_MANY))
825                         return (EINVAL);
826
827                 atp->atp_attr.bearer.tag = T_ATM_PRESENT;
828                 atp->atp_attr.bearer.v = p.brr;
829                 break;
830
831         case T_ATM_BHLI:
832                 err = sooptcopyin(sopt, &p.bhl, sizeof p.bhl, sizeof p.bhl);
833                 if (err)
834                         break;
835                 if ((p.bhl.ID_type != T_ATM_ABSENT) &&
836                     (p.bhl.ID_type != T_ATM_ISO_APP_ID) &&
837                     (p.bhl.ID_type != T_ATM_USER_APP_ID) &&
838                     (p.bhl.ID_type != T_ATM_VENDOR_APP_ID))
839                         return (EINVAL);
840
841                 if (p.bhl.ID_type == T_ATM_ABSENT)
842                         atp->atp_attr.bhli.tag = T_ATM_ABSENT;
843                 else {
844                         atp->atp_attr.bhli.tag = T_ATM_PRESENT;
845                         atp->atp_attr.bhli.v = p.bhl;
846                 }
847                 break;
848
849         case T_ATM_BLLI:
850                 err = sooptcopyin(sopt, &p.bll, sizeof p.bll, sizeof p.bll);
851                 if (err)
852                         break;
853                 if ((p.bll.layer_2_protocol.ID_type != T_ATM_ABSENT) &&
854                     (p.bll.layer_2_protocol.ID_type != T_ATM_SIMPLE_ID) &&
855                     (p.bll.layer_2_protocol.ID_type != T_ATM_USER_ID))
856                         return (EINVAL);
857                 if ((p.bll.layer_2_protocol.mode != T_ATM_ABSENT) &&
858                     (p.bll.layer_2_protocol.mode != T_ATM_BLLI_NORMAL_MODE) &&
859                     (p.bll.layer_2_protocol.mode != T_ATM_BLLI_EXTENDED_MODE))
860                         return (EINVAL);
861                 if ((p.bll.layer_2_protocol.window_size != T_ATM_ABSENT) &&
862                     (p.bll.layer_2_protocol.window_size < 1))
863                         return (EINVAL);
864
865                 if ((p.bll.layer_3_protocol.ID_type != T_ATM_ABSENT) &&
866                     (p.bll.layer_3_protocol.ID_type != T_ATM_SIMPLE_ID) &&
867                     (p.bll.layer_3_protocol.ID_type != T_ATM_IPI_ID) &&
868                     (p.bll.layer_3_protocol.ID_type != T_ATM_SNAP_ID) &&
869                     (p.bll.layer_3_protocol.ID_type != T_ATM_USER_ID))
870                         return (EINVAL);
871                 if ((p.bll.layer_3_protocol.mode != T_ATM_ABSENT) &&
872                     (p.bll.layer_3_protocol.mode != T_ATM_BLLI_NORMAL_MODE) &&
873                     (p.bll.layer_3_protocol.mode != T_ATM_BLLI_EXTENDED_MODE))
874                         return (EINVAL);
875                 if ((p.bll.layer_3_protocol.packet_size != T_ATM_ABSENT) &&
876                     (p.bll.layer_3_protocol.packet_size & MAXMASK(4)))
877                         return (EINVAL);
878                 if ((p.bll.layer_3_protocol.window_size != T_ATM_ABSENT) &&
879                     (p.bll.layer_3_protocol.window_size < 1))
880                         return (EINVAL);
881
882                 if (p.bll.layer_2_protocol.ID_type == T_ATM_ABSENT) 
883                         atp->atp_attr.blli.tag_l2 = T_ATM_ABSENT;
884                 else
885                         atp->atp_attr.blli.tag_l2 = T_ATM_PRESENT;
886
887                 if (p.bll.layer_3_protocol.ID_type == T_ATM_ABSENT) 
888                         atp->atp_attr.blli.tag_l3 = T_ATM_ABSENT;
889                 else
890                         atp->atp_attr.blli.tag_l3 = T_ATM_PRESENT;
891
892                 if ((atp->atp_attr.blli.tag_l2 == T_ATM_PRESENT) ||
893                     (atp->atp_attr.blli.tag_l3 == T_ATM_PRESENT))
894                         atp->atp_attr.blli.v = p.bll;
895                 break;
896
897         case T_ATM_DEST_ADDR:
898                 err = sooptcopyin(sopt, &p.addr, sizeof p.addr, sizeof p.addr);
899                 if (err)
900                         break;
901                 if ((p.addr.address_format != T_ATM_ENDSYS_ADDR) &&
902                     (p.addr.address_format != T_ATM_E164_ADDR))
903                         return (EINVAL);
904                 if (p.addr.address_length > ATM_ADDR_LEN)
905                         return (EINVAL);
906
907                 atp->atp_attr.called.tag = T_ATM_PRESENT;
908                 atp->atp_attr.called.addr = p.addr;
909                 break;
910
911         case T_ATM_DEST_SUB:
912                 err = sooptcopyin(sopt, &p.addr, sizeof p.addr, sizeof p.addr);
913                 if (err)
914                         break;
915                 if ((p.addr.address_format != T_ATM_ABSENT) &&
916                     (p.addr.address_format != T_ATM_NSAP_ADDR))
917                         return (EINVAL);
918                 if (p.addr.address_length > ATM_ADDR_LEN)
919                         return (EINVAL);
920
921                 /* T_ATM_DEST_ADDR controls tag */
922                 atp->atp_attr.called.subaddr = p.addr;
923                 break;
924
925         case T_ATM_ORIG_ADDR:
926                 return (EACCES);
927
928         case T_ATM_ORIG_SUB:
929                 return (EACCES);
930
931         case T_ATM_CALLER_ID:
932                 return (EACCES);
933
934         case T_ATM_CAUSE:
935                 err = sooptcopyin(sopt, &p.cau, sizeof p.cau, sizeof p.cau);
936                 if (err)
937                         break;
938                 if ((p.cau.coding_standard != T_ATM_ABSENT) &&
939                     (p.cau.coding_standard != T_ATM_ITU_CODING) &&
940                     (p.cau.coding_standard != T_ATM_NETWORK_CODING))
941                         return (EINVAL);
942                 if ((p.cau.location != T_ATM_LOC_USER) &&
943                     (p.cau.location != T_ATM_LOC_LOCAL_PRIVATE_NET) &&
944                     (p.cau.location != T_ATM_LOC_LOCAL_PUBLIC_NET) &&
945                     (p.cau.location != T_ATM_LOC_TRANSIT_NET) &&
946                     (p.cau.location != T_ATM_LOC_REMOTE_PUBLIC_NET) &&
947                     (p.cau.location != T_ATM_LOC_REMOTE_PRIVATE_NET) &&
948                     (p.cau.location != T_ATM_LOC_INTERNATIONAL_NET) &&
949                     (p.cau.location != T_ATM_LOC_BEYOND_INTERWORKING))
950                         return (EINVAL);
951
952                 if (p.cau.coding_standard == T_ATM_ABSENT)
953                         atp->atp_attr.cause.tag = T_ATM_ABSENT;
954                 else {
955                         atp->atp_attr.cause.tag = T_ATM_PRESENT;
956                         atp->atp_attr.cause.v = p.cau;
957                 }
958                 break;
959
960         case T_ATM_QOS:
961                 err = sooptcopyin(sopt, &p.qos, sizeof p.qos, sizeof p.qos);
962                 if (err)
963                         break;
964                 if ((p.qos.coding_standard != T_ATM_ABSENT) &&
965                     (p.qos.coding_standard != T_ATM_ITU_CODING) &&
966                     (p.qos.coding_standard != T_ATM_NETWORK_CODING))
967                         return (EINVAL);
968                 if ((p.qos.forward.qos_class != T_ATM_QOS_CLASS_0) &&
969                     (p.qos.forward.qos_class != T_ATM_QOS_CLASS_1) &&
970                     (p.qos.forward.qos_class != T_ATM_QOS_CLASS_2) &&
971                     (p.qos.forward.qos_class != T_ATM_QOS_CLASS_3) &&
972                     (p.qos.forward.qos_class != T_ATM_QOS_CLASS_4))
973                         return (EINVAL);
974                 if ((p.qos.backward.qos_class != T_ATM_QOS_CLASS_0) &&
975                     (p.qos.backward.qos_class != T_ATM_QOS_CLASS_1) &&
976                     (p.qos.backward.qos_class != T_ATM_QOS_CLASS_2) &&
977                     (p.qos.backward.qos_class != T_ATM_QOS_CLASS_3) &&
978                     (p.qos.backward.qos_class != T_ATM_QOS_CLASS_4))
979                         return (EINVAL);
980
981                 if (p.qos.coding_standard == T_ATM_ABSENT)
982                         atp->atp_attr.qos.tag = T_ATM_ABSENT;
983                 else {
984                         atp->atp_attr.qos.tag = T_ATM_PRESENT;
985                         atp->atp_attr.qos.v = p.qos;
986                 }
987                 break;
988
989         case T_ATM_TRANSIT:
990                 err = sooptcopyin(sopt, &p.trn, sizeof p.trn, sizeof p.trn);
991                 if (err)
992                         break;
993                 if (p.trn.length > T_ATM_MAX_NET_ID)
994                         return (EINVAL);
995
996                 if (p.trn.length == 0)
997                         atp->atp_attr.transit.tag = T_ATM_ABSENT;
998                 else {
999                         atp->atp_attr.transit.tag = T_ATM_PRESENT;
1000                         atp->atp_attr.transit.v = p.trn;
1001                 }
1002                 break;
1003
1004         case T_ATM_ADD_LEAF:
1005                 return (EPROTONOSUPPORT);       /* XXX */
1006
1007         case T_ATM_DROP_LEAF:
1008                 return (EPROTONOSUPPORT);       /* XXX */
1009
1010         case T_ATM_NET_INTF:
1011                 err = sooptcopyin(sopt, &p.nif, sizeof p.nif, sizeof p.nif);
1012                 if (err)
1013                         break;
1014
1015                 atp->atp_attr.nif = atm_nifname(p.nif.net_intf);
1016                 if (atp->atp_attr.nif == NULL)
1017                         return (ENXIO);
1018                 break;
1019
1020         case T_ATM_LLC:
1021                 err = sooptcopyin(sopt, &p.llc, sizeof p.llc, sizeof p.llc);
1022                 if (err)
1023                         break;
1024                 if ((p.llc.llc_len < T_ATM_LLC_MIN_LEN) ||
1025                     (p.llc.llc_len > T_ATM_LLC_MAX_LEN))
1026                         return (EINVAL);
1027
1028                 atp->atp_attr.llc.tag = T_ATM_PRESENT;
1029                 atp->atp_attr.llc.v = p.llc;
1030                 break;
1031
1032         case T_ATM_APP_NAME:
1033                 err = sooptcopyin(sopt, &p.appn, sizeof p.appn, sizeof p.appn);
1034                 if (err)
1035                         break;
1036
1037                 strncpy(atp->atp_name, p.appn.app_name, T_ATM_APP_NAME_LEN);
1038                 break;
1039
1040         default:
1041                 return (ENOPROTOOPT);
1042         }
1043
1044         return (err);
1045 }
1046
1047
1048 /*
1049  * Common getsockopt processing
1050  *
1051  * Called at splnet.
1052  *
1053  * Arguments:
1054  *      so      pointer to socket
1055  *      sopt    pointer to socket option info
1056  *      atp     pointer to ATM PCB
1057  *
1058  * Returns:
1059  *      0       request processed
1060  *      errno   error processing request - reason indicated
1061  *
1062  */
1063 int
1064 atm_sock_getopt(so, sopt, atp)
1065         struct socket   *so;
1066         struct sockopt  *sopt;
1067         Atm_pcb         *atp;
1068 {
1069         Atm_attributes  *ap;
1070
1071         /*
1072          * If socket is connected, return attributes for the VCC in use,
1073          * otherwise just return what the user has setup so far.
1074          */
1075         if (so->so_state & SS_ISCONNECTED)
1076                 ap = &atp->atp_conn->co_connvc->cvc_attr;
1077         else
1078                 ap = &atp->atp_attr;
1079
1080         switch (sopt->sopt_name) {
1081
1082         case T_ATM_AAL5:
1083                 if ((ap->aal.tag == T_ATM_PRESENT) &&
1084                     (ap->aal.type == ATM_AAL5)) {
1085                         return (sooptcopyout(sopt, &ap->aal.v.aal5,
1086                                         sizeof ap->aal.v.aal5));
1087                 } else {
1088                         return (ENOENT);
1089                 }
1090                 break;
1091
1092         case T_ATM_TRAFFIC:
1093                 if (ap->traffic.tag == T_ATM_PRESENT) {
1094                         return (sooptcopyout(sopt, &ap->traffic.v,
1095                                         sizeof ap->traffic.v));
1096                 } else {
1097                         return (ENOENT);
1098                 }
1099                 break;
1100
1101         case T_ATM_BEARER_CAP:
1102                 if (ap->bearer.tag == T_ATM_PRESENT) {
1103                         return (sooptcopyout(sopt, &ap->bearer.v,
1104                                         sizeof ap->bearer.v));
1105                 } else {
1106                         return (ENOENT);
1107                 }
1108                 break;
1109
1110         case T_ATM_BHLI:
1111                 if (ap->bhli.tag == T_ATM_PRESENT) {
1112                         return (sooptcopyout(sopt, &ap->bhli.v,
1113                                         sizeof ap->bhli.v));
1114                 } else {
1115                         return (ENOENT);
1116                 }
1117                 break;
1118
1119         case T_ATM_BLLI:
1120                 if ((ap->blli.tag_l2 == T_ATM_PRESENT) ||
1121                     (ap->blli.tag_l3 == T_ATM_PRESENT)) {
1122                         return (sooptcopyout(sopt, &ap->blli.v,
1123                                         sizeof ap->blli.v));
1124                 } else {
1125                         return (ENOENT);
1126                 }
1127                 break;
1128
1129         case T_ATM_DEST_ADDR:
1130                 if (ap->called.tag == T_ATM_PRESENT) {
1131                         return (sooptcopyout(sopt, &ap->called.addr,
1132                                         sizeof ap->called.addr));
1133                 } else {
1134                         return (ENOENT);
1135                 }
1136                 break;
1137
1138         case T_ATM_DEST_SUB:
1139                 if (ap->called.tag == T_ATM_PRESENT) {
1140                         return (sooptcopyout(sopt, &ap->called.subaddr,
1141                                         sizeof ap->called.subaddr));
1142                 } else {
1143                         return (ENOENT);
1144                 }
1145                 break;
1146
1147         case T_ATM_ORIG_ADDR:
1148                 if (ap->calling.tag == T_ATM_PRESENT) {
1149                         return (sooptcopyout(sopt, &ap->calling.addr,
1150                                         sizeof ap->calling.addr));
1151                 } else {
1152                         return (ENOENT);
1153                 }
1154                 break;
1155
1156         case T_ATM_ORIG_SUB:
1157                 if (ap->calling.tag == T_ATM_PRESENT) {
1158                         return (sooptcopyout(sopt, &ap->calling.subaddr,
1159                                         sizeof ap->calling.subaddr));
1160                 } else {
1161                         return (ENOENT);
1162                 }
1163                 break;
1164
1165         case T_ATM_CALLER_ID:
1166                 if (ap->calling.tag == T_ATM_PRESENT) {
1167                         return (sooptcopyout(sopt, &ap->calling.cid,
1168                                         sizeof ap->calling.cid));
1169                 } else {
1170                         return (ENOENT);
1171                 }
1172                 break;
1173
1174         case T_ATM_CAUSE:
1175                 if (ap->cause.tag == T_ATM_PRESENT) {
1176                         return (sooptcopyout(sopt, &ap->cause.v,
1177                                         sizeof ap->cause.v));
1178                 } else {
1179                         return (ENOENT);
1180                 }
1181                 break;
1182
1183         case T_ATM_QOS:
1184                 if (ap->qos.tag == T_ATM_PRESENT) {
1185                         return (sooptcopyout(sopt, &ap->qos.v,
1186                                         sizeof ap->qos.v));
1187                 } else {
1188                         return (ENOENT);
1189                 }
1190                 break;
1191
1192         case T_ATM_TRANSIT:
1193                 if (ap->transit.tag == T_ATM_PRESENT) {
1194                         return (sooptcopyout(sopt, &ap->transit.v,
1195                                         sizeof ap->transit.v));
1196                 } else {
1197                         return (ENOENT);
1198                 }
1199                 break;
1200
1201         case T_ATM_LEAF_IND:
1202                 return (EPROTONOSUPPORT);       /* XXX */
1203
1204         case T_ATM_NET_INTF:
1205                 if (ap->nif) {
1206                         struct t_atm_net_intf   netif;
1207                         struct ifnet            *ifp;
1208
1209                         ifp = &ap->nif->nif_if;
1210                         (void) snprintf(netif.net_intf, sizeof(netif.net_intf),
1211                             "%s%d", ifp->if_name, ifp->if_unit);
1212                         return (sooptcopyout(sopt, &netif,
1213                                         sizeof netif));
1214                 } else {
1215                         return (ENOENT);
1216                 }
1217                 break;
1218
1219         case T_ATM_LLC:
1220                 if (ap->llc.tag == T_ATM_PRESENT) {
1221                         return (sooptcopyout(sopt, &ap->llc.v,
1222                                         sizeof ap->llc.v));
1223                 } else {
1224                         return (ENOENT);
1225                 }
1226                 break;
1227
1228         default:
1229                 return (ENOPROTOOPT);
1230         }
1231
1232         return (0);
1233 }
1234
1235
1236 /*
1237  * Process Socket VCC Connected Notification
1238  *
1239  * Arguments:
1240  *      toku    owner's connection token (atm_pcb protocol block)
1241  *
1242  * Returns:
1243  *      none
1244  *
1245  */
1246 void
1247 atm_sock_connected(toku)
1248         void            *toku;
1249 {
1250         Atm_pcb         *atp = (Atm_pcb *)toku;
1251
1252         /*
1253          * Connection is setup
1254          */
1255         atm_sock_stat.as_conncomp[atp->atp_type]++;
1256         soisconnected(atp->atp_socket);
1257 }
1258
1259
1260 /*
1261  * Process Socket VCC Cleared Notification
1262  *
1263  * Arguments:
1264  *      toku    owner's connection token (atm_pcb protocol block)
1265  *      cause   pointer to cause code
1266  *
1267  * Returns:
1268  *      none
1269  *
1270  */
1271 void
1272 atm_sock_cleared(toku, cause)
1273         void            *toku;
1274         struct t_atm_cause      *cause;
1275 {
1276         Atm_pcb         *atp = (Atm_pcb *)toku;
1277         struct socket   *so;
1278
1279         so = atp->atp_socket;
1280
1281         /*
1282          * Save call clearing cause
1283          */
1284         atp->atp_attr.cause.tag = T_ATM_PRESENT;
1285         atp->atp_attr.cause.v = *cause;
1286
1287         /*
1288          * Set user error code
1289          */
1290         if (so->so_state & SS_ISCONNECTED) {
1291                 so->so_error = ECONNRESET;
1292                 atm_sock_stat.as_connclr[atp->atp_type]++;
1293         } else {
1294                 so->so_error = ECONNREFUSED;
1295                 atm_sock_stat.as_connfail[atp->atp_type]++;
1296         }
1297
1298         /*
1299          * Connection is gone
1300          */
1301         atp->atp_conn = NULL;
1302         soisdisconnected(so);
1303
1304         /*
1305          * Cleanup failed incoming connection setup
1306          */
1307         if (so->so_state & SS_NOFDREF) {
1308                 (void) atm_sock_detach(so);
1309         }
1310 }
1311