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