2 * ===================================
3 * HARP | Host ATM Research Platform
4 * ===================================
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.
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.
20 * Copyright 1994-1998 Network Computing Services, Inc.
22 * Copies of this Software may be made, however, the above copyright
23 * notice must be reproduced on all copies.
30 * ATM common socket protocol processing
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
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>
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>
64 static uma_zone_t atm_pcb_zone;
66 static struct t_atm_cause atm_sock_cause = {
69 T_ATM_CAUSE_UNSPECIFIED_NORMAL,
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");
84 * Allocate resources for a new ATM socket
89 * so pointer to socket
90 * send socket send buffer maximum
91 * recv socket receive buffer maximum
95 * errno attach failed - reason indicated
99 atm_sock_attach(so, send, recv)
104 Atm_pcb *atp = sotoatmpcb(so);
108 * Make sure initialization has happened
114 * Make sure we're not already attached
120 * Reserve socket buffer space, if not already done
122 if ((so->so_snd.sb_hiwat == 0) || (so->so_rcv.sb_hiwat == 0)) {
123 err = soreserve(so, send, recv);
129 * Allocate and initialize our control block
131 atp = uma_zalloc(atm_pcb_zone, M_ZERO | M_NOWAIT);
135 atp->atp_socket = so;
136 so->so_pcb = (caddr_t)atp;
142 * Detach from socket and free resources
147 * so pointer to socket
154 Atm_pcb *atp = sotoatmpcb(so);
157 * Make sure we're still attached
159 KASSERT(atp != NULL, ("atm_sock_detach: atp == NULL"));
162 * Terminate any (possibly pending) connection
165 (void) atm_sock_disconnect(so);
170 uma_zfree(atm_pcb_zone, atp);
175 * Bind local address to socket
180 * so pointer to socket
181 * addr pointer to protocol address
184 * 0 request processed
185 * errno error processing request - reason indicated
189 atm_sock_bind(so, addr)
191 struct sockaddr *addr;
193 Atm_pcb *atp = sotoatmpcb(so);
195 struct sockaddr_atm *satm;
196 struct t_atm_sap_addr *sapadr;
197 struct t_atm_sap_layer2 *sapl2;
198 struct t_atm_sap_layer3 *sapl3;
199 struct t_atm_sap_appl *sapapl;
202 * Make sure we're still attached
208 * Can't change local address once we've started connection process
210 if (atp->atp_conn != NULL)
211 return (EADDRNOTAVAIL);
214 * Validate requested local address
216 satm = (struct sockaddr_atm *)addr;
217 if (satm->satm_family != AF_ATM)
218 return (EAFNOSUPPORT);
220 sapadr = &satm->satm_addr.t_atm_sap_addr;
221 if (sapadr->SVE_tag_addr == T_ATM_PRESENT) {
222 if (sapadr->address_format == T_ATM_ENDSYS_ADDR) {
223 if (sapadr->SVE_tag_selector != T_ATM_PRESENT)
225 } else if (sapadr->address_format == T_ATM_E164_ADDR) {
226 if (sapadr->SVE_tag_selector != T_ATM_ABSENT)
230 } else if ((sapadr->SVE_tag_addr != T_ATM_ABSENT) &&
231 (sapadr->SVE_tag_addr != T_ATM_ANY))
233 if (sapadr->address_length > ATM_ADDR_LEN)
236 sapl2 = &satm->satm_addr.t_atm_sap_layer2;
237 if (sapl2->SVE_tag == T_ATM_PRESENT) {
238 if ((sapl2->ID_type != T_ATM_SIMPLE_ID) &&
239 (sapl2->ID_type != T_ATM_USER_ID))
241 } else if ((sapl2->SVE_tag != T_ATM_ABSENT) &&
242 (sapl2->SVE_tag != T_ATM_ANY))
245 sapl3 = &satm->satm_addr.t_atm_sap_layer3;
246 if (sapl3->SVE_tag == T_ATM_PRESENT) {
247 if ((sapl3->ID_type != T_ATM_SIMPLE_ID) &&
248 (sapl3->ID_type != T_ATM_IPI_ID) &&
249 (sapl3->ID_type != T_ATM_SNAP_ID) &&
250 (sapl3->ID_type != T_ATM_USER_ID))
252 } else if ((sapl3->SVE_tag != T_ATM_ABSENT) &&
253 (sapl3->SVE_tag != T_ATM_ANY))
256 sapapl = &satm->satm_addr.t_atm_sap_appl;
257 if (sapapl->SVE_tag == T_ATM_PRESENT) {
258 if ((sapapl->ID_type != T_ATM_ISO_APP_ID) &&
259 (sapapl->ID_type != T_ATM_USER_APP_ID) &&
260 (sapapl->ID_type != T_ATM_VENDOR_APP_ID))
262 } else if ((sapapl->SVE_tag != T_ATM_ABSENT) &&
263 (sapapl->SVE_tag != T_ATM_ANY))
267 * Create temporary attributes list so that we can check out the
268 * new bind parameters before we modify the socket's values;
270 attr = atp->atp_attr;
271 attr.called.tag = sapadr->SVE_tag_addr;
272 bcopy(&sapadr->address_format, &attr.called.addr, sizeof(Atm_addr));
274 attr.blli.tag_l2 = sapl2->SVE_tag;
275 if (sapl2->SVE_tag == T_ATM_PRESENT) {
276 attr.blli.v.layer_2_protocol.ID_type = sapl2->ID_type;
277 bcopy(&sapl2->ID, &attr.blli.v.layer_2_protocol.ID,
278 sizeof(attr.blli.v.layer_2_protocol.ID));
281 attr.blli.tag_l3 = sapl3->SVE_tag;
282 if (sapl3->SVE_tag == T_ATM_PRESENT) {
283 attr.blli.v.layer_3_protocol.ID_type = sapl3->ID_type;
284 bcopy(&sapl3->ID, &attr.blli.v.layer_3_protocol.ID,
285 sizeof(attr.blli.v.layer_3_protocol.ID));
288 attr.bhli.tag = sapapl->SVE_tag;
289 if (sapapl->SVE_tag == T_ATM_PRESENT) {
290 attr.bhli.v.ID_type = sapapl->ID_type;
291 bcopy(&sapapl->ID, &attr.bhli.v.ID,
292 sizeof(attr.bhli.v.ID));
296 * Make sure we have unique listening attributes
298 if (atm_cm_match(&attr, NULL) != NULL)
302 * Looks good, save new attributes
304 atp->atp_attr = attr;
311 * Listen for incoming connections
316 * so pointer to socket
317 * epp pointer to endpoint definition structure
320 * 0 request processed
321 * errno error processing request - reason indicated
325 atm_sock_listen(so, epp, backlog)
330 Atm_pcb *atp = sotoatmpcb(so);
333 * Make sure we're still attached
339 * Start listening for incoming calls
341 return (atm_cm_listen(so, epp, atp, &atp->atp_attr, &atp->atp_conn,
347 * Connect socket to peer
352 * so pointer to socket
353 * addr pointer to protocol address
354 * epp pointer to endpoint definition structure
357 * 0 request processed
358 * errno error processing request - reason indicated
362 atm_sock_connect(so, addr, epp)
364 struct sockaddr *addr;
367 Atm_pcb *atp = sotoatmpcb(so);
368 struct sockaddr_atm *satm;
369 struct t_atm_sap_addr *sapadr;
370 struct t_atm_sap_layer2 *sapl2;
371 struct t_atm_sap_layer3 *sapl3;
372 struct t_atm_sap_appl *sapapl;
376 * Make sure we're still attached
382 * Validate requested peer address
384 satm = (struct sockaddr_atm *)addr;
385 if (satm->satm_family != AF_ATM)
386 return (EAFNOSUPPORT);
388 sapadr = &satm->satm_addr.t_atm_sap_addr;
389 if (sapadr->SVE_tag_addr != T_ATM_PRESENT)
391 if (sapadr->address_format == T_ATM_ENDSYS_ADDR) {
392 if (sapadr->SVE_tag_selector != T_ATM_PRESENT)
394 } else if (sapadr->address_format == T_ATM_E164_ADDR) {
395 if (sapadr->SVE_tag_selector != T_ATM_ABSENT)
397 } else if (sapadr->address_format == T_ATM_PVC_ADDR) {
398 if (sapadr->SVE_tag_selector != T_ATM_ABSENT)
402 if (sapadr->address_length > ATM_ADDR_LEN)
405 sapl2 = &satm->satm_addr.t_atm_sap_layer2;
406 if (sapl2->SVE_tag == T_ATM_PRESENT) {
407 if ((sapl2->ID_type != T_ATM_SIMPLE_ID) &&
408 (sapl2->ID_type != T_ATM_USER_ID))
410 } else if (sapl2->SVE_tag != T_ATM_ABSENT)
413 sapl3 = &satm->satm_addr.t_atm_sap_layer3;
414 if (sapl3->SVE_tag == T_ATM_PRESENT) {
415 if ((sapl3->ID_type != T_ATM_SIMPLE_ID) &&
416 (sapl3->ID_type != T_ATM_IPI_ID) &&
417 (sapl3->ID_type != T_ATM_SNAP_ID) &&
418 (sapl3->ID_type != T_ATM_USER_ID))
420 } else if (sapl3->SVE_tag != T_ATM_ABSENT)
423 sapapl = &satm->satm_addr.t_atm_sap_appl;
424 if (sapapl->SVE_tag == T_ATM_PRESENT) {
425 if ((sapapl->ID_type != T_ATM_ISO_APP_ID) &&
426 (sapapl->ID_type != T_ATM_USER_APP_ID) &&
427 (sapapl->ID_type != T_ATM_VENDOR_APP_ID))
429 } else if (sapapl->SVE_tag != T_ATM_ABSENT)
433 * Select an outgoing network interface
435 if (atp->atp_attr.nif == NULL) {
438 for (pip = atm_interface_head; pip != NULL;
439 pip = pip->pif_next) {
440 if (pip->pif_nif != NULL) {
441 atp->atp_attr.nif = pip->pif_nif;
445 if (atp->atp_attr.nif == NULL)
450 * Set supplied connection attributes
452 atp->atp_attr.called.tag = T_ATM_PRESENT;
453 bcopy(&sapadr->address_format, &atp->atp_attr.called.addr,
456 atp->atp_attr.blli.tag_l2 = sapl2->SVE_tag;
457 if (sapl2->SVE_tag == T_ATM_PRESENT) {
458 atp->atp_attr.blli.v.layer_2_protocol.ID_type = sapl2->ID_type;
459 bcopy(&sapl2->ID, &atp->atp_attr.blli.v.layer_2_protocol.ID,
460 sizeof(atp->atp_attr.blli.v.layer_2_protocol.ID));
463 atp->atp_attr.blli.tag_l3 = sapl3->SVE_tag;
464 if (sapl3->SVE_tag == T_ATM_PRESENT) {
465 atp->atp_attr.blli.v.layer_3_protocol.ID_type = sapl3->ID_type;
466 bcopy(&sapl3->ID, &atp->atp_attr.blli.v.layer_3_protocol.ID,
467 sizeof(atp->atp_attr.blli.v.layer_3_protocol.ID));
470 atp->atp_attr.bhli.tag = sapapl->SVE_tag;
471 if (sapapl->SVE_tag == T_ATM_PRESENT) {
472 atp->atp_attr.bhli.v.ID_type = sapapl->ID_type;
473 bcopy(&sapapl->ID, &atp->atp_attr.bhli.v.ID,
474 sizeof(atp->atp_attr.bhli.v.ID));
478 * We're finally ready to initiate the ATM connection
481 atm_sock_stat.as_connreq[atp->atp_type]++;
482 err = atm_cm_connect(epp, atp, &atp->atp_attr, &atp->atp_conn);
485 * Connection is setup
487 atm_sock_stat.as_conncomp[atp->atp_type]++;
490 } else if (err == EINPROGRESS) {
492 * We've got to wait for a connected event
500 atm_sock_stat.as_connfail[atp->atp_type]++;
501 soisdisconnected(so);
509 * Disconnect connected socket
514 * so pointer to socket
517 * 0 request processed
518 * errno error processing request - reason indicated
522 atm_sock_disconnect(so)
525 Atm_pcb *atp = sotoatmpcb(so);
526 struct t_atm_cause *cause;
530 * Make sure we're still attached
536 * Release the ATM connection
539 if (atp->atp_attr.cause.tag == T_ATM_PRESENT)
540 cause = &atp->atp_attr.cause.v;
542 cause = &atm_sock_cause;
543 err = atm_cm_release(atp->atp_conn, cause);
545 log(LOG_ERR, "atm_sock_disconnect: release fail (%d)\n",
547 atm_sock_stat.as_connrel[atp->atp_type]++;
548 atp->atp_conn = NULL;
551 soisdisconnected(so);
558 * Retrieve local socket address
563 * so pointer to socket
564 * addr pointer to pointer to contain protocol address
567 * 0 request processed
568 * errno error processing request - reason indicated
572 atm_sock_sockaddr(so, addr)
574 struct sockaddr **addr;
576 struct sockaddr_atm *satm;
577 struct t_atm_sap_addr *saddr;
578 Atm_pcb *atp = sotoatmpcb(so);
581 * Return local interface address, if known
583 satm = malloc(sizeof(*satm), M_SONAME, M_WAITOK | M_ZERO);
587 satm->satm_family = AF_ATM;
588 satm->satm_len = sizeof(*satm);
590 saddr = &satm->satm_addr.t_atm_sap_addr;
591 if (atp->atp_attr.nif && atp->atp_attr.nif->nif_pif->pif_siginst) {
592 saddr->SVE_tag_addr = T_ATM_PRESENT;
594 &atp->atp_attr.nif->nif_pif->pif_siginst->si_addr,
595 atp->atp_attr.nif->nif_sel, saddr);
596 if (saddr->address_format == T_ATM_ENDSYS_ADDR)
597 saddr->SVE_tag_selector = T_ATM_PRESENT;
599 saddr->SVE_tag_selector = T_ATM_ABSENT;
601 saddr->SVE_tag_addr = T_ATM_ABSENT;
602 saddr->SVE_tag_selector = T_ATM_ABSENT;
603 saddr->address_format = T_ATM_ABSENT;
605 satm->satm_addr.t_atm_sap_layer2.SVE_tag = T_ATM_ABSENT;
606 satm->satm_addr.t_atm_sap_layer3.SVE_tag = T_ATM_ABSENT;
607 satm->satm_addr.t_atm_sap_appl.SVE_tag = T_ATM_ABSENT;
609 *addr = (struct sockaddr *)satm;
615 * Retrieve peer socket address
620 * so pointer to socket
621 * addr pointer to pointer to contain protocol address
624 * 0 request processed
625 * errno error processing request - reason indicated
629 atm_sock_peeraddr(so, addr)
631 struct sockaddr **addr;
633 struct sockaddr_atm *satm;
634 struct t_atm_sap_addr *saddr;
635 Atm_pcb *atp = sotoatmpcb(so);
639 * Return remote address, if known
641 satm = malloc(sizeof(*satm), M_SONAME, M_WAITOK | M_ZERO);
645 satm->satm_family = AF_ATM;
646 satm->satm_len = sizeof(*satm);
647 saddr = &satm->satm_addr.t_atm_sap_addr;
648 if (so->so_state & SS_ISCONNECTED) {
649 cvp = atp->atp_conn->co_connvc;
650 saddr->SVE_tag_addr = T_ATM_PRESENT;
651 if (cvp->cvc_flags & CVCF_CALLER) {
652 ATM_ADDR_COPY(&cvp->cvc_attr.called.addr, saddr);
654 if (cvp->cvc_attr.calling.tag == T_ATM_PRESENT) {
655 ATM_ADDR_COPY(&cvp->cvc_attr.calling.addr,
658 saddr->SVE_tag_addr = T_ATM_ABSENT;
659 saddr->address_format = T_ATM_ABSENT;
662 if (saddr->address_format == T_ATM_ENDSYS_ADDR)
663 saddr->SVE_tag_selector = T_ATM_PRESENT;
665 saddr->SVE_tag_selector = T_ATM_ABSENT;
667 saddr->SVE_tag_addr = T_ATM_ABSENT;
668 saddr->SVE_tag_selector = T_ATM_ABSENT;
669 saddr->address_format = T_ATM_ABSENT;
671 satm->satm_addr.t_atm_sap_layer2.SVE_tag = T_ATM_ABSENT;
672 satm->satm_addr.t_atm_sap_layer3.SVE_tag = T_ATM_ABSENT;
673 satm->satm_addr.t_atm_sap_appl.SVE_tag = T_ATM_ABSENT;
675 *addr = (struct sockaddr *)satm;
681 * Common setsockopt processing
686 * so pointer to socket
687 * sopt pointer to socket option info
688 * atp pointer to ATM PCB
691 * 0 request processed
692 * errno error processing request - reason indicated
696 atm_sock_setopt(so, sopt, atp)
698 struct sockopt *sopt;
703 struct t_atm_aal5 aal5;
704 struct t_atm_traffic trf;
705 struct t_atm_bearer brr;
706 struct t_atm_bhli bhl;
707 struct t_atm_blli bll;
709 struct t_atm_cause cau;
710 struct t_atm_qos qos;
711 struct t_atm_transit trn;
712 struct t_atm_net_intf nif;
713 struct t_atm_llc llc;
714 struct t_atm_app_name appn;
717 #define MAXVAL(bits) ((1 << bits) - 1)
718 #define MAXMASK(bits) (~MAXVAL(bits))
720 switch (sopt->sopt_name) {
723 err = sooptcopyin(sopt, &p.aal5, sizeof p.aal5, sizeof p.aal5);
726 if ((p.aal5.forward_max_SDU_size != T_ATM_ABSENT) &&
727 (p.aal5.forward_max_SDU_size & MAXMASK(16)))
729 if ((p.aal5.backward_max_SDU_size != T_ATM_ABSENT) &&
730 (p.aal5.backward_max_SDU_size & MAXMASK(16)))
732 if ((p.aal5.SSCS_type != T_ATM_ABSENT) &&
733 (p.aal5.SSCS_type != T_ATM_NULL) &&
734 (p.aal5.SSCS_type != T_ATM_SSCS_SSCOP_REL) &&
735 (p.aal5.SSCS_type != T_ATM_SSCS_SSCOP_UNREL) &&
736 (p.aal5.SSCS_type != T_ATM_SSCS_FR))
739 if ((p.aal5.forward_max_SDU_size == T_ATM_ABSENT) &&
740 (p.aal5.backward_max_SDU_size == T_ATM_ABSENT) &&
741 (p.aal5.SSCS_type == T_ATM_ABSENT))
742 atp->atp_attr.aal.tag = T_ATM_ABSENT;
744 atp->atp_attr.aal.tag = T_ATM_PRESENT;
745 atp->atp_attr.aal.type = ATM_AAL5;
746 atp->atp_attr.aal.v.aal5 = p.aal5;
751 err = sooptcopyin(sopt, &p.trf, sizeof p.trf, sizeof p.trf);
754 if ((p.trf.forward.PCR_high_priority != T_ATM_ABSENT) &&
755 (p.trf.forward.PCR_high_priority & MAXMASK(24)))
757 if (p.trf.forward.PCR_all_traffic & MAXMASK(24))
759 if ((p.trf.forward.SCR_high_priority != T_ATM_ABSENT) &&
760 (p.trf.forward.SCR_high_priority & MAXMASK(24)))
762 if ((p.trf.forward.SCR_all_traffic != T_ATM_ABSENT) &&
763 (p.trf.forward.SCR_all_traffic & MAXMASK(24)))
765 if ((p.trf.forward.MBS_high_priority != T_ATM_ABSENT) &&
766 (p.trf.forward.MBS_high_priority & MAXMASK(24)))
768 if ((p.trf.forward.MBS_all_traffic != T_ATM_ABSENT) &&
769 (p.trf.forward.MBS_all_traffic & MAXMASK(24)))
771 if ((p.trf.forward.tagging != T_YES) &&
772 (p.trf.forward.tagging != T_NO))
775 if ((p.trf.backward.PCR_high_priority != T_ATM_ABSENT) &&
776 (p.trf.backward.PCR_high_priority & MAXMASK(24)))
778 if (p.trf.backward.PCR_all_traffic & MAXMASK(24))
780 if ((p.trf.backward.SCR_high_priority != T_ATM_ABSENT) &&
781 (p.trf.backward.SCR_high_priority & MAXMASK(24)))
783 if ((p.trf.backward.SCR_all_traffic != T_ATM_ABSENT) &&
784 (p.trf.backward.SCR_all_traffic & MAXMASK(24)))
786 if ((p.trf.backward.MBS_high_priority != T_ATM_ABSENT) &&
787 (p.trf.backward.MBS_high_priority & MAXMASK(24)))
789 if ((p.trf.backward.MBS_all_traffic != T_ATM_ABSENT) &&
790 (p.trf.backward.MBS_all_traffic & MAXMASK(24)))
792 if ((p.trf.backward.tagging != T_YES) &&
793 (p.trf.backward.tagging != T_NO))
795 if ((p.trf.best_effort != T_YES) &&
796 (p.trf.best_effort != T_NO))
799 atp->atp_attr.traffic.tag = T_ATM_PRESENT;
800 atp->atp_attr.traffic.v = p.trf;
803 case T_ATM_BEARER_CAP:
804 err = sooptcopyin(sopt, &p.brr, sizeof p.brr, sizeof p.brr);
807 if ((p.brr.bearer_class != T_ATM_CLASS_A) &&
808 (p.brr.bearer_class != T_ATM_CLASS_C) &&
809 (p.brr.bearer_class != T_ATM_CLASS_X))
811 if ((p.brr.traffic_type != T_ATM_NULL) &&
812 (p.brr.traffic_type != T_ATM_CBR) &&
813 (p.brr.traffic_type != T_ATM_VBR) &&
814 (p.brr.traffic_type != T_ATM_ABR) &&
815 (p.brr.traffic_type != T_ATM_UBR))
817 if ((p.brr.timing_requirements != T_ATM_NULL) &&
818 (p.brr.timing_requirements != T_ATM_END_TO_END) &&
819 (p.brr.timing_requirements != T_ATM_NO_END_TO_END))
821 if ((p.brr.clipping_susceptibility != T_NO) &&
822 (p.brr.clipping_susceptibility != T_YES))
824 if ((p.brr.connection_configuration != T_ATM_1_TO_1) &&
825 (p.brr.connection_configuration != T_ATM_1_TO_MANY))
828 atp->atp_attr.bearer.tag = T_ATM_PRESENT;
829 atp->atp_attr.bearer.v = p.brr;
833 err = sooptcopyin(sopt, &p.bhl, sizeof p.bhl, sizeof p.bhl);
836 if ((p.bhl.ID_type != T_ATM_ABSENT) &&
837 (p.bhl.ID_type != T_ATM_ISO_APP_ID) &&
838 (p.bhl.ID_type != T_ATM_USER_APP_ID) &&
839 (p.bhl.ID_type != T_ATM_VENDOR_APP_ID))
842 if (p.bhl.ID_type == T_ATM_ABSENT)
843 atp->atp_attr.bhli.tag = T_ATM_ABSENT;
845 atp->atp_attr.bhli.tag = T_ATM_PRESENT;
846 atp->atp_attr.bhli.v = p.bhl;
851 err = sooptcopyin(sopt, &p.bll, sizeof p.bll, sizeof p.bll);
854 if ((p.bll.layer_2_protocol.ID_type != T_ATM_ABSENT) &&
855 (p.bll.layer_2_protocol.ID_type != T_ATM_SIMPLE_ID) &&
856 (p.bll.layer_2_protocol.ID_type != T_ATM_USER_ID))
858 if ((p.bll.layer_2_protocol.mode != T_ATM_ABSENT) &&
859 (p.bll.layer_2_protocol.mode != T_ATM_BLLI_NORMAL_MODE) &&
860 (p.bll.layer_2_protocol.mode != T_ATM_BLLI_EXTENDED_MODE))
862 if ((p.bll.layer_2_protocol.window_size != T_ATM_ABSENT) &&
863 (p.bll.layer_2_protocol.window_size < 1))
866 if ((p.bll.layer_3_protocol.ID_type != T_ATM_ABSENT) &&
867 (p.bll.layer_3_protocol.ID_type != T_ATM_SIMPLE_ID) &&
868 (p.bll.layer_3_protocol.ID_type != T_ATM_IPI_ID) &&
869 (p.bll.layer_3_protocol.ID_type != T_ATM_SNAP_ID) &&
870 (p.bll.layer_3_protocol.ID_type != T_ATM_USER_ID))
872 if ((p.bll.layer_3_protocol.mode != T_ATM_ABSENT) &&
873 (p.bll.layer_3_protocol.mode != T_ATM_BLLI_NORMAL_MODE) &&
874 (p.bll.layer_3_protocol.mode != T_ATM_BLLI_EXTENDED_MODE))
876 if ((p.bll.layer_3_protocol.packet_size != T_ATM_ABSENT) &&
877 (p.bll.layer_3_protocol.packet_size & MAXMASK(4)))
879 if ((p.bll.layer_3_protocol.window_size != T_ATM_ABSENT) &&
880 (p.bll.layer_3_protocol.window_size < 1))
883 if (p.bll.layer_2_protocol.ID_type == T_ATM_ABSENT)
884 atp->atp_attr.blli.tag_l2 = T_ATM_ABSENT;
886 atp->atp_attr.blli.tag_l2 = T_ATM_PRESENT;
888 if (p.bll.layer_3_protocol.ID_type == T_ATM_ABSENT)
889 atp->atp_attr.blli.tag_l3 = T_ATM_ABSENT;
891 atp->atp_attr.blli.tag_l3 = T_ATM_PRESENT;
893 if ((atp->atp_attr.blli.tag_l2 == T_ATM_PRESENT) ||
894 (atp->atp_attr.blli.tag_l3 == T_ATM_PRESENT))
895 atp->atp_attr.blli.v = p.bll;
898 case T_ATM_DEST_ADDR:
899 err = sooptcopyin(sopt, &p.addr, sizeof p.addr, sizeof p.addr);
902 if ((p.addr.address_format != T_ATM_ENDSYS_ADDR) &&
903 (p.addr.address_format != T_ATM_E164_ADDR))
905 if (p.addr.address_length > ATM_ADDR_LEN)
908 atp->atp_attr.called.tag = T_ATM_PRESENT;
909 atp->atp_attr.called.addr = p.addr;
913 err = sooptcopyin(sopt, &p.addr, sizeof p.addr, sizeof p.addr);
916 if ((p.addr.address_format != T_ATM_ABSENT) &&
917 (p.addr.address_format != T_ATM_NSAP_ADDR))
919 if (p.addr.address_length > ATM_ADDR_LEN)
922 /* T_ATM_DEST_ADDR controls tag */
923 atp->atp_attr.called.subaddr = p.addr;
926 case T_ATM_ORIG_ADDR:
932 case T_ATM_CALLER_ID:
936 err = sooptcopyin(sopt, &p.cau, sizeof p.cau, sizeof p.cau);
939 if ((p.cau.coding_standard != T_ATM_ABSENT) &&
940 (p.cau.coding_standard != T_ATM_ITU_CODING) &&
941 (p.cau.coding_standard != T_ATM_NETWORK_CODING))
943 if ((p.cau.location != T_ATM_LOC_USER) &&
944 (p.cau.location != T_ATM_LOC_LOCAL_PRIVATE_NET) &&
945 (p.cau.location != T_ATM_LOC_LOCAL_PUBLIC_NET) &&
946 (p.cau.location != T_ATM_LOC_TRANSIT_NET) &&
947 (p.cau.location != T_ATM_LOC_REMOTE_PUBLIC_NET) &&
948 (p.cau.location != T_ATM_LOC_REMOTE_PRIVATE_NET) &&
949 (p.cau.location != T_ATM_LOC_INTERNATIONAL_NET) &&
950 (p.cau.location != T_ATM_LOC_BEYOND_INTERWORKING))
953 if (p.cau.coding_standard == T_ATM_ABSENT)
954 atp->atp_attr.cause.tag = T_ATM_ABSENT;
956 atp->atp_attr.cause.tag = T_ATM_PRESENT;
957 atp->atp_attr.cause.v = p.cau;
962 err = sooptcopyin(sopt, &p.qos, sizeof p.qos, sizeof p.qos);
965 if ((p.qos.coding_standard != T_ATM_ABSENT) &&
966 (p.qos.coding_standard != T_ATM_ITU_CODING) &&
967 (p.qos.coding_standard != T_ATM_NETWORK_CODING))
969 if ((p.qos.forward.qos_class != T_ATM_QOS_CLASS_0) &&
970 (p.qos.forward.qos_class != T_ATM_QOS_CLASS_1) &&
971 (p.qos.forward.qos_class != T_ATM_QOS_CLASS_2) &&
972 (p.qos.forward.qos_class != T_ATM_QOS_CLASS_3) &&
973 (p.qos.forward.qos_class != T_ATM_QOS_CLASS_4))
975 if ((p.qos.backward.qos_class != T_ATM_QOS_CLASS_0) &&
976 (p.qos.backward.qos_class != T_ATM_QOS_CLASS_1) &&
977 (p.qos.backward.qos_class != T_ATM_QOS_CLASS_2) &&
978 (p.qos.backward.qos_class != T_ATM_QOS_CLASS_3) &&
979 (p.qos.backward.qos_class != T_ATM_QOS_CLASS_4))
982 if (p.qos.coding_standard == T_ATM_ABSENT)
983 atp->atp_attr.qos.tag = T_ATM_ABSENT;
985 atp->atp_attr.qos.tag = T_ATM_PRESENT;
986 atp->atp_attr.qos.v = p.qos;
991 err = sooptcopyin(sopt, &p.trn, sizeof p.trn, sizeof p.trn);
994 if (p.trn.length > T_ATM_MAX_NET_ID)
997 if (p.trn.length == 0)
998 atp->atp_attr.transit.tag = T_ATM_ABSENT;
1000 atp->atp_attr.transit.tag = T_ATM_PRESENT;
1001 atp->atp_attr.transit.v = p.trn;
1005 case T_ATM_ADD_LEAF:
1006 return (EPROTONOSUPPORT); /* XXX */
1008 case T_ATM_DROP_LEAF:
1009 return (EPROTONOSUPPORT); /* XXX */
1011 case T_ATM_NET_INTF:
1012 err = sooptcopyin(sopt, &p.nif, sizeof p.nif, sizeof p.nif);
1016 atp->atp_attr.nif = atm_nifname(p.nif.net_intf);
1017 if (atp->atp_attr.nif == NULL)
1022 err = sooptcopyin(sopt, &p.llc, sizeof p.llc, sizeof p.llc);
1025 if ((p.llc.llc_len < T_ATM_LLC_MIN_LEN) ||
1026 (p.llc.llc_len > T_ATM_LLC_MAX_LEN))
1029 atp->atp_attr.llc.tag = T_ATM_PRESENT;
1030 atp->atp_attr.llc.v = p.llc;
1033 case T_ATM_APP_NAME:
1034 err = sooptcopyin(sopt, &p.appn, sizeof p.appn, sizeof p.appn);
1038 strncpy(atp->atp_name, p.appn.app_name, T_ATM_APP_NAME_LEN);
1042 return (ENOPROTOOPT);
1050 * Common getsockopt processing
1055 * so pointer to socket
1056 * sopt pointer to socket option info
1057 * atp pointer to ATM PCB
1060 * 0 request processed
1061 * errno error processing request - reason indicated
1065 atm_sock_getopt(so, sopt, atp)
1067 struct sockopt *sopt;
1073 * If socket is connected, return attributes for the VCC in use,
1074 * otherwise just return what the user has setup so far.
1076 if (so->so_state & SS_ISCONNECTED)
1077 ap = &atp->atp_conn->co_connvc->cvc_attr;
1079 ap = &atp->atp_attr;
1081 switch (sopt->sopt_name) {
1084 if ((ap->aal.tag == T_ATM_PRESENT) &&
1085 (ap->aal.type == ATM_AAL5)) {
1086 return (sooptcopyout(sopt, &ap->aal.v.aal5,
1087 sizeof ap->aal.v.aal5));
1094 if (ap->traffic.tag == T_ATM_PRESENT) {
1095 return (sooptcopyout(sopt, &ap->traffic.v,
1096 sizeof ap->traffic.v));
1102 case T_ATM_BEARER_CAP:
1103 if (ap->bearer.tag == T_ATM_PRESENT) {
1104 return (sooptcopyout(sopt, &ap->bearer.v,
1105 sizeof ap->bearer.v));
1112 if (ap->bhli.tag == T_ATM_PRESENT) {
1113 return (sooptcopyout(sopt, &ap->bhli.v,
1114 sizeof ap->bhli.v));
1121 if ((ap->blli.tag_l2 == T_ATM_PRESENT) ||
1122 (ap->blli.tag_l3 == T_ATM_PRESENT)) {
1123 return (sooptcopyout(sopt, &ap->blli.v,
1124 sizeof ap->blli.v));
1130 case T_ATM_DEST_ADDR:
1131 if (ap->called.tag == T_ATM_PRESENT) {
1132 return (sooptcopyout(sopt, &ap->called.addr,
1133 sizeof ap->called.addr));
1139 case T_ATM_DEST_SUB:
1140 if (ap->called.tag == T_ATM_PRESENT) {
1141 return (sooptcopyout(sopt, &ap->called.subaddr,
1142 sizeof ap->called.subaddr));
1148 case T_ATM_ORIG_ADDR:
1149 if (ap->calling.tag == T_ATM_PRESENT) {
1150 return (sooptcopyout(sopt, &ap->calling.addr,
1151 sizeof ap->calling.addr));
1157 case T_ATM_ORIG_SUB:
1158 if (ap->calling.tag == T_ATM_PRESENT) {
1159 return (sooptcopyout(sopt, &ap->calling.subaddr,
1160 sizeof ap->calling.subaddr));
1166 case T_ATM_CALLER_ID:
1167 if (ap->calling.tag == T_ATM_PRESENT) {
1168 return (sooptcopyout(sopt, &ap->calling.cid,
1169 sizeof ap->calling.cid));
1176 if (ap->cause.tag == T_ATM_PRESENT) {
1177 return (sooptcopyout(sopt, &ap->cause.v,
1178 sizeof ap->cause.v));
1185 if (ap->qos.tag == T_ATM_PRESENT) {
1186 return (sooptcopyout(sopt, &ap->qos.v,
1194 if (ap->transit.tag == T_ATM_PRESENT) {
1195 return (sooptcopyout(sopt, &ap->transit.v,
1196 sizeof ap->transit.v));
1202 case T_ATM_LEAF_IND:
1203 return (EPROTONOSUPPORT); /* XXX */
1205 case T_ATM_NET_INTF:
1207 struct t_atm_net_intf netif;
1210 ifp = ANIF2IFP(ap->nif);
1211 (void) snprintf(netif.net_intf, sizeof(netif.net_intf),
1212 "%s", ifp->if_xname);
1213 return (sooptcopyout(sopt, &netif,
1221 if (ap->llc.tag == T_ATM_PRESENT) {
1222 return (sooptcopyout(sopt, &ap->llc.v,
1230 return (ENOPROTOOPT);
1238 * Process Socket VCC Connected Notification
1241 * toku owner's connection token (atm_pcb protocol block)
1248 atm_sock_connected(toku)
1251 Atm_pcb *atp = (Atm_pcb *)toku;
1254 * Connection is setup
1256 atm_sock_stat.as_conncomp[atp->atp_type]++;
1257 soisconnected(atp->atp_socket);
1262 * Process Socket VCC Cleared Notification
1265 * toku owner's connection token (atm_pcb protocol block)
1266 * cause pointer to cause code
1273 atm_sock_cleared(toku, cause)
1275 struct t_atm_cause *cause;
1277 Atm_pcb *atp = (Atm_pcb *)toku;
1280 so = atp->atp_socket;
1283 * Save call clearing cause
1285 atp->atp_attr.cause.tag = T_ATM_PRESENT;
1286 atp->atp_attr.cause.v = *cause;
1289 * Set user error code
1291 if (so->so_state & SS_ISCONNECTED) {
1292 so->so_error = ECONNRESET;
1293 atm_sock_stat.as_connclr[atp->atp_type]++;
1295 so->so_error = ECONNREFUSED;
1296 atm_sock_stat.as_connfail[atp->atp_type]++;
1300 * Connection is gone
1302 atp->atp_conn = NULL;
1303 soisdisconnected(so);
1306 * Cleanup failed incoming connection setup
1308 if (so->so_state & SS_NOFDREF) {
1309 (void) atm_sock_detach(so);