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/uni/unisig_if.c,v 1.8 2000/01/17 20:49:56 mks Exp $
27 * @(#) $DragonFly: src/sys/netproto/atm/uni/unisig_if.c,v 1.3 2003/08/07 21:17:36 dillon Exp $
31 * ATM Forum UNI 3.0/3.1 Signalling Manager
32 * ----------------------------------------
34 * System interface module
38 #include <netatm/kern_include.h>
40 #include <netatm/ipatm/ipatm_var.h>
41 #include <netatm/ipatm/ipatm_serv.h>
42 #include "uniip_var.h"
45 #include "unisig_var.h"
46 #include "unisig_msg.h"
51 struct sp_info unisig_vcpool = {
52 "unisig vcc pool", /* si_name */
53 sizeof(struct unisig_vccb), /* si_blksiz */
58 struct sp_info unisig_msgpool = {
59 "unisig message pool", /* si_name */
60 sizeof(struct unisig_msg), /* si_blksiz */
65 struct sp_info unisig_iepool = {
66 "unisig ie pool", /* si_name */
67 sizeof(struct ie_generic), /* si_blksiz */
76 static int unisig_attach __P((struct sigmgr *, struct atm_pif *));
77 static int unisig_detach __P((struct atm_pif *));
78 static int unisig_setup __P((Atm_connvc *, int *));
79 static int unisig_release __P((struct vccb *, int *));
80 static int unisig_accept __P((struct vccb *, int *));
81 static int unisig_reject __P((struct vccb *, int *));
82 static int unisig_abort __P((struct vccb *));
83 static int unisig_ioctl __P((int, caddr_t, caddr_t));
89 static struct sigmgr unisig_mgr30 = {
103 static struct sigmgr unisig_mgr31 = {
119 * Initialize UNISIG processing
121 * This will be called during module loading. We'll just register
122 * the UNISIG protocol descriptor and wait for a UNISIG ATM interface
129 * 0 startup was successful
130 * errno startup failed - reason indicated
139 * Verify software version
141 if (atm_version != ATM_VERSION) {
142 log(LOG_ERR, "version mismatch: unisig=%d.%d kernel=%d.%d\n",
143 ATM_VERS_MAJ(ATM_VERSION),
144 ATM_VERS_MIN(ATM_VERSION),
145 ATM_VERS_MAJ(atm_version),
146 ATM_VERS_MIN(atm_version));
151 * Register ourselves with system
153 err = atm_sigmgr_register(&unisig_mgr30);
157 err = atm_sigmgr_register(&unisig_mgr31);
165 * Halt UNISIG processing
167 * This should be called just prior to unloading the module from
168 * memory. All UNISIG interfaces must be deregistered before the
169 * protocol can be shutdown.
175 * 0 startup was successful
176 * errno startup failed - reason indicated
187 * Any protocol instances still registered?
189 if ((unisig_mgr30.sm_prinst != NULL) ||
190 (unisig_mgr31.sm_prinst != NULL)) {
192 /* Yes, can't stop now */
198 * De-register from system
200 (void) atm_sigmgr_deregister(&unisig_mgr30);
201 (void) atm_sigmgr_deregister(&unisig_mgr31);
204 * Free up our storage pools
206 atm_release_pool(&unisig_vcpool);
207 atm_release_pool(&unisig_msgpool);
208 atm_release_pool(&unisig_iepool);
217 * Attach a UNISIG-controlled interface
219 * Each ATM physical interface must be attached with the signalling
220 * manager for the interface's signalling protocol (via the
221 * atm_sigmgr_attach function). This function will handle the
222 * attachment for UNISIG-controlled interfaces. A new UNISIG protocol
223 * instance will be created and then we'll just sit around waiting for
224 * status or connection requests.
226 * Function must be called at splnet.
229 * smp pointer to UNISIG signalling manager control block
230 * pip pointer to ATM physical interface control block
233 * 0 attach successful
234 * errno attach failed - reason indicated
238 unisig_attach(smp, pip)
243 struct unisig *usp = NULL;
245 ATM_DEBUG2("unisig_attach: smp=%p, pip=%p\n", smp, pip);
248 * Allocate UNISIG protocol instance control block
250 usp = (struct unisig *)
251 KM_ALLOC(sizeof(struct unisig), M_DEVBUF, M_NOWAIT);
256 KM_ZERO(usp, sizeof(struct unisig));
259 * Set state in UNISIG protocol instance control block
261 usp->us_state = UNISIG_NULL;
262 usp->us_proto = smp->sm_proto;
265 * Set initial call reference allocation value
270 * Link instance into manager's chain
272 LINK2TAIL((struct siginst *)usp, struct siginst, smp->sm_prinst,
280 pip->pif_sigmgr = smp;
281 pip->pif_siginst = (struct siginst *) usp;
285 * Clear our ATM address. The address will be set by user
286 * command or by registration via ILMI.
288 usp->us_addr.address_format = T_ATM_ABSENT;
289 usp->us_addr.address_length = 0;
290 usp->us_subaddr.address_format = T_ATM_ABSENT;
291 usp->us_subaddr.address_length = 0;
296 usp->us_ipserv = &uniip_ipserv;
299 * Kick-start the UNISIG protocol
301 UNISIG_TIMER(usp, 0);
304 * Log the fact that we've attached
306 log(LOG_INFO, "unisig: attached to interface %s%d\n",
307 pip->pif_name, pip->pif_unit);
311 * Reset our work if attach fails
316 UNLINK((struct siginst *)usp, struct siginst,
317 smp->sm_prinst, si_next);
318 KM_FREE(usp, sizeof(struct unisig), M_DEVBUF);
321 pip->pif_sigmgr = NULL;
322 pip->pif_siginst = NULL;
331 * Detach a UNISIG-controlled interface
333 * Each ATM physical interface may be detached from its signalling
334 * manager (via the atm_sigmgr_detach function). This function will
335 * handle the detachment for all UNISIG-controlled interfaces. All
336 * circuits will be immediately terminated.
338 * Function must be called at splnet.
341 * pip pointer to ATM physical interface control block
344 * 0 detach successful
345 * errno detach failed - reason indicated
355 ATM_DEBUG1("unisig_detach: pip=%p\n", pip);
358 * Get UNISIG protocol instance
360 usp = (struct unisig *)pip->pif_siginst;
363 * Return an error if we're already detaching
365 if (usp->us_state == UNISIG_DETACH) {
370 * Pass the detach event to the signalling manager
373 err = unisig_sigmgr_state(usp, UNISIG_SIGMGR_DETACH,
377 * Log the fact that we've detached
380 log(LOG_INFO, "unisig: detached from interface %s%d\n",
381 pip->pif_name, pip->pif_unit);
388 * Open a UNISIG ATM Connection
390 * All service user requests to open a VC connection (via
391 * atm_open_connection) over an ATM interface attached to the UNISIG
392 * signalling manager are handled here.
394 * Function will be called at splnet.
397 * cvp pointer to user's requested connection parameters
398 * errp pointer to an int for extended error information
401 * CALL_PROCEEDING connection establishment is in progress
402 * CALL_FAILED connection establishment failed
403 * CALL_CONNECTED connection has been successfully established
407 unisig_setup(cvp, errp)
411 struct atm_pif *pip = cvp->cvc_attr.nif->nif_pif;
412 struct unisig *usp = (struct unisig *)pip->pif_siginst;
415 ATM_DEBUG1("unisig_setup: cvp=%p\n", cvp);
418 * Intialize the returned error code
423 * Open the connection
425 switch (cvp->cvc_attr.called.addr.address_format) {
430 *errp = unisig_open_vcc(usp, cvp);
431 rc = (*errp ? CALL_FAILED : CALL_CONNECTED);
434 case T_ATM_ENDSYS_ADDR:
435 case T_ATM_E164_ADDR:
440 *errp = unisig_open_vcc(usp, cvp);
441 rc = (*errp ? CALL_FAILED : CALL_PROCEEDING);
445 *errp = EPROTONOSUPPORT;
454 * Close a UNISIG ATM Connection
456 * All service user requests to terminate a previously open VC
457 * connection (via the atm_close_connection function), which is running
458 * over an interface attached to the UNISIG signalling manager, are
461 * Function will be called at splnet.
464 * vcp pointer to connection's VC control block
465 * errp pointer to an int for extended error information
468 * CALL_PROCEEDING connection termination is in progress
469 * CALL_FAILED connection termination failed
470 * CALL_CLEARED connection has been successfully terminated
474 unisig_release(vcp, errp)
479 struct atm_pif *pip = vcp->vc_pif;
480 struct unisig *usp = (struct unisig *)pip->pif_siginst;
482 ATM_DEBUG1("unisig_release: vcp=%p\n", vcp);
485 * Initialize returned error code
490 * Validate the connection type (PVC or SVC)
492 if (!(vcp->vc_type & (VCC_PVC | VCC_SVC))) {
493 *errp = EPROTONOSUPPORT;
500 *errp = unisig_close_vcc(usp, (struct unisig_vccb *)vcp);
503 * Set the return code
507 } else if (vcp->vc_sstate == UNI_NULL ||
508 vcp->vc_sstate == UNI_FREE) {
511 rc = CALL_PROCEEDING;
519 * Accept a UNISIG Open from a remote host
521 * A user calls this routine (via the atm_accept_call function)
522 * after it is notified that an open request was received for it.
524 * Function will be called at splnet.
527 * vcp pointer to user's VCCB
528 * errp pointer to an int for extended error information
531 * CALL_PROCEEDING connection establishment is in progress
532 * CALL_FAILED connection establishment failed
533 * CALL_CONNECTED connection has been successfully established
537 unisig_accept(vcp, errp)
541 struct unisig_vccb *uvp = (struct unisig_vccb *)vcp;
542 struct atm_pif *pip = uvp->uv_pif;
543 struct unisig *usp = (struct unisig *)pip->pif_siginst;
545 ATM_DEBUG1("unisig_accept: vcp=%p\n", vcp);
548 * Initialize the returned error code
553 * Return an error if we're detaching
555 if (usp->us_state == UNISIG_DETACH) {
561 * Return an error if we lost the connection
563 if (uvp->uv_sstate == UNI_FREE) {
569 * Pass the acceptance to the VC state machine
571 *errp = unisig_vc_state(usp, uvp, UNI_VC_ACCEPT_CALL,
572 (struct unisig_msg *) 0);
576 return(CALL_PROCEEDING);
580 * On error, free the VCCB and return CALL_FAILED
584 uvp->uv_sstate = UNI_FREE;
585 uvp->uv_ustate = VCCU_CLOSED;
586 DEQUEUE(uvp, struct unisig_vccb, uv_sigelem, usp->us_vccq);
587 unisig_free((struct vccb *)uvp);
594 * Reject a UNISIG Open from a remote host
596 * A user calls this routine (via the atm_reject_call function)
597 * after it is notified that an open request was received for it.
599 * Function will be called at splnet.
602 * uvp pointer to user's VCCB
603 * errp pointer to an int for extended error information
606 * CALL_CLEARED call request rejected
607 * CALL_FAILED call rejection failed
611 unisig_reject(vcp, errp)
615 struct unisig_vccb *uvp = (struct unisig_vccb *)vcp;
616 struct atm_pif *pip = uvp->uv_pif;
617 struct unisig *usp = (struct unisig *)pip->pif_siginst;
619 ATM_DEBUG1("unisig_reject: uvp=%p\n", uvp);
622 * Initialize the returned error code
628 * Return an error if we're detaching
630 if (usp->us_state == UNISIG_DETACH) {
636 * Call the VC state machine
638 *errp = unisig_vc_state(usp, uvp, UNI_VC_REJECT_CALL,
639 (struct unisig_msg *) 0);
643 return(CALL_CLEARED);
647 * On error, free the VCCB and return CALL_FAILED
649 uvp->uv_sstate = UNI_FREE;
650 uvp->uv_ustate = VCCU_CLOSED;
651 DEQUEUE(uvp, struct unisig_vccb, uv_sigelem, usp->us_vccq);
652 (void) unisig_free((struct vccb *)uvp);
658 * Abort a UNISIG ATM Connection
660 * All (non-user) requests to abort a previously open VC connection (via
661 * the atm_abort_connection function), which is running over an
662 * interface attached to the UNISIG signalling manager, are handled here.
663 * The VCC owner will be notified of the request, in order to initiate
664 * termination of the connection.
666 * Function will be called at splnet.
669 * vcp pointer to connection's VC control block
672 * 0 connection release was successful
673 * errno connection release failed - reason indicated
681 ATM_DEBUG1("unisig_abort: vcp=%p\n", vcp);
686 if (vcp->vc_ustate == VCCU_ABORT) {
691 * Cancel any timer that might be running
693 UNISIG_VC_CANCEL(vcp);
696 * Set immediate timer to schedule connection termination
698 vcp->vc_ustate = VCCU_ABORT;
699 UNISIG_VC_TIMER(vcp, 0);
706 * Free UNISIG ATM connection resources
708 * All service user requests to free the resources of a closed VCC
709 * connection (via the atm_free_connection function), which is running
710 * over an interface attached to the UNISIG signalling manager, are
713 * Function will be called at splnet.
716 * vcp pointer to connection's VC control block
719 * 0 connection free was successful
720 * errno connection free failed - reason indicated
727 struct atm_pif *pip = vcp->vc_pif;
728 struct unisig *usp = (struct unisig *)pip->pif_siginst;
730 ATM_DEBUG1("unisig_free: vcp = %p\n", vcp);
733 * Make sure VCC has been closed
735 if ((vcp->vc_ustate != VCCU_CLOSED &&
736 vcp->vc_ustate != VCCU_ABORT) ||
737 vcp->vc_sstate != UNI_FREE) {
738 ATM_DEBUG2("unisig_free: bad state, sstate=%d, ustate=%d\n",
739 vcp->vc_sstate, vcp->vc_ustate);
744 * Remove VCCB from protocol queue
746 DEQUEUE(vcp, struct vccb, vc_sigelem, usp->us_vccq);
751 vcp->vc_ustate = VCCU_NULL;
752 vcp->vc_sstate = UNI_NULL;
753 atm_free((caddr_t)vcp);
756 * If we're detaching and this was the last VCC queued,
757 * get rid of the protocol instance
759 if ((usp->us_state == UNISIG_DETACH) &&
760 (Q_HEAD(usp->us_vccq, struct vccb) == NULL)) {
761 struct sigmgr *smp = pip->pif_sigmgr;
764 pip->pif_sigmgr = NULL;
765 pip->pif_siginst = NULL;
768 UNLINK((struct siginst *)usp, struct siginst,
769 smp->sm_prinst, si_next);
770 KM_FREE(usp, sizeof(struct unisig), M_DEVBUF);
778 * UNISIG IOCTL support
780 * Function will be called at splnet.
783 * code PF_ATM sub-operation code
784 * data pointer to code specific parameter data area
785 * arg1 pointer to code specific argument
789 * errno error processing request - reason indicated
793 unisig_ioctl(code, data, arg1)
798 struct atmdelreq *adp;
799 struct atminfreq *aip;
800 struct atmsetreq *asp;
802 struct unisig_vccb *uvp;
803 struct air_vcc_rsp rsp;
807 int err = 0, buf_len, i;
810 ATM_DEBUG1("unisig_ioctl: code=%d\n", code);
819 adp = (struct atmdelreq *)data;
820 usp = (struct unisig *)arg1;
823 * Don't let a user close the UNISIG signalling VC
825 vpi = adp->adr_pvc_vpi;
826 vci = adp->adr_pvc_vci;
827 if ((vpi == UNISIG_SIG_VPI && vci == UNISIG_SIG_VCI))
833 for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb); uvp;
834 uvp = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem)) {
835 if ((uvp->uv_vpi == vpi) && (uvp->uv_vci == vci))
846 if (!(uvp->uv_type & VCC_PVC)) {
851 if (!(uvp->uv_type & VCC_SVC)) {
858 * Schedule VCC termination
860 unisig_cause_attr_from_user(&uvp->uv_connvc->cvc_attr,
861 T_ATM_CAUSE_UNSPECIFIED_NORMAL);
862 err = unisig_abort((struct vccb *)uvp);
867 * Return VCC information
869 aip = (struct atminfreq *)data;
870 usp = (struct unisig *)arg1;
872 buf_addr = aip->air_buf_addr;
873 buf_len = aip->air_buf_len;
876 * Loop through the VCC queue
878 for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb); uvp;
879 uvp = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem)) {
881 * Make sure there's room in the user's buffer
883 if (buf_len < sizeof(rsp)) {
889 * Fill out the response struct for the VCC
891 (void) snprintf(rsp.avp_intf,
892 sizeof(rsp.avp_intf), "%s%d",
893 usp->us_pif->pif_name,
894 usp->us_pif->pif_unit);
895 rsp.avp_vpi = uvp->uv_vpi;
896 rsp.avp_vci = uvp->uv_vci;
897 rsp.avp_type = uvp->uv_type;
898 rsp.avp_aal = uvp->uv_connvc->cvc_attr.aal.type;
899 rsp.avp_sig_proto = uvp->uv_proto;
900 cop = uvp->uv_connvc->cvc_conn;
902 rsp.avp_encaps = cop->co_mpx;
905 rsp.avp_state = uvp->uv_sstate;
906 if (uvp->uv_connvc->cvc_flags & CVCF_CALLER) {
907 rsp.avp_daddr = uvp->uv_connvc->cvc_attr.called.addr;
909 rsp.avp_daddr = uvp->uv_connvc->cvc_attr.calling.addr;
911 rsp.avp_dsubaddr.address_format = T_ATM_ABSENT;
912 rsp.avp_dsubaddr.address_length = 0;
913 rsp.avp_ipdus = uvp->uv_ipdus;
914 rsp.avp_opdus = uvp->uv_opdus;
915 rsp.avp_ibytes = uvp->uv_ibytes;
916 rsp.avp_obytes = uvp->uv_obytes;
917 rsp.avp_ierrors = uvp->uv_ierrors;
918 rsp.avp_oerrors = uvp->uv_oerrors;
919 rsp.avp_tstamp = uvp->uv_tstamp;
920 KM_ZERO(rsp.avp_owners,
921 sizeof(rsp.avp_owners));
922 for (i = 0; cop && i < sizeof(rsp.avp_owners);
924 i += T_ATM_APP_NAME_LEN+1) {
925 strncpy(&rsp.avp_owners[i],
926 cop->co_endpt->ep_getname(cop->co_toku),
931 * Copy the response into the user's buffer
933 if ((err = copyout((caddr_t)&rsp, buf_addr,
936 buf_addr += sizeof(rsp);
937 buf_len -= sizeof(rsp);
941 * Update the buffer pointer and length
943 aip->air_buf_addr = buf_addr;
944 aip->air_buf_len = buf_len;
951 * Get ARP table information or get/set ARP server address
953 err = uniarp_ioctl(code, data, arg1);
960 asp = (struct atmsetreq *)data;
961 usp = (struct unisig *)arg1;
963 if (usp->us_addr.address_format != T_ATM_ABSENT) {
964 if (KM_CMP(asp->asr_prf_pref, usp->us_addr.address,
965 sizeof(asp->asr_prf_pref)) != 0)
969 usp->us_addr.address_format = T_ATM_ENDSYS_ADDR;
970 usp->us_addr.address_length = sizeof(Atm_addr_nsap);
971 KM_COPY(&pip->pif_macaddr,
972 ((Atm_addr_nsap *)usp->us_addr.address)->aan_esi,
973 sizeof(pip->pif_macaddr));
974 KM_COPY((caddr_t) asp->asr_prf_pref,
975 &((Atm_addr_nsap *)usp->us_addr.address)->aan_afi,
976 sizeof(asp->asr_prf_pref));
977 log(LOG_INFO, "uni: set address %s on interface %s\n",
978 unisig_addr_print(&usp->us_addr),
982 * Pass event to signalling manager state machine
984 err = unisig_sigmgr_state(usp, UNISIG_SIGMGR_ADDR_SET,
988 * Clean up if there was an error
991 usp->us_addr.address_format = T_ATM_ABSENT;
992 usp->us_addr.address_length = 0;
997 * Inform ARP code of new address
999 uniarp_ifaddr((struct siginst *)usp);