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