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