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