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