MFC r1.3 r1.13 r1.8 (HEAD):
[dragonfly.git] / sys / netproto / atm / atm_socket.c
blobeb84bcb163e44aa407c16c4d4d2e97319bd7d066
1 /*
3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
8 * This Host ATM Research Platform ("HARP") file (the "Software") is
9 * made available by Network Computing Services, Inc. ("NetworkCS")
10 * "AS IS". NetworkCS does not provide maintenance, improvements or
11 * support of any kind.
13 * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14 * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15 * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16 * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17 * In no event shall NetworkCS be responsible for any damages, including
18 * but not limited to consequential damages, arising from or relating to
19 * any use of the Software or related support.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
26 * @(#) $FreeBSD: src/sys/netatm/atm_socket.c,v 1.4 1999/08/28 00:48:37 peter Exp $
27 * @(#) $DragonFly: src/sys/netproto/atm/atm_socket.c,v 1.12 2008/06/21 12:30:19 aggelos Exp $
31 * Core ATM Services
32 * -----------------
34 * ATM common socket protocol processing
38 #include "kern_include.h"
41 * Local functions
46 * Local variables
48 static struct sp_info atm_pcb_pool = {
49 "atm pcb pool", /* si_name */
50 sizeof(Atm_pcb), /* si_blksiz */
51 10, /* si_blkcnt */
52 100 /* si_maxallow */
55 static struct t_atm_cause atm_sock_cause = {
56 T_ATM_ITU_CODING,
57 T_ATM_LOC_USER,
58 T_ATM_CAUSE_UNSPECIFIED_NORMAL,
59 {0, 0, 0, 0}
64 * Allocate resources for a new ATM socket
66 * Called at splnet.
68 * Arguments:
69 * so pointer to socket
70 * send socket send buffer maximum
71 * recv socket receive buffer maximum
73 * Returns:
74 * 0 attach successful
75 * errno attach failed - reason indicated
78 int
79 atm_sock_attach(struct socket *so, u_long send, u_long recv, struct rlimit *rl)
81 Atm_pcb *atp = sotoatmpcb(so);
82 int err;
85 * Make sure initialization has happened
87 if (!atm_init)
88 atm_initialize();
91 * Make sure we're not already attached
93 if (atp)
94 return (EISCONN);
97 * Reserve socket buffer space, if not already done
99 if ((so->so_snd.ssb_hiwat == 0) || (so->so_rcv.ssb_hiwat == 0)) {
100 err = soreserve(so, send, recv, rl);
101 if (err)
102 return (err);
106 * Allocate and initialize our control block
108 atp = (Atm_pcb *)atm_allocate(&atm_pcb_pool);
109 if (atp == NULL)
110 return (ENOMEM);
112 atp->atp_socket = so;
113 so->so_pcb = (caddr_t)atp;
114 return (0);
119 * Detach from socket and free resources
121 * Called at splnet.
123 * Arguments:
124 * so pointer to socket
126 * Returns:
127 * 0 detach successful
128 * errno detach failed - reason indicated
132 atm_sock_detach(struct socket *so)
134 Atm_pcb *atp = sotoatmpcb(so);
137 * Make sure we're still attached
139 if (atp == NULL)
140 return (ENOTCONN);
143 * Terminate any (possibly pending) connection
145 if (atp->atp_conn) {
146 atm_sock_disconnect(so);
150 * Break links and free control blocks
152 so->so_pcb = NULL;
153 sofree(so);
155 atm_free((caddr_t)atp);
157 return (0);
162 * Bind local address to socket
164 * Called at splnet.
166 * Arguments:
167 * so pointer to socket
168 * addr pointer to protocol address
170 * Returns:
171 * 0 request processed
172 * errno error processing request - reason indicated
176 atm_sock_bind(struct socket *so, struct sockaddr *addr)
178 Atm_pcb *atp = sotoatmpcb(so);
179 Atm_attributes attr;
180 struct sockaddr_atm *satm;
181 struct t_atm_sap_addr *sapadr;
182 struct t_atm_sap_layer2 *sapl2;
183 struct t_atm_sap_layer3 *sapl3;
184 struct t_atm_sap_appl *sapapl;
187 * Make sure we're still attached
189 if (atp == NULL)
190 return (ENOTCONN);
193 * Can't change local address once we've started connection process
195 if (atp->atp_conn != NULL)
196 return (EADDRNOTAVAIL);
199 * Validate requested local address
201 satm = (struct sockaddr_atm *)addr;
202 if (satm->satm_family != AF_ATM)
203 return (EAFNOSUPPORT);
205 sapadr = &satm->satm_addr.t_atm_sap_addr;
206 if (sapadr->SVE_tag_addr == T_ATM_PRESENT) {
207 if (sapadr->address_format == T_ATM_ENDSYS_ADDR) {
208 if (sapadr->SVE_tag_selector != T_ATM_PRESENT)
209 return (EINVAL);
210 } else if (sapadr->address_format == T_ATM_E164_ADDR) {
211 if (sapadr->SVE_tag_selector != T_ATM_ABSENT)
212 return (EINVAL);
213 } else
214 return (EINVAL);
215 } else if ((sapadr->SVE_tag_addr != T_ATM_ABSENT) &&
216 (sapadr->SVE_tag_addr != T_ATM_ANY))
217 return (EINVAL);
218 if (sapadr->address_length > ATM_ADDR_LEN)
219 return (EINVAL);
221 sapl2 = &satm->satm_addr.t_atm_sap_layer2;
222 if (sapl2->SVE_tag == T_ATM_PRESENT) {
223 if ((sapl2->ID_type != T_ATM_SIMPLE_ID) &&
224 (sapl2->ID_type != T_ATM_USER_ID))
225 return (EINVAL);
226 } else if ((sapl2->SVE_tag != T_ATM_ABSENT) &&
227 (sapl2->SVE_tag != T_ATM_ANY))
228 return (EINVAL);
230 sapl3 = &satm->satm_addr.t_atm_sap_layer3;
231 if (sapl3->SVE_tag == T_ATM_PRESENT) {
232 if ((sapl3->ID_type != T_ATM_SIMPLE_ID) &&
233 (sapl3->ID_type != T_ATM_IPI_ID) &&
234 (sapl3->ID_type != T_ATM_SNAP_ID) &&
235 (sapl3->ID_type != T_ATM_USER_ID))
236 return (EINVAL);
237 } else if ((sapl3->SVE_tag != T_ATM_ABSENT) &&
238 (sapl3->SVE_tag != T_ATM_ANY))
239 return (EINVAL);
241 sapapl = &satm->satm_addr.t_atm_sap_appl;
242 if (sapapl->SVE_tag == T_ATM_PRESENT) {
243 if ((sapapl->ID_type != T_ATM_ISO_APP_ID) &&
244 (sapapl->ID_type != T_ATM_USER_APP_ID) &&
245 (sapapl->ID_type != T_ATM_VENDOR_APP_ID))
246 return (EINVAL);
247 } else if ((sapapl->SVE_tag != T_ATM_ABSENT) &&
248 (sapapl->SVE_tag != T_ATM_ANY))
249 return (EINVAL);
252 * Create temporary attributes list so that we can check out the
253 * new bind parameters before we modify the socket's values;
255 attr = atp->atp_attr;
256 attr.called.tag = sapadr->SVE_tag_addr;
257 KM_COPY(&sapadr->address_format, &attr.called.addr, sizeof(Atm_addr));
259 attr.blli.tag_l2 = sapl2->SVE_tag;
260 if (sapl2->SVE_tag == T_ATM_PRESENT) {
261 attr.blli.v.layer_2_protocol.ID_type = sapl2->ID_type;
262 KM_COPY(&sapl2->ID, &attr.blli.v.layer_2_protocol.ID,
263 sizeof(attr.blli.v.layer_2_protocol.ID));
266 attr.blli.tag_l3 = sapl3->SVE_tag;
267 if (sapl3->SVE_tag == T_ATM_PRESENT) {
268 attr.blli.v.layer_3_protocol.ID_type = sapl3->ID_type;
269 KM_COPY(&sapl3->ID, &attr.blli.v.layer_3_protocol.ID,
270 sizeof(attr.blli.v.layer_3_protocol.ID));
273 attr.bhli.tag = sapapl->SVE_tag;
274 if (sapapl->SVE_tag == T_ATM_PRESENT) {
275 attr.bhli.v.ID_type = sapapl->ID_type;
276 KM_COPY(&sapapl->ID, &attr.bhli.v.ID,
277 sizeof(attr.bhli.v.ID));
281 * Make sure we have unique listening attributes
283 if (atm_cm_match(&attr, NULL) != NULL)
284 return (EADDRINUSE);
287 * Looks good, save new attributes
289 atp->atp_attr = attr;
291 return (0);
296 * Listen for incoming connections
298 * Called at splnet.
300 * Arguments:
301 * so pointer to socket
302 * epp pointer to endpoint definition structure
304 * Returns:
305 * 0 request processed
306 * errno error processing request - reason indicated
310 atm_sock_listen(struct socket *so, Atm_endpoint *epp)
312 Atm_pcb *atp = sotoatmpcb(so);
315 * Make sure we're still attached
317 if (atp == NULL)
318 return (ENOTCONN);
321 * Start listening for incoming calls
323 return (atm_cm_listen(epp, atp, &atp->atp_attr, &atp->atp_conn));
328 * Connect socket to peer
330 * Called at splnet.
332 * Arguments:
333 * so pointer to socket
334 * addr pointer to protocol address
335 * epp pointer to endpoint definition structure
337 * Returns:
338 * 0 request processed
339 * errno error processing request - reason indicated
343 atm_sock_connect(struct socket *so, struct sockaddr *addr, Atm_endpoint *epp)
345 Atm_pcb *atp = sotoatmpcb(so);
346 struct sockaddr_atm *satm;
347 struct t_atm_sap_addr *sapadr;
348 struct t_atm_sap_layer2 *sapl2;
349 struct t_atm_sap_layer3 *sapl3;
350 struct t_atm_sap_appl *sapapl;
351 int err;
354 * Make sure we're still attached
356 if (atp == NULL)
357 return (ENOTCONN);
360 * Validate requested peer address
362 satm = (struct sockaddr_atm *)addr;
363 if (satm->satm_family != AF_ATM)
364 return (EAFNOSUPPORT);
366 sapadr = &satm->satm_addr.t_atm_sap_addr;
367 if (sapadr->SVE_tag_addr != T_ATM_PRESENT)
368 return (EINVAL);
369 if (sapadr->address_format == T_ATM_ENDSYS_ADDR) {
370 if (sapadr->SVE_tag_selector != T_ATM_PRESENT)
371 return (EINVAL);
372 } else if (sapadr->address_format == T_ATM_E164_ADDR) {
373 if (sapadr->SVE_tag_selector != T_ATM_ABSENT)
374 return (EINVAL);
375 } else if (sapadr->address_format == T_ATM_PVC_ADDR) {
376 if (sapadr->SVE_tag_selector != T_ATM_ABSENT)
377 return (EINVAL);
378 } else
379 return (EINVAL);
380 if (sapadr->address_length > ATM_ADDR_LEN)
381 return (EINVAL);
383 sapl2 = &satm->satm_addr.t_atm_sap_layer2;
384 if (sapl2->SVE_tag == T_ATM_PRESENT) {
385 if ((sapl2->ID_type != T_ATM_SIMPLE_ID) &&
386 (sapl2->ID_type != T_ATM_USER_ID))
387 return (EINVAL);
388 } else if (sapl2->SVE_tag != T_ATM_ABSENT)
389 return (EINVAL);
391 sapl3 = &satm->satm_addr.t_atm_sap_layer3;
392 if (sapl3->SVE_tag == T_ATM_PRESENT) {
393 if ((sapl3->ID_type != T_ATM_SIMPLE_ID) &&
394 (sapl3->ID_type != T_ATM_IPI_ID) &&
395 (sapl3->ID_type != T_ATM_SNAP_ID) &&
396 (sapl3->ID_type != T_ATM_USER_ID))
397 return (EINVAL);
398 } else if (sapl3->SVE_tag != T_ATM_ABSENT)
399 return (EINVAL);
401 sapapl = &satm->satm_addr.t_atm_sap_appl;
402 if (sapapl->SVE_tag == T_ATM_PRESENT) {
403 if ((sapapl->ID_type != T_ATM_ISO_APP_ID) &&
404 (sapapl->ID_type != T_ATM_USER_APP_ID) &&
405 (sapapl->ID_type != T_ATM_VENDOR_APP_ID))
406 return (EINVAL);
407 } else if (sapapl->SVE_tag != T_ATM_ABSENT)
408 return (EINVAL);
411 * Select an outgoing network interface
413 if (atp->atp_attr.nif == NULL) {
414 struct atm_pif *pip;
416 for (pip = atm_interface_head; pip != NULL;
417 pip = pip->pif_next) {
418 if (pip->pif_nif != NULL) {
419 atp->atp_attr.nif = pip->pif_nif;
420 break;
423 if (atp->atp_attr.nif == NULL)
424 return (ENXIO);
428 * Set supplied connection attributes
430 atp->atp_attr.called.tag = T_ATM_PRESENT;
431 KM_COPY(&sapadr->address_format, &atp->atp_attr.called.addr,
432 sizeof(Atm_addr));
434 atp->atp_attr.blli.tag_l2 = sapl2->SVE_tag;
435 if (sapl2->SVE_tag == T_ATM_PRESENT) {
436 atp->atp_attr.blli.v.layer_2_protocol.ID_type = sapl2->ID_type;
437 KM_COPY(&sapl2->ID, &atp->atp_attr.blli.v.layer_2_protocol.ID,
438 sizeof(atp->atp_attr.blli.v.layer_2_protocol.ID));
441 atp->atp_attr.blli.tag_l3 = sapl3->SVE_tag;
442 if (sapl3->SVE_tag == T_ATM_PRESENT) {
443 atp->atp_attr.blli.v.layer_3_protocol.ID_type = sapl3->ID_type;
444 KM_COPY(&sapl3->ID, &atp->atp_attr.blli.v.layer_3_protocol.ID,
445 sizeof(atp->atp_attr.blli.v.layer_3_protocol.ID));
448 atp->atp_attr.bhli.tag = sapapl->SVE_tag;
449 if (sapapl->SVE_tag == T_ATM_PRESENT) {
450 atp->atp_attr.bhli.v.ID_type = sapapl->ID_type;
451 KM_COPY(&sapapl->ID, &atp->atp_attr.bhli.v.ID,
452 sizeof(atp->atp_attr.bhli.v.ID));
456 * We're finally ready to initiate the ATM connection
458 soisconnecting(so);
459 atm_sock_stat.as_connreq[atp->atp_type]++;
460 err = atm_cm_connect(epp, atp, &atp->atp_attr, &atp->atp_conn);
461 if (err == 0) {
463 * Connection is setup
465 atm_sock_stat.as_conncomp[atp->atp_type]++;
466 soisconnected(so);
468 } else if (err == EINPROGRESS) {
470 * We've got to wait for a connected event
472 err = 0;
474 } else {
476 * Call failed...
478 atm_sock_stat.as_connfail[atp->atp_type]++;
479 soisdisconnected(so);
482 return (err);
487 * Disconnect connected socket
489 * Called at splnet.
491 * Arguments:
492 * so pointer to socket
494 * Returns:
495 * 0 request processed
496 * errno error processing request - reason indicated
500 atm_sock_disconnect(struct socket *so)
502 Atm_pcb *atp = sotoatmpcb(so);
503 struct t_atm_cause *cause;
504 int err;
507 * Make sure we're still attached
509 if (atp == NULL)
510 return (ENOTCONN);
513 * Release the ATM connection
515 if (atp->atp_conn) {
516 if (atp->atp_attr.cause.tag == T_ATM_PRESENT)
517 cause = &atp->atp_attr.cause.v;
518 else
519 cause = &atm_sock_cause;
520 err = atm_cm_release(atp->atp_conn, cause);
521 if (err)
522 log(LOG_ERR, "atm_sock_disconnect: release fail (%d)\n",
523 err);
524 atm_sock_stat.as_connrel[atp->atp_type]++;
525 atp->atp_conn = NULL;
528 soisdisconnected(so);
530 return (0);
535 * Retrieve local socket address
537 * Called at splnet.
539 * Arguments:
540 * so pointer to socket
541 * addr pointer to pointer to contain protocol address
543 * Returns:
544 * 0 request processed
545 * errno error processing request - reason indicated
549 atm_sock_sockaddr(struct socket *so, struct sockaddr **addr)
551 struct sockaddr_atm *satm;
552 struct t_atm_sap_addr *saddr;
553 Atm_pcb *atp = sotoatmpcb(so);
556 * Return local interface address, if known
558 satm = KM_ALLOC(sizeof *satm, M_SONAME, M_WAITOK);
560 KM_ZERO(satm, sizeof(*satm));
561 satm->satm_family = AF_ATM;
562 satm->satm_len = sizeof(*satm);
564 saddr = &satm->satm_addr.t_atm_sap_addr;
565 if (atp->atp_attr.nif && atp->atp_attr.nif->nif_pif->pif_siginst) {
566 saddr->SVE_tag_addr = T_ATM_PRESENT;
567 ATM_ADDR_SEL_COPY(
568 &atp->atp_attr.nif->nif_pif->pif_siginst->si_addr,
569 atp->atp_attr.nif->nif_sel, saddr);
570 if (saddr->address_format == T_ATM_ENDSYS_ADDR)
571 saddr->SVE_tag_selector = T_ATM_PRESENT;
572 else
573 saddr->SVE_tag_selector = T_ATM_ABSENT;
574 } else {
575 saddr->SVE_tag_addr = T_ATM_ABSENT;
576 saddr->SVE_tag_selector = T_ATM_ABSENT;
577 saddr->address_format = T_ATM_ABSENT;
579 satm->satm_addr.t_atm_sap_layer2.SVE_tag = T_ATM_ABSENT;
580 satm->satm_addr.t_atm_sap_layer3.SVE_tag = T_ATM_ABSENT;
581 satm->satm_addr.t_atm_sap_appl.SVE_tag = T_ATM_ABSENT;
583 *addr = (struct sockaddr *)satm;
584 return (0);
589 * Retrieve peer socket address
591 * Called at splnet.
593 * Arguments:
594 * so pointer to socket
595 * addr pointer to pointer to contain protocol address
597 * Returns:
598 * 0 request processed
599 * errno error processing request - reason indicated
603 atm_sock_peeraddr(struct socket *so, struct sockaddr **addr)
605 struct sockaddr_atm *satm;
606 struct t_atm_sap_addr *saddr;
607 Atm_pcb *atp = sotoatmpcb(so);
608 Atm_connvc *cvp;
611 * Return remote address, if known
613 satm = KM_ALLOC(sizeof *satm, M_SONAME, M_WAITOK);
615 KM_ZERO(satm, sizeof(*satm));
616 satm->satm_family = AF_ATM;
617 satm->satm_len = sizeof(*satm);
619 saddr = &satm->satm_addr.t_atm_sap_addr;
620 if (so->so_state & SS_ISCONNECTED) {
621 cvp = atp->atp_conn->co_connvc;
622 saddr->SVE_tag_addr = T_ATM_PRESENT;
623 if (cvp->cvc_flags & CVCF_CALLER) {
624 ATM_ADDR_COPY(&cvp->cvc_attr.called.addr, saddr);
625 } else {
626 if (cvp->cvc_attr.calling.tag == T_ATM_PRESENT) {
627 ATM_ADDR_COPY(&cvp->cvc_attr.calling.addr,
628 saddr);
629 } else {
630 saddr->SVE_tag_addr = T_ATM_ABSENT;
631 saddr->address_format = T_ATM_ABSENT;
634 if (saddr->address_format == T_ATM_ENDSYS_ADDR)
635 saddr->SVE_tag_selector = T_ATM_PRESENT;
636 else
637 saddr->SVE_tag_selector = T_ATM_ABSENT;
638 } else {
639 saddr->SVE_tag_addr = T_ATM_ABSENT;
640 saddr->SVE_tag_selector = T_ATM_ABSENT;
641 saddr->address_format = T_ATM_ABSENT;
643 satm->satm_addr.t_atm_sap_layer2.SVE_tag = T_ATM_ABSENT;
644 satm->satm_addr.t_atm_sap_layer3.SVE_tag = T_ATM_ABSENT;
645 satm->satm_addr.t_atm_sap_appl.SVE_tag = T_ATM_ABSENT;
647 *addr = (struct sockaddr *)satm;
648 return (0);
653 * Common setsockopt processing
655 * Called at splnet.
657 * Arguments:
658 * so pointer to socket
659 * sopt pointer to socket option info
660 * atp pointer to ATM PCB
662 * Returns:
663 * 0 request processed
664 * errno error processing request - reason indicated
668 atm_sock_setopt(struct socket *so, struct sockopt *sopt, Atm_pcb *atp)
670 int err = 0;
671 union {
672 struct t_atm_aal5 aal5;
673 struct t_atm_traffic trf;
674 struct t_atm_bearer brr;
675 struct t_atm_bhli bhl;
676 struct t_atm_blli bll;
677 Atm_addr addr;
678 struct t_atm_cause cau;
679 struct t_atm_qos qos;
680 struct t_atm_transit trn;
681 struct t_atm_net_intf nif;
682 struct t_atm_llc llc;
683 struct t_atm_app_name appn;
684 } p;
686 #define MAXVAL(bits) ((1 << bits) - 1)
687 #define MAXMASK(bits) (~MAXVAL(bits))
689 switch (sopt->sopt_name) {
691 case T_ATM_AAL5:
692 err = soopt_to_kbuf(sopt, &p.aal5, sizeof p.aal5, sizeof p.aal5);
693 if (err)
694 break;
695 if ((p.aal5.forward_max_SDU_size != T_ATM_ABSENT) &&
696 (p.aal5.forward_max_SDU_size & MAXMASK(16)))
697 return (EINVAL);
698 if ((p.aal5.backward_max_SDU_size != T_ATM_ABSENT) &&
699 (p.aal5.backward_max_SDU_size & MAXMASK(16)))
700 return (EINVAL);
701 if ((p.aal5.SSCS_type != T_ATM_ABSENT) &&
702 (p.aal5.SSCS_type != T_ATM_NULL) &&
703 (p.aal5.SSCS_type != T_ATM_SSCS_SSCOP_REL) &&
704 (p.aal5.SSCS_type != T_ATM_SSCS_SSCOP_UNREL) &&
705 (p.aal5.SSCS_type != T_ATM_SSCS_FR))
706 return (EINVAL);
708 if ((p.aal5.forward_max_SDU_size == T_ATM_ABSENT) &&
709 (p.aal5.backward_max_SDU_size == T_ATM_ABSENT) &&
710 (p.aal5.SSCS_type == T_ATM_ABSENT))
711 atp->atp_attr.aal.tag = T_ATM_ABSENT;
712 else {
713 atp->atp_attr.aal.tag = T_ATM_PRESENT;
714 atp->atp_attr.aal.type = ATM_AAL5;
715 atp->atp_attr.aal.v.aal5 = p.aal5;
717 break;
719 case T_ATM_TRAFFIC:
720 err = soopt_to_kbuf(sopt, &p.trf, sizeof p.trf, sizeof p.trf);
721 if (err)
722 break;
723 if ((p.trf.forward.PCR_high_priority != T_ATM_ABSENT) &&
724 (p.trf.forward.PCR_high_priority & MAXMASK(24)))
725 return (EINVAL);
726 if (p.trf.forward.PCR_all_traffic & MAXMASK(24))
727 return (EINVAL);
728 if ((p.trf.forward.SCR_high_priority != T_ATM_ABSENT) &&
729 (p.trf.forward.SCR_high_priority & MAXMASK(24)))
730 return (EINVAL);
731 if ((p.trf.forward.SCR_all_traffic != T_ATM_ABSENT) &&
732 (p.trf.forward.SCR_all_traffic & MAXMASK(24)))
733 return (EINVAL);
734 if ((p.trf.forward.MBS_high_priority != T_ATM_ABSENT) &&
735 (p.trf.forward.MBS_high_priority & MAXMASK(24)))
736 return (EINVAL);
737 if ((p.trf.forward.MBS_all_traffic != T_ATM_ABSENT) &&
738 (p.trf.forward.MBS_all_traffic & MAXMASK(24)))
739 return (EINVAL);
740 if ((p.trf.forward.tagging != T_YES) &&
741 (p.trf.forward.tagging != T_NO))
742 return (EINVAL);
744 if ((p.trf.backward.PCR_high_priority != T_ATM_ABSENT) &&
745 (p.trf.backward.PCR_high_priority & MAXMASK(24)))
746 return (EINVAL);
747 if (p.trf.backward.PCR_all_traffic & MAXMASK(24))
748 return (EINVAL);
749 if ((p.trf.backward.SCR_high_priority != T_ATM_ABSENT) &&
750 (p.trf.backward.SCR_high_priority & MAXMASK(24)))
751 return (EINVAL);
752 if ((p.trf.backward.SCR_all_traffic != T_ATM_ABSENT) &&
753 (p.trf.backward.SCR_all_traffic & MAXMASK(24)))
754 return (EINVAL);
755 if ((p.trf.backward.MBS_high_priority != T_ATM_ABSENT) &&
756 (p.trf.backward.MBS_high_priority & MAXMASK(24)))
757 return (EINVAL);
758 if ((p.trf.backward.MBS_all_traffic != T_ATM_ABSENT) &&
759 (p.trf.backward.MBS_all_traffic & MAXMASK(24)))
760 return (EINVAL);
761 if ((p.trf.backward.tagging != T_YES) &&
762 (p.trf.backward.tagging != T_NO))
763 return (EINVAL);
764 if ((p.trf.best_effort != T_YES) &&
765 (p.trf.best_effort != T_NO))
766 return (EINVAL);
768 atp->atp_attr.traffic.tag = T_ATM_PRESENT;
769 atp->atp_attr.traffic.v = p.trf;
770 break;
772 case T_ATM_BEARER_CAP:
773 err = soopt_to_kbuf(sopt, &p.brr, sizeof p.brr, sizeof p.brr);
774 if (err)
775 break;
776 if ((p.brr.bearer_class != T_ATM_CLASS_A) &&
777 (p.brr.bearer_class != T_ATM_CLASS_C) &&
778 (p.brr.bearer_class != T_ATM_CLASS_X))
779 return (EINVAL);
780 if ((p.brr.traffic_type != T_ATM_NULL) &&
781 (p.brr.traffic_type != T_ATM_CBR) &&
782 (p.brr.traffic_type != T_ATM_VBR))
783 return (EINVAL);
784 if ((p.brr.timing_requirements != T_ATM_NULL) &&
785 (p.brr.timing_requirements != T_ATM_END_TO_END) &&
786 (p.brr.timing_requirements != T_ATM_NO_END_TO_END))
787 return (EINVAL);
788 if ((p.brr.clipping_susceptibility != T_NO) &&
789 (p.brr.clipping_susceptibility != T_YES))
790 return (EINVAL);
791 if ((p.brr.connection_configuration != T_ATM_1_TO_1) &&
792 (p.brr.connection_configuration != T_ATM_1_TO_MANY))
793 return (EINVAL);
795 atp->atp_attr.bearer.tag = T_ATM_PRESENT;
796 atp->atp_attr.bearer.v = p.brr;
797 break;
799 case T_ATM_BHLI:
800 err = soopt_to_kbuf(sopt, &p.bhl, sizeof p.bhl, sizeof p.bhl);
801 if (err)
802 break;
803 if ((p.bhl.ID_type != T_ATM_ABSENT) &&
804 (p.bhl.ID_type != T_ATM_ISO_APP_ID) &&
805 (p.bhl.ID_type != T_ATM_USER_APP_ID) &&
806 (p.bhl.ID_type != T_ATM_VENDOR_APP_ID))
807 return (EINVAL);
809 if (p.bhl.ID_type == T_ATM_ABSENT)
810 atp->atp_attr.bhli.tag = T_ATM_ABSENT;
811 else {
812 atp->atp_attr.bhli.tag = T_ATM_PRESENT;
813 atp->atp_attr.bhli.v = p.bhl;
815 break;
817 case T_ATM_BLLI:
818 err = soopt_to_kbuf(sopt, &p.bll, sizeof p.bll, sizeof p.bll);
819 if (err)
820 break;
821 if ((p.bll.layer_2_protocol.ID_type != T_ATM_ABSENT) &&
822 (p.bll.layer_2_protocol.ID_type != T_ATM_SIMPLE_ID) &&
823 (p.bll.layer_2_protocol.ID_type != T_ATM_USER_ID))
824 return (EINVAL);
825 if ((p.bll.layer_2_protocol.mode != T_ATM_ABSENT) &&
826 (p.bll.layer_2_protocol.mode != T_ATM_BLLI_NORMAL_MODE) &&
827 (p.bll.layer_2_protocol.mode != T_ATM_BLLI_EXTENDED_MODE))
828 return (EINVAL);
829 if ((p.bll.layer_2_protocol.window_size != T_ATM_ABSENT) &&
830 (p.bll.layer_2_protocol.window_size < 1))
831 return (EINVAL);
833 if ((p.bll.layer_3_protocol.ID_type != T_ATM_ABSENT) &&
834 (p.bll.layer_3_protocol.ID_type != T_ATM_SIMPLE_ID) &&
835 (p.bll.layer_3_protocol.ID_type != T_ATM_IPI_ID) &&
836 (p.bll.layer_3_protocol.ID_type != T_ATM_SNAP_ID) &&
837 (p.bll.layer_3_protocol.ID_type != T_ATM_USER_ID))
838 return (EINVAL);
839 if ((p.bll.layer_3_protocol.mode != T_ATM_ABSENT) &&
840 (p.bll.layer_3_protocol.mode != T_ATM_BLLI_NORMAL_MODE) &&
841 (p.bll.layer_3_protocol.mode != T_ATM_BLLI_EXTENDED_MODE))
842 return (EINVAL);
843 if ((p.bll.layer_3_protocol.packet_size != T_ATM_ABSENT) &&
844 (p.bll.layer_3_protocol.packet_size & MAXMASK(4)))
845 return (EINVAL);
846 if ((p.bll.layer_3_protocol.window_size != T_ATM_ABSENT) &&
847 (p.bll.layer_3_protocol.window_size < 1))
848 return (EINVAL);
850 if (p.bll.layer_2_protocol.ID_type == T_ATM_ABSENT)
851 atp->atp_attr.blli.tag_l2 = T_ATM_ABSENT;
852 else
853 atp->atp_attr.blli.tag_l2 = T_ATM_PRESENT;
855 if (p.bll.layer_3_protocol.ID_type == T_ATM_ABSENT)
856 atp->atp_attr.blli.tag_l3 = T_ATM_ABSENT;
857 else
858 atp->atp_attr.blli.tag_l3 = T_ATM_PRESENT;
860 if ((atp->atp_attr.blli.tag_l2 == T_ATM_PRESENT) ||
861 (atp->atp_attr.blli.tag_l3 == T_ATM_PRESENT))
862 atp->atp_attr.blli.v = p.bll;
863 break;
865 case T_ATM_DEST_ADDR:
866 err = soopt_to_kbuf(sopt, &p.addr, sizeof p.addr, sizeof p.addr);
867 if (err)
868 break;
869 if ((p.addr.address_format != T_ATM_ENDSYS_ADDR) &&
870 (p.addr.address_format != T_ATM_E164_ADDR))
871 return (EINVAL);
872 if (p.addr.address_length > ATM_ADDR_LEN)
873 return (EINVAL);
875 atp->atp_attr.called.tag = T_ATM_PRESENT;
876 atp->atp_attr.called.addr = p.addr;
877 break;
879 case T_ATM_DEST_SUB:
880 err = soopt_to_kbuf(sopt, &p.addr, sizeof p.addr, sizeof p.addr);
881 if (err)
882 break;
883 if ((p.addr.address_format != T_ATM_ABSENT) &&
884 (p.addr.address_format != T_ATM_NSAP_ADDR))
885 return (EINVAL);
886 if (p.addr.address_length > ATM_ADDR_LEN)
887 return (EINVAL);
889 /* T_ATM_DEST_ADDR controls tag */
890 atp->atp_attr.called.subaddr = p.addr;
891 break;
893 case T_ATM_ORIG_ADDR:
894 return (EACCES);
896 case T_ATM_ORIG_SUB:
897 return (EACCES);
899 case T_ATM_CALLER_ID:
900 return (EACCES);
902 case T_ATM_CAUSE:
903 err = soopt_to_kbuf(sopt, &p.cau, sizeof p.cau, sizeof p.cau);
904 if (err)
905 break;
906 if ((p.cau.coding_standard != T_ATM_ABSENT) &&
907 (p.cau.coding_standard != T_ATM_ITU_CODING) &&
908 (p.cau.coding_standard != T_ATM_NETWORK_CODING))
909 return (EINVAL);
910 if ((p.cau.location != T_ATM_LOC_USER) &&
911 (p.cau.location != T_ATM_LOC_LOCAL_PRIVATE_NET) &&
912 (p.cau.location != T_ATM_LOC_LOCAL_PUBLIC_NET) &&
913 (p.cau.location != T_ATM_LOC_TRANSIT_NET) &&
914 (p.cau.location != T_ATM_LOC_REMOTE_PUBLIC_NET) &&
915 (p.cau.location != T_ATM_LOC_REMOTE_PRIVATE_NET) &&
916 (p.cau.location != T_ATM_LOC_INTERNATIONAL_NET) &&
917 (p.cau.location != T_ATM_LOC_BEYOND_INTERWORKING))
918 return (EINVAL);
920 if (p.cau.coding_standard == T_ATM_ABSENT)
921 atp->atp_attr.cause.tag = T_ATM_ABSENT;
922 else {
923 atp->atp_attr.cause.tag = T_ATM_PRESENT;
924 atp->atp_attr.cause.v = p.cau;
926 break;
928 case T_ATM_QOS:
929 err = soopt_to_kbuf(sopt, &p.qos, sizeof p.qos, sizeof p.qos);
930 if (err)
931 break;
932 if ((p.qos.coding_standard != T_ATM_ABSENT) &&
933 (p.qos.coding_standard != T_ATM_ITU_CODING) &&
934 (p.qos.coding_standard != T_ATM_NETWORK_CODING))
935 return (EINVAL);
936 if ((p.qos.forward.qos_class != T_ATM_QOS_CLASS_0) &&
937 (p.qos.forward.qos_class != T_ATM_QOS_CLASS_1) &&
938 (p.qos.forward.qos_class != T_ATM_QOS_CLASS_2) &&
939 (p.qos.forward.qos_class != T_ATM_QOS_CLASS_3) &&
940 (p.qos.forward.qos_class != T_ATM_QOS_CLASS_4))
941 return (EINVAL);
942 if ((p.qos.backward.qos_class != T_ATM_QOS_CLASS_0) &&
943 (p.qos.backward.qos_class != T_ATM_QOS_CLASS_1) &&
944 (p.qos.backward.qos_class != T_ATM_QOS_CLASS_2) &&
945 (p.qos.backward.qos_class != T_ATM_QOS_CLASS_3) &&
946 (p.qos.backward.qos_class != T_ATM_QOS_CLASS_4))
947 return (EINVAL);
949 if (p.qos.coding_standard == T_ATM_ABSENT)
950 atp->atp_attr.qos.tag = T_ATM_ABSENT;
951 else {
952 atp->atp_attr.qos.tag = T_ATM_PRESENT;
953 atp->atp_attr.qos.v = p.qos;
955 break;
957 case T_ATM_TRANSIT:
958 err = soopt_to_kbuf(sopt, &p.trn, sizeof p.trn, sizeof p.trn);
959 if (err)
960 break;
961 if (p.trn.length > T_ATM_MAX_NET_ID)
962 return (EINVAL);
964 if (p.trn.length == 0)
965 atp->atp_attr.transit.tag = T_ATM_ABSENT;
966 else {
967 atp->atp_attr.transit.tag = T_ATM_PRESENT;
968 atp->atp_attr.transit.v = p.trn;
970 break;
972 case T_ATM_ADD_LEAF:
973 return (EPROTONOSUPPORT); /* XXX */
975 case T_ATM_DROP_LEAF:
976 return (EPROTONOSUPPORT); /* XXX */
978 case T_ATM_NET_INTF:
979 err = soopt_to_kbuf(sopt, &p.nif, sizeof p.nif, sizeof p.nif);
980 if (err)
981 break;
983 atp->atp_attr.nif = atm_nifname(p.nif.net_intf);
984 if (atp->atp_attr.nif == NULL)
985 return (ENXIO);
986 break;
988 case T_ATM_LLC:
989 err = soopt_to_kbuf(sopt, &p.llc, sizeof p.llc, sizeof p.llc);
990 if (err)
991 break;
992 if ((p.llc.llc_len < T_ATM_LLC_MIN_LEN) ||
993 (p.llc.llc_len > T_ATM_LLC_MAX_LEN))
994 return (EINVAL);
996 atp->atp_attr.llc.tag = T_ATM_PRESENT;
997 atp->atp_attr.llc.v = p.llc;
998 break;
1000 case T_ATM_APP_NAME:
1001 err = soopt_to_kbuf(sopt, &p.appn, sizeof p.appn, sizeof p.appn);
1002 if (err)
1003 break;
1005 strncpy(atp->atp_name, p.appn.app_name, T_ATM_APP_NAME_LEN);
1006 break;
1008 default:
1009 return (ENOPROTOOPT);
1012 return (err);
1017 * Common getsockopt processing
1019 * Called at splnet.
1021 * Arguments:
1022 * so pointer to socket
1023 * sopt pointer to socket option info
1024 * atp pointer to ATM PCB
1026 * Returns:
1027 * 0 request processed
1028 * errno error processing request - reason indicated
1032 atm_sock_getopt(struct socket *so, struct sockopt *sopt, Atm_pcb *atp)
1034 Atm_attributes *ap;
1037 * If socket is connected, return attributes for the VCC in use,
1038 * otherwise just return what the user has setup so far.
1040 if (so->so_state & SS_ISCONNECTED)
1041 ap = &atp->atp_conn->co_connvc->cvc_attr;
1042 else
1043 ap = &atp->atp_attr;
1045 switch (sopt->sopt_name) {
1047 case T_ATM_AAL5:
1048 if ((ap->aal.tag == T_ATM_PRESENT) &&
1049 (ap->aal.type == ATM_AAL5)) {
1050 soopt_from_kbuf(sopt, &ap->aal.v.aal5,
1051 sizeof ap->aal.v.aal5);
1052 return 0;
1053 } else {
1054 return (ENOENT);
1056 break;
1058 case T_ATM_TRAFFIC:
1059 if (ap->traffic.tag == T_ATM_PRESENT) {
1060 soopt_from_kbuf(sopt, &ap->traffic.v,
1061 sizeof ap->traffic.v);
1062 return 0;
1063 } else {
1064 return (ENOENT);
1066 break;
1068 case T_ATM_BEARER_CAP:
1069 if (ap->bearer.tag == T_ATM_PRESENT) {
1070 soopt_from_kbuf(sopt, &ap->bearer.v,
1071 sizeof ap->bearer.v);
1072 return 0;
1073 } else {
1074 return (ENOENT);
1076 break;
1078 case T_ATM_BHLI:
1079 if (ap->bhli.tag == T_ATM_PRESENT) {
1080 soopt_from_kbuf(sopt, &ap->bhli.v,
1081 sizeof ap->bhli.v);
1082 return 0;
1083 } else {
1084 return (ENOENT);
1086 break;
1088 case T_ATM_BLLI:
1089 if ((ap->blli.tag_l2 == T_ATM_PRESENT) ||
1090 (ap->blli.tag_l3 == T_ATM_PRESENT)) {
1091 soopt_from_kbuf(sopt, &ap->blli.v,
1092 sizeof ap->blli.v);
1093 return 0;
1094 } else {
1095 return (ENOENT);
1097 break;
1099 case T_ATM_DEST_ADDR:
1100 if (ap->called.tag == T_ATM_PRESENT) {
1101 soopt_from_kbuf(sopt, &ap->called.addr,
1102 sizeof ap->called.addr);
1103 return 0;
1104 } else {
1105 return (ENOENT);
1107 break;
1109 case T_ATM_DEST_SUB:
1110 if (ap->called.tag == T_ATM_PRESENT) {
1111 soopt_from_kbuf(sopt, &ap->called.subaddr,
1112 sizeof ap->called.subaddr);
1113 return 0;
1114 } else {
1115 return (ENOENT);
1117 break;
1119 case T_ATM_ORIG_ADDR:
1120 if (ap->calling.tag == T_ATM_PRESENT) {
1121 soopt_from_kbuf(sopt, &ap->calling.addr,
1122 sizeof ap->calling.addr);
1123 return 0;
1124 } else {
1125 return (ENOENT);
1127 break;
1129 case T_ATM_ORIG_SUB:
1130 if (ap->calling.tag == T_ATM_PRESENT) {
1131 soopt_from_kbuf(sopt, &ap->calling.subaddr,
1132 sizeof ap->calling.subaddr);
1133 return 0;
1134 } else {
1135 return (ENOENT);
1137 break;
1139 case T_ATM_CALLER_ID:
1140 if (ap->calling.tag == T_ATM_PRESENT) {
1141 soopt_from_kbuf(sopt, &ap->calling.cid,
1142 sizeof ap->calling.cid);
1143 return 0;
1144 } else {
1145 return (ENOENT);
1147 break;
1149 case T_ATM_CAUSE:
1150 if (ap->cause.tag == T_ATM_PRESENT) {
1151 soopt_from_kbuf(sopt, &ap->cause.v,
1152 sizeof ap->cause.v);
1153 return 0;
1154 } else {
1155 return (ENOENT);
1157 break;
1159 case T_ATM_QOS:
1160 if (ap->qos.tag == T_ATM_PRESENT) {
1161 soopt_from_kbuf(sopt, &ap->qos.v,
1162 sizeof ap->qos.v);
1163 return 0;
1164 } else {
1165 return (ENOENT);
1167 break;
1169 case T_ATM_TRANSIT:
1170 if (ap->transit.tag == T_ATM_PRESENT) {
1171 soopt_from_kbuf(sopt, &ap->transit.v,
1172 sizeof ap->transit.v);
1173 return 0;
1174 } else {
1175 return (ENOENT);
1177 break;
1179 case T_ATM_LEAF_IND:
1180 return (EPROTONOSUPPORT); /* XXX */
1182 case T_ATM_NET_INTF:
1183 if (ap->nif) {
1184 struct t_atm_net_intf netif;
1185 struct ifnet *ifp;
1187 ifp = &ap->nif->nif_if;
1188 ksnprintf(netif.net_intf, sizeof(netif.net_intf),
1189 "%s", ifp->if_xname);
1190 soopt_from_kbuf(sopt, &netif,
1191 sizeof netif);
1192 return 0;
1193 } else {
1194 return (ENOENT);
1196 break;
1198 case T_ATM_LLC:
1199 if (ap->llc.tag == T_ATM_PRESENT) {
1200 soopt_from_kbuf(sopt, &ap->llc.v,
1201 sizeof ap->llc.v);
1202 return 0;
1203 } else {
1204 return (ENOENT);
1206 break;
1208 default:
1209 return (ENOPROTOOPT);
1212 return (0);
1217 * Process Socket VCC Connected Notification
1219 * Arguments:
1220 * toku owner's connection token (atm_pcb protocol block)
1222 * Returns:
1223 * none
1226 void
1227 atm_sock_connected(void *toku)
1229 Atm_pcb *atp = (Atm_pcb *)toku;
1232 * Connection is setup
1234 atm_sock_stat.as_conncomp[atp->atp_type]++;
1235 soisconnected(atp->atp_socket);
1240 * Process Socket VCC Cleared Notification
1242 * Arguments:
1243 * toku owner's connection token (atm_pcb protocol block)
1244 * cause pointer to cause code
1246 * Returns:
1247 * none
1250 void
1251 atm_sock_cleared(void *toku, struct t_atm_cause *cause)
1253 Atm_pcb *atp = (Atm_pcb *)toku;
1254 struct socket *so;
1256 so = atp->atp_socket;
1259 * Save call clearing cause
1261 atp->atp_attr.cause.tag = T_ATM_PRESENT;
1262 atp->atp_attr.cause.v = *cause;
1265 * Set user error code
1267 if (so->so_state & SS_ISCONNECTED) {
1268 so->so_error = ECONNRESET;
1269 atm_sock_stat.as_connclr[atp->atp_type]++;
1270 } else {
1271 so->so_error = ECONNREFUSED;
1272 atm_sock_stat.as_connfail[atp->atp_type]++;
1276 * Connection is gone
1278 atp->atp_conn = NULL;
1279 soisdisconnected(so);
1282 * Cleanup failed incoming connection setup
1284 if (so->so_state & SS_NOFDREF) {
1285 atm_sock_detach(so);