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