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