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