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