Merge from vendor branch LIBARCHIVE:
[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.7 2005/02/01 00:51:50 joerg 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         satm->satm_len = sizeof(*satm);
580
581         saddr = &satm->satm_addr.t_atm_sap_addr;
582         if (atp->atp_attr.nif && atp->atp_attr.nif->nif_pif->pif_siginst) {
583                 saddr->SVE_tag_addr = T_ATM_PRESENT;
584                 ATM_ADDR_SEL_COPY(
585                         &atp->atp_attr.nif->nif_pif->pif_siginst->si_addr,
586                         atp->atp_attr.nif->nif_sel, saddr);
587                 if (saddr->address_format == T_ATM_ENDSYS_ADDR)
588                         saddr->SVE_tag_selector = T_ATM_PRESENT;
589                 else
590                         saddr->SVE_tag_selector = T_ATM_ABSENT;
591         } else {
592                 saddr->SVE_tag_addr = T_ATM_ABSENT;
593                 saddr->SVE_tag_selector = T_ATM_ABSENT;
594                 saddr->address_format = T_ATM_ABSENT;
595         }
596         satm->satm_addr.t_atm_sap_layer2.SVE_tag = T_ATM_ABSENT;
597         satm->satm_addr.t_atm_sap_layer3.SVE_tag = T_ATM_ABSENT;
598         satm->satm_addr.t_atm_sap_appl.SVE_tag = T_ATM_ABSENT;
599
600         *addr = (struct sockaddr *)satm;
601         return (0);
602 }
603
604
605 /*
606  * Retrieve peer socket address
607  *
608  * Called at splnet.
609  *
610  * Arguments:
611  *      so      pointer to socket
612  *      addr    pointer to pointer to contain protocol address
613  *
614  * Returns:
615  *      0       request processed
616  *      errno   error processing request - reason indicated
617  *
618  */
619 int
620 atm_sock_peeraddr(so, addr)
621         struct socket   *so;
622         struct sockaddr **addr;
623 {
624         struct sockaddr_atm     *satm;
625         struct t_atm_sap_addr   *saddr;
626         Atm_pcb         *atp = sotoatmpcb(so);
627         Atm_connvc      *cvp;
628
629         /*
630          * Return remote address, if known
631          */
632         satm = KM_ALLOC(sizeof *satm, M_SONAME, M_WAITOK);
633         if (satm == NULL)
634                 return (ENOMEM);
635
636         KM_ZERO(satm, sizeof(*satm));
637         satm->satm_family = AF_ATM;
638         satm->satm_len = sizeof(*satm);
639
640         saddr = &satm->satm_addr.t_atm_sap_addr;
641         if (so->so_state & SS_ISCONNECTED) {
642                 cvp = atp->atp_conn->co_connvc;
643                 saddr->SVE_tag_addr = T_ATM_PRESENT;
644                 if (cvp->cvc_flags & CVCF_CALLER) {
645                         ATM_ADDR_COPY(&cvp->cvc_attr.called.addr, saddr);
646                 } else {
647                         if (cvp->cvc_attr.calling.tag == T_ATM_PRESENT) {
648                                 ATM_ADDR_COPY(&cvp->cvc_attr.calling.addr,
649                                                         saddr);
650                         } else {
651                                 saddr->SVE_tag_addr = T_ATM_ABSENT;
652                                 saddr->address_format = T_ATM_ABSENT;
653                         }
654                 }
655                 if (saddr->address_format == T_ATM_ENDSYS_ADDR)
656                         saddr->SVE_tag_selector = T_ATM_PRESENT;
657                 else
658                         saddr->SVE_tag_selector = T_ATM_ABSENT;
659         } else {
660                 saddr->SVE_tag_addr = T_ATM_ABSENT;
661                 saddr->SVE_tag_selector = T_ATM_ABSENT;
662                 saddr->address_format = T_ATM_ABSENT;
663         }
664         satm->satm_addr.t_atm_sap_layer2.SVE_tag = T_ATM_ABSENT;
665         satm->satm_addr.t_atm_sap_layer3.SVE_tag = T_ATM_ABSENT;
666         satm->satm_addr.t_atm_sap_appl.SVE_tag = T_ATM_ABSENT;
667
668         *addr = (struct sockaddr *)satm;
669         return (0);
670 }
671
672
673 /*
674  * Common setsockopt processing
675  *
676  * Called at splnet.
677  *
678  * Arguments:
679  *      so      pointer to socket
680  *      sopt    pointer to socket option info
681  *      atp     pointer to ATM PCB
682  *
683  * Returns:
684  *      0       request processed
685  *      errno   error processing request - reason indicated
686  *
687  */
688 int
689 atm_sock_setopt(so, sopt, atp)
690         struct socket   *so;
691         struct sockopt  *sopt;
692         Atm_pcb         *atp;
693 {
694         int     err = 0;
695         union {
696                 struct t_atm_aal5       aal5;
697                 struct t_atm_traffic    trf;
698                 struct t_atm_bearer     brr;
699                 struct t_atm_bhli       bhl;
700                 struct t_atm_blli       bll;
701                 Atm_addr                addr;
702                 struct t_atm_cause      cau;
703                 struct t_atm_qos        qos;
704                 struct t_atm_transit    trn;
705                 struct t_atm_net_intf   nif;
706                 struct t_atm_llc        llc;
707                 struct t_atm_app_name   appn;
708         } p;
709
710 #define MAXVAL(bits)    ((1 << bits) - 1)
711 #define MAXMASK(bits)   (~MAXVAL(bits))
712
713         switch (sopt->sopt_name) {
714
715         case T_ATM_AAL5:
716                 err = sooptcopyin(sopt, &p.aal5, sizeof p.aal5, sizeof p.aal5);
717                 if (err)
718                         break;
719                 if ((p.aal5.forward_max_SDU_size != T_ATM_ABSENT) &&
720                     (p.aal5.forward_max_SDU_size & MAXMASK(16)))
721                         return (EINVAL);
722                 if ((p.aal5.backward_max_SDU_size != T_ATM_ABSENT) &&
723                     (p.aal5.backward_max_SDU_size & MAXMASK(16)))
724                         return (EINVAL);
725                 if ((p.aal5.SSCS_type != T_ATM_ABSENT) &&
726                     (p.aal5.SSCS_type != T_ATM_NULL) &&
727                     (p.aal5.SSCS_type != T_ATM_SSCS_SSCOP_REL) &&
728                     (p.aal5.SSCS_type != T_ATM_SSCS_SSCOP_UNREL) &&
729                     (p.aal5.SSCS_type != T_ATM_SSCS_FR))
730                         return (EINVAL);
731
732                 if ((p.aal5.forward_max_SDU_size == T_ATM_ABSENT) &&
733                     (p.aal5.backward_max_SDU_size == T_ATM_ABSENT) &&
734                     (p.aal5.SSCS_type == T_ATM_ABSENT))
735                         atp->atp_attr.aal.tag = T_ATM_ABSENT;
736                 else {
737                         atp->atp_attr.aal.tag = T_ATM_PRESENT;
738                         atp->atp_attr.aal.type = ATM_AAL5;
739                         atp->atp_attr.aal.v.aal5 = p.aal5;
740                 }
741                 break;
742
743         case T_ATM_TRAFFIC:
744                 err = sooptcopyin(sopt, &p.trf, sizeof p.trf, sizeof p.trf);
745                 if (err)
746                         break;
747                 if ((p.trf.forward.PCR_high_priority != T_ATM_ABSENT) &&
748                     (p.trf.forward.PCR_high_priority & MAXMASK(24)))
749                         return (EINVAL);
750                 if (p.trf.forward.PCR_all_traffic & MAXMASK(24))
751                         return (EINVAL);
752                 if ((p.trf.forward.SCR_high_priority != T_ATM_ABSENT) &&
753                     (p.trf.forward.SCR_high_priority & MAXMASK(24)))
754                         return (EINVAL);
755                 if ((p.trf.forward.SCR_all_traffic != T_ATM_ABSENT) &&
756                     (p.trf.forward.SCR_all_traffic & MAXMASK(24)))
757                         return (EINVAL);
758                 if ((p.trf.forward.MBS_high_priority != T_ATM_ABSENT) &&
759                     (p.trf.forward.MBS_high_priority & MAXMASK(24)))
760                         return (EINVAL);
761                 if ((p.trf.forward.MBS_all_traffic != T_ATM_ABSENT) &&
762                     (p.trf.forward.MBS_all_traffic & MAXMASK(24)))
763                         return (EINVAL);
764                 if ((p.trf.forward.tagging != T_YES) &&
765                     (p.trf.forward.tagging != T_NO))
766                         return (EINVAL);
767
768                 if ((p.trf.backward.PCR_high_priority != T_ATM_ABSENT) &&
769                     (p.trf.backward.PCR_high_priority & MAXMASK(24)))
770                         return (EINVAL);
771                 if (p.trf.backward.PCR_all_traffic & MAXMASK(24))
772                         return (EINVAL);
773                 if ((p.trf.backward.SCR_high_priority != T_ATM_ABSENT) &&
774                     (p.trf.backward.SCR_high_priority & MAXMASK(24)))
775                         return (EINVAL);
776                 if ((p.trf.backward.SCR_all_traffic != T_ATM_ABSENT) &&
777                     (p.trf.backward.SCR_all_traffic & MAXMASK(24)))
778                         return (EINVAL);
779                 if ((p.trf.backward.MBS_high_priority != T_ATM_ABSENT) &&
780                     (p.trf.backward.MBS_high_priority & MAXMASK(24)))
781                         return (EINVAL);
782                 if ((p.trf.backward.MBS_all_traffic != T_ATM_ABSENT) &&
783                     (p.trf.backward.MBS_all_traffic & MAXMASK(24)))
784                         return (EINVAL);
785                 if ((p.trf.backward.tagging != T_YES) &&
786                     (p.trf.backward.tagging != T_NO))
787                         return (EINVAL);
788                 if ((p.trf.best_effort != T_YES) &&
789                     (p.trf.best_effort != T_NO))
790                         return (EINVAL);
791
792                 atp->atp_attr.traffic.tag = T_ATM_PRESENT;
793                 atp->atp_attr.traffic.v = p.trf;
794                 break;
795
796         case T_ATM_BEARER_CAP:
797                 err = sooptcopyin(sopt, &p.brr, sizeof p.brr, sizeof p.brr);
798                 if (err)
799                         break;
800                 if ((p.brr.bearer_class != T_ATM_CLASS_A) &&
801                     (p.brr.bearer_class != T_ATM_CLASS_C) &&
802                     (p.brr.bearer_class != T_ATM_CLASS_X))
803                         return (EINVAL);
804                 if ((p.brr.traffic_type != T_ATM_NULL) &&
805                     (p.brr.traffic_type != T_ATM_CBR) &&
806                     (p.brr.traffic_type != T_ATM_VBR))
807                         return (EINVAL);
808                 if ((p.brr.timing_requirements != T_ATM_NULL) &&
809                     (p.brr.timing_requirements != T_ATM_END_TO_END) &&
810                     (p.brr.timing_requirements != T_ATM_NO_END_TO_END))
811                         return (EINVAL);
812                 if ((p.brr.clipping_susceptibility != T_NO) &&
813                     (p.brr.clipping_susceptibility != T_YES))
814                         return (EINVAL);
815                 if ((p.brr.connection_configuration != T_ATM_1_TO_1) &&
816                     (p.brr.connection_configuration != T_ATM_1_TO_MANY))
817                         return (EINVAL);
818
819                 atp->atp_attr.bearer.tag = T_ATM_PRESENT;
820                 atp->atp_attr.bearer.v = p.brr;
821                 break;
822
823         case T_ATM_BHLI:
824                 err = sooptcopyin(sopt, &p.bhl, sizeof p.bhl, sizeof p.bhl);
825                 if (err)
826                         break;
827                 if ((p.bhl.ID_type != T_ATM_ABSENT) &&
828                     (p.bhl.ID_type != T_ATM_ISO_APP_ID) &&
829                     (p.bhl.ID_type != T_ATM_USER_APP_ID) &&
830                     (p.bhl.ID_type != T_ATM_VENDOR_APP_ID))
831                         return (EINVAL);
832
833                 if (p.bhl.ID_type == T_ATM_ABSENT)
834                         atp->atp_attr.bhli.tag = T_ATM_ABSENT;
835                 else {
836                         atp->atp_attr.bhli.tag = T_ATM_PRESENT;
837                         atp->atp_attr.bhli.v = p.bhl;
838                 }
839                 break;
840
841         case T_ATM_BLLI:
842                 err = sooptcopyin(sopt, &p.bll, sizeof p.bll, sizeof p.bll);
843                 if (err)
844                         break;
845                 if ((p.bll.layer_2_protocol.ID_type != T_ATM_ABSENT) &&
846                     (p.bll.layer_2_protocol.ID_type != T_ATM_SIMPLE_ID) &&
847                     (p.bll.layer_2_protocol.ID_type != T_ATM_USER_ID))
848                         return (EINVAL);
849                 if ((p.bll.layer_2_protocol.mode != T_ATM_ABSENT) &&
850                     (p.bll.layer_2_protocol.mode != T_ATM_BLLI_NORMAL_MODE) &&
851                     (p.bll.layer_2_protocol.mode != T_ATM_BLLI_EXTENDED_MODE))
852                         return (EINVAL);
853                 if ((p.bll.layer_2_protocol.window_size != T_ATM_ABSENT) &&
854                     (p.bll.layer_2_protocol.window_size < 1))
855                         return (EINVAL);
856
857                 if ((p.bll.layer_3_protocol.ID_type != T_ATM_ABSENT) &&
858                     (p.bll.layer_3_protocol.ID_type != T_ATM_SIMPLE_ID) &&
859                     (p.bll.layer_3_protocol.ID_type != T_ATM_IPI_ID) &&
860                     (p.bll.layer_3_protocol.ID_type != T_ATM_SNAP_ID) &&
861                     (p.bll.layer_3_protocol.ID_type != T_ATM_USER_ID))
862                         return (EINVAL);
863                 if ((p.bll.layer_3_protocol.mode != T_ATM_ABSENT) &&
864                     (p.bll.layer_3_protocol.mode != T_ATM_BLLI_NORMAL_MODE) &&
865                     (p.bll.layer_3_protocol.mode != T_ATM_BLLI_EXTENDED_MODE))
866                         return (EINVAL);
867                 if ((p.bll.layer_3_protocol.packet_size != T_ATM_ABSENT) &&
868                     (p.bll.layer_3_protocol.packet_size & MAXMASK(4)))
869                         return (EINVAL);
870                 if ((p.bll.layer_3_protocol.window_size != T_ATM_ABSENT) &&
871                     (p.bll.layer_3_protocol.window_size < 1))
872                         return (EINVAL);
873
874                 if (p.bll.layer_2_protocol.ID_type == T_ATM_ABSENT) 
875                         atp->atp_attr.blli.tag_l2 = T_ATM_ABSENT;
876                 else
877                         atp->atp_attr.blli.tag_l2 = T_ATM_PRESENT;
878
879                 if (p.bll.layer_3_protocol.ID_type == T_ATM_ABSENT) 
880                         atp->atp_attr.blli.tag_l3 = T_ATM_ABSENT;
881                 else
882                         atp->atp_attr.blli.tag_l3 = T_ATM_PRESENT;
883
884                 if ((atp->atp_attr.blli.tag_l2 == T_ATM_PRESENT) ||
885                     (atp->atp_attr.blli.tag_l3 == T_ATM_PRESENT))
886                         atp->atp_attr.blli.v = p.bll;
887                 break;
888
889         case T_ATM_DEST_ADDR:
890                 err = sooptcopyin(sopt, &p.addr, sizeof p.addr, sizeof p.addr);
891                 if (err)
892                         break;
893                 if ((p.addr.address_format != T_ATM_ENDSYS_ADDR) &&
894                     (p.addr.address_format != T_ATM_E164_ADDR))
895                         return (EINVAL);
896                 if (p.addr.address_length > ATM_ADDR_LEN)
897                         return (EINVAL);
898
899                 atp->atp_attr.called.tag = T_ATM_PRESENT;
900                 atp->atp_attr.called.addr = p.addr;
901                 break;
902
903         case T_ATM_DEST_SUB:
904                 err = sooptcopyin(sopt, &p.addr, sizeof p.addr, sizeof p.addr);
905                 if (err)
906                         break;
907                 if ((p.addr.address_format != T_ATM_ABSENT) &&
908                     (p.addr.address_format != T_ATM_NSAP_ADDR))
909                         return (EINVAL);
910                 if (p.addr.address_length > ATM_ADDR_LEN)
911                         return (EINVAL);
912
913                 /* T_ATM_DEST_ADDR controls tag */
914                 atp->atp_attr.called.subaddr = p.addr;
915                 break;
916
917         case T_ATM_ORIG_ADDR:
918                 return (EACCES);
919
920         case T_ATM_ORIG_SUB:
921                 return (EACCES);
922
923         case T_ATM_CALLER_ID:
924                 return (EACCES);
925
926         case T_ATM_CAUSE:
927                 err = sooptcopyin(sopt, &p.cau, sizeof p.cau, sizeof p.cau);
928                 if (err)
929                         break;
930                 if ((p.cau.coding_standard != T_ATM_ABSENT) &&
931                     (p.cau.coding_standard != T_ATM_ITU_CODING) &&
932                     (p.cau.coding_standard != T_ATM_NETWORK_CODING))
933                         return (EINVAL);
934                 if ((p.cau.location != T_ATM_LOC_USER) &&
935                     (p.cau.location != T_ATM_LOC_LOCAL_PRIVATE_NET) &&
936                     (p.cau.location != T_ATM_LOC_LOCAL_PUBLIC_NET) &&
937                     (p.cau.location != T_ATM_LOC_TRANSIT_NET) &&
938                     (p.cau.location != T_ATM_LOC_REMOTE_PUBLIC_NET) &&
939                     (p.cau.location != T_ATM_LOC_REMOTE_PRIVATE_NET) &&
940                     (p.cau.location != T_ATM_LOC_INTERNATIONAL_NET) &&
941                     (p.cau.location != T_ATM_LOC_BEYOND_INTERWORKING))
942                         return (EINVAL);
943
944                 if (p.cau.coding_standard == T_ATM_ABSENT)
945                         atp->atp_attr.cause.tag = T_ATM_ABSENT;
946                 else {
947                         atp->atp_attr.cause.tag = T_ATM_PRESENT;
948                         atp->atp_attr.cause.v = p.cau;
949                 }
950                 break;
951
952         case T_ATM_QOS:
953                 err = sooptcopyin(sopt, &p.qos, sizeof p.qos, sizeof p.qos);
954                 if (err)
955                         break;
956                 if ((p.qos.coding_standard != T_ATM_ABSENT) &&
957                     (p.qos.coding_standard != T_ATM_ITU_CODING) &&
958                     (p.qos.coding_standard != T_ATM_NETWORK_CODING))
959                         return (EINVAL);
960                 if ((p.qos.forward.qos_class != T_ATM_QOS_CLASS_0) &&
961                     (p.qos.forward.qos_class != T_ATM_QOS_CLASS_1) &&
962                     (p.qos.forward.qos_class != T_ATM_QOS_CLASS_2) &&
963                     (p.qos.forward.qos_class != T_ATM_QOS_CLASS_3) &&
964                     (p.qos.forward.qos_class != T_ATM_QOS_CLASS_4))
965                         return (EINVAL);
966                 if ((p.qos.backward.qos_class != T_ATM_QOS_CLASS_0) &&
967                     (p.qos.backward.qos_class != T_ATM_QOS_CLASS_1) &&
968                     (p.qos.backward.qos_class != T_ATM_QOS_CLASS_2) &&
969                     (p.qos.backward.qos_class != T_ATM_QOS_CLASS_3) &&
970                     (p.qos.backward.qos_class != T_ATM_QOS_CLASS_4))
971                         return (EINVAL);
972
973                 if (p.qos.coding_standard == T_ATM_ABSENT)
974                         atp->atp_attr.qos.tag = T_ATM_ABSENT;
975                 else {
976                         atp->atp_attr.qos.tag = T_ATM_PRESENT;
977                         atp->atp_attr.qos.v = p.qos;
978                 }
979                 break;
980
981         case T_ATM_TRANSIT:
982                 err = sooptcopyin(sopt, &p.trn, sizeof p.trn, sizeof p.trn);
983                 if (err)
984                         break;
985                 if (p.trn.length > T_ATM_MAX_NET_ID)
986                         return (EINVAL);
987
988                 if (p.trn.length == 0)
989                         atp->atp_attr.transit.tag = T_ATM_ABSENT;
990                 else {
991                         atp->atp_attr.transit.tag = T_ATM_PRESENT;
992                         atp->atp_attr.transit.v = p.trn;
993                 }
994                 break;
995
996         case T_ATM_ADD_LEAF:
997                 return (EPROTONOSUPPORT);       /* XXX */
998
999         case T_ATM_DROP_LEAF:
1000                 return (EPROTONOSUPPORT);       /* XXX */
1001
1002         case T_ATM_NET_INTF:
1003                 err = sooptcopyin(sopt, &p.nif, sizeof p.nif, sizeof p.nif);
1004                 if (err)
1005                         break;
1006
1007                 atp->atp_attr.nif = atm_nifname(p.nif.net_intf);
1008                 if (atp->atp_attr.nif == NULL)
1009                         return (ENXIO);
1010                 break;
1011
1012         case T_ATM_LLC:
1013                 err = sooptcopyin(sopt, &p.llc, sizeof p.llc, sizeof p.llc);
1014                 if (err)
1015                         break;
1016                 if ((p.llc.llc_len < T_ATM_LLC_MIN_LEN) ||
1017                     (p.llc.llc_len > T_ATM_LLC_MAX_LEN))
1018                         return (EINVAL);
1019
1020                 atp->atp_attr.llc.tag = T_ATM_PRESENT;
1021                 atp->atp_attr.llc.v = p.llc;
1022                 break;
1023
1024         case T_ATM_APP_NAME:
1025                 err = sooptcopyin(sopt, &p.appn, sizeof p.appn, sizeof p.appn);
1026                 if (err)
1027                         break;
1028
1029                 strncpy(atp->atp_name, p.appn.app_name, T_ATM_APP_NAME_LEN);
1030                 break;
1031
1032         default:
1033                 return (ENOPROTOOPT);
1034         }
1035
1036         return (err);
1037 }
1038
1039
1040 /*
1041  * Common getsockopt processing
1042  *
1043  * Called at splnet.
1044  *
1045  * Arguments:
1046  *      so      pointer to socket
1047  *      sopt    pointer to socket option info
1048  *      atp     pointer to ATM PCB
1049  *
1050  * Returns:
1051  *      0       request processed
1052  *      errno   error processing request - reason indicated
1053  *
1054  */
1055 int
1056 atm_sock_getopt(so, sopt, atp)
1057         struct socket   *so;
1058         struct sockopt  *sopt;
1059         Atm_pcb         *atp;
1060 {
1061         Atm_attributes  *ap;
1062
1063         /*
1064          * If socket is connected, return attributes for the VCC in use,
1065          * otherwise just return what the user has setup so far.
1066          */
1067         if (so->so_state & SS_ISCONNECTED)
1068                 ap = &atp->atp_conn->co_connvc->cvc_attr;
1069         else
1070                 ap = &atp->atp_attr;
1071
1072         switch (sopt->sopt_name) {
1073
1074         case T_ATM_AAL5:
1075                 if ((ap->aal.tag == T_ATM_PRESENT) &&
1076                     (ap->aal.type == ATM_AAL5)) {
1077                         return (sooptcopyout(sopt, &ap->aal.v.aal5,
1078                                         sizeof ap->aal.v.aal5));
1079                 } else {
1080                         return (ENOENT);
1081                 }
1082                 break;
1083
1084         case T_ATM_TRAFFIC:
1085                 if (ap->traffic.tag == T_ATM_PRESENT) {
1086                         return (sooptcopyout(sopt, &ap->traffic.v,
1087                                         sizeof ap->traffic.v));
1088                 } else {
1089                         return (ENOENT);
1090                 }
1091                 break;
1092
1093         case T_ATM_BEARER_CAP:
1094                 if (ap->bearer.tag == T_ATM_PRESENT) {
1095                         return (sooptcopyout(sopt, &ap->bearer.v,
1096                                         sizeof ap->bearer.v));
1097                 } else {
1098                         return (ENOENT);
1099                 }
1100                 break;
1101
1102         case T_ATM_BHLI:
1103                 if (ap->bhli.tag == T_ATM_PRESENT) {
1104                         return (sooptcopyout(sopt, &ap->bhli.v,
1105                                         sizeof ap->bhli.v));
1106                 } else {
1107                         return (ENOENT);
1108                 }
1109                 break;
1110
1111         case T_ATM_BLLI:
1112                 if ((ap->blli.tag_l2 == T_ATM_PRESENT) ||
1113                     (ap->blli.tag_l3 == T_ATM_PRESENT)) {
1114                         return (sooptcopyout(sopt, &ap->blli.v,
1115                                         sizeof ap->blli.v));
1116                 } else {
1117                         return (ENOENT);
1118                 }
1119                 break;
1120
1121         case T_ATM_DEST_ADDR:
1122                 if (ap->called.tag == T_ATM_PRESENT) {
1123                         return (sooptcopyout(sopt, &ap->called.addr,
1124                                         sizeof ap->called.addr));
1125                 } else {
1126                         return (ENOENT);
1127                 }
1128                 break;
1129
1130         case T_ATM_DEST_SUB:
1131                 if (ap->called.tag == T_ATM_PRESENT) {
1132                         return (sooptcopyout(sopt, &ap->called.subaddr,
1133                                         sizeof ap->called.subaddr));
1134                 } else {
1135                         return (ENOENT);
1136                 }
1137                 break;
1138
1139         case T_ATM_ORIG_ADDR:
1140                 if (ap->calling.tag == T_ATM_PRESENT) {
1141                         return (sooptcopyout(sopt, &ap->calling.addr,
1142                                         sizeof ap->calling.addr));
1143                 } else {
1144                         return (ENOENT);
1145                 }
1146                 break;
1147
1148         case T_ATM_ORIG_SUB:
1149                 if (ap->calling.tag == T_ATM_PRESENT) {
1150                         return (sooptcopyout(sopt, &ap->calling.subaddr,
1151                                         sizeof ap->calling.subaddr));
1152                 } else {
1153                         return (ENOENT);
1154                 }
1155                 break;
1156
1157         case T_ATM_CALLER_ID:
1158                 if (ap->calling.tag == T_ATM_PRESENT) {
1159                         return (sooptcopyout(sopt, &ap->calling.cid,
1160                                         sizeof ap->calling.cid));
1161                 } else {
1162                         return (ENOENT);
1163                 }
1164                 break;
1165
1166         case T_ATM_CAUSE:
1167                 if (ap->cause.tag == T_ATM_PRESENT) {
1168                         return (sooptcopyout(sopt, &ap->cause.v,
1169                                         sizeof ap->cause.v));
1170                 } else {
1171                         return (ENOENT);
1172                 }
1173                 break;
1174
1175         case T_ATM_QOS:
1176                 if (ap->qos.tag == T_ATM_PRESENT) {
1177                         return (sooptcopyout(sopt, &ap->qos.v,
1178                                         sizeof ap->qos.v));
1179                 } else {
1180                         return (ENOENT);
1181                 }
1182                 break;
1183
1184         case T_ATM_TRANSIT:
1185                 if (ap->transit.tag == T_ATM_PRESENT) {
1186                         return (sooptcopyout(sopt, &ap->transit.v,
1187                                         sizeof ap->transit.v));
1188                 } else {
1189                         return (ENOENT);
1190                 }
1191                 break;
1192
1193         case T_ATM_LEAF_IND:
1194                 return (EPROTONOSUPPORT);       /* XXX */
1195
1196         case T_ATM_NET_INTF:
1197                 if (ap->nif) {
1198                         struct t_atm_net_intf   netif;
1199                         struct ifnet            *ifp;
1200
1201                         ifp = &ap->nif->nif_if;
1202                         (void) snprintf(netif.net_intf, sizeof(netif.net_intf),
1203                             "%s", ifp->if_xname);
1204                         return (sooptcopyout(sopt, &netif,
1205                                         sizeof netif));
1206                 } else {
1207                         return (ENOENT);
1208                 }
1209                 break;
1210
1211         case T_ATM_LLC:
1212                 if (ap->llc.tag == T_ATM_PRESENT) {
1213                         return (sooptcopyout(sopt, &ap->llc.v,
1214                                         sizeof ap->llc.v));
1215                 } else {
1216                         return (ENOENT);
1217                 }
1218                 break;
1219
1220         default:
1221                 return (ENOPROTOOPT);
1222         }
1223
1224         return (0);
1225 }
1226
1227
1228 /*
1229  * Process Socket VCC Connected Notification
1230  *
1231  * Arguments:
1232  *      toku    owner's connection token (atm_pcb protocol block)
1233  *
1234  * Returns:
1235  *      none
1236  *
1237  */
1238 void
1239 atm_sock_connected(toku)
1240         void            *toku;
1241 {
1242         Atm_pcb         *atp = (Atm_pcb *)toku;
1243
1244         /*
1245          * Connection is setup
1246          */
1247         atm_sock_stat.as_conncomp[atp->atp_type]++;
1248         soisconnected(atp->atp_socket);
1249 }
1250
1251
1252 /*
1253  * Process Socket VCC Cleared Notification
1254  *
1255  * Arguments:
1256  *      toku    owner's connection token (atm_pcb protocol block)
1257  *      cause   pointer to cause code
1258  *
1259  * Returns:
1260  *      none
1261  *
1262  */
1263 void
1264 atm_sock_cleared(toku, cause)
1265         void            *toku;
1266         struct t_atm_cause      *cause;
1267 {
1268         Atm_pcb         *atp = (Atm_pcb *)toku;
1269         struct socket   *so;
1270
1271         so = atp->atp_socket;
1272
1273         /*
1274          * Save call clearing cause
1275          */
1276         atp->atp_attr.cause.tag = T_ATM_PRESENT;
1277         atp->atp_attr.cause.v = *cause;
1278
1279         /*
1280          * Set user error code
1281          */
1282         if (so->so_state & SS_ISCONNECTED) {
1283                 so->so_error = ECONNRESET;
1284                 atm_sock_stat.as_connclr[atp->atp_type]++;
1285         } else {
1286                 so->so_error = ECONNREFUSED;
1287                 atm_sock_stat.as_connfail[atp->atp_type]++;
1288         }
1289
1290         /*
1291          * Connection is gone
1292          */
1293         atp->atp_conn = NULL;
1294         soisdisconnected(so);
1295
1296         /*
1297          * Cleanup failed incoming connection setup
1298          */
1299         if (so->so_state & SS_NOFDREF) {
1300                 (void) atm_sock_detach(so);
1301         }
1302 }
1303