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