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 $
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 <netatm/uni/uniip_var.h>
44 #include <netatm/uni/unisig.h>
45 #include <netatm/uni/unisig_var.h>
46 #include <netatm/uni/unisig_msg.h>
49 __RCSID("@(#) $FreeBSD: src/sys/netatm/uni/unisig_if.c,v 1.8 2000/01/17 20:49:56 mks Exp $");
56 struct sp_info unisig_vcpool = {
57 "unisig vcc pool", /* si_name */
58 sizeof(struct unisig_vccb), /* si_blksiz */
63 struct sp_info unisig_msgpool = {
64 "unisig message pool", /* si_name */
65 sizeof(struct unisig_msg), /* si_blksiz */
70 struct sp_info unisig_iepool = {
71 "unisig ie pool", /* si_name */
72 sizeof(struct ie_generic), /* si_blksiz */
81 static int unisig_attach __P((struct sigmgr *, struct atm_pif *));
82 static int unisig_detach __P((struct atm_pif *));
83 static int unisig_setup __P((Atm_connvc *, int *));
84 static int unisig_release __P((struct vccb *, int *));
85 static int unisig_accept __P((struct vccb *, int *));
86 static int unisig_reject __P((struct vccb *, int *));
87 static int unisig_abort __P((struct vccb *));
88 static int unisig_ioctl __P((int, caddr_t, caddr_t));
94 static struct sigmgr unisig_mgr30 = {
108 static struct sigmgr unisig_mgr31 = {
124 * Initialize UNISIG processing
126 * This will be called during module loading. We'll just register
127 * the UNISIG protocol descriptor and wait for a UNISIG ATM interface
134 * 0 startup was successful
135 * errno startup failed - reason indicated
144 * Verify software version
146 if (atm_version != ATM_VERSION) {
147 log(LOG_ERR, "version mismatch: unisig=%d.%d kernel=%d.%d\n",
148 ATM_VERS_MAJ(ATM_VERSION),
149 ATM_VERS_MIN(ATM_VERSION),
150 ATM_VERS_MAJ(atm_version),
151 ATM_VERS_MIN(atm_version));
156 * Register ourselves with system
158 err = atm_sigmgr_register(&unisig_mgr30);
162 err = atm_sigmgr_register(&unisig_mgr31);
170 * Halt UNISIG processing
172 * This should be called just prior to unloading the module from
173 * memory. All UNISIG interfaces must be deregistered before the
174 * protocol can be shutdown.
180 * 0 startup was successful
181 * errno startup failed - reason indicated
192 * Any protocol instances still registered?
194 if ((unisig_mgr30.sm_prinst != NULL) ||
195 (unisig_mgr31.sm_prinst != NULL)) {
197 /* Yes, can't stop now */
203 * De-register from system
205 (void) atm_sigmgr_deregister(&unisig_mgr30);
206 (void) atm_sigmgr_deregister(&unisig_mgr31);
209 * Free up our storage pools
211 atm_release_pool(&unisig_vcpool);
212 atm_release_pool(&unisig_msgpool);
213 atm_release_pool(&unisig_iepool);
222 * Attach a UNISIG-controlled interface
224 * Each ATM physical interface must be attached with the signalling
225 * manager for the interface's signalling protocol (via the
226 * atm_sigmgr_attach function). This function will handle the
227 * attachment for UNISIG-controlled interfaces. A new UNISIG protocol
228 * instance will be created and then we'll just sit around waiting for
229 * status or connection requests.
231 * Function must be called at splnet.
234 * smp pointer to UNISIG signalling manager control block
235 * pip pointer to ATM physical interface control block
238 * 0 attach successful
239 * errno attach failed - reason indicated
243 unisig_attach(smp, pip)
248 struct unisig *usp = NULL;
250 ATM_DEBUG2("unisig_attach: smp=%p, pip=%p\n", smp, pip);
253 * Allocate UNISIG protocol instance control block
255 usp = (struct unisig *)
256 KM_ALLOC(sizeof(struct unisig), M_DEVBUF, M_NOWAIT);
261 KM_ZERO(usp, sizeof(struct unisig));
264 * Set state in UNISIG protocol instance control block
266 usp->us_state = UNISIG_NULL;
267 usp->us_proto = smp->sm_proto;
270 * Set initial call reference allocation value
275 * Link instance into manager's chain
277 LINK2TAIL((struct siginst *)usp, struct siginst, smp->sm_prinst,
285 pip->pif_sigmgr = smp;
286 pip->pif_siginst = (struct siginst *) usp;
290 * Clear our ATM address. The address will be set by user
291 * command or by registration via ILMI.
293 usp->us_addr.address_format = T_ATM_ABSENT;
294 usp->us_addr.address_length = 0;
295 usp->us_subaddr.address_format = T_ATM_ABSENT;
296 usp->us_subaddr.address_length = 0;
301 usp->us_ipserv = &uniip_ipserv;
304 * Kick-start the UNISIG protocol
306 UNISIG_TIMER(usp, 0);
309 * Log the fact that we've attached
311 log(LOG_INFO, "unisig: attached to interface %s%d\n",
312 pip->pif_name, pip->pif_unit);
316 * Reset our work if attach fails
321 UNLINK((struct siginst *)usp, struct siginst,
322 smp->sm_prinst, si_next);
323 KM_FREE(usp, sizeof(struct unisig), M_DEVBUF);
326 pip->pif_sigmgr = NULL;
327 pip->pif_siginst = NULL;
336 * Detach a UNISIG-controlled interface
338 * Each ATM physical interface may be detached from its signalling
339 * manager (via the atm_sigmgr_detach function). This function will
340 * handle the detachment for all UNISIG-controlled interfaces. All
341 * circuits will be immediately terminated.
343 * Function must be called at splnet.
346 * pip pointer to ATM physical interface control block
349 * 0 detach successful
350 * errno detach failed - reason indicated
360 ATM_DEBUG1("unisig_detach: pip=%p\n", pip);
363 * Get UNISIG protocol instance
365 usp = (struct unisig *)pip->pif_siginst;
368 * Return an error if we're already detaching
370 if (usp->us_state == UNISIG_DETACH) {
375 * Pass the detach event to the signalling manager
378 err = unisig_sigmgr_state(usp, UNISIG_SIGMGR_DETACH,
382 * Log the fact that we've detached
385 log(LOG_INFO, "unisig: detached from interface %s%d\n",
386 pip->pif_name, pip->pif_unit);
393 * Open a UNISIG ATM Connection
395 * All service user requests to open a VC connection (via
396 * atm_open_connection) over an ATM interface attached to the UNISIG
397 * signalling manager are handled here.
399 * Function will be called at splnet.
402 * cvp pointer to user's requested connection parameters
403 * errp pointer to an int for extended error information
406 * CALL_PROCEEDING connection establishment is in progress
407 * CALL_FAILED connection establishment failed
408 * CALL_CONNECTED connection has been successfully established
412 unisig_setup(cvp, errp)
416 struct atm_pif *pip = cvp->cvc_attr.nif->nif_pif;
417 struct unisig *usp = (struct unisig *)pip->pif_siginst;
420 ATM_DEBUG1("unisig_setup: cvp=%p\n", cvp);
423 * Intialize the returned error code
428 * Open the connection
430 switch (cvp->cvc_attr.called.addr.address_format) {
435 *errp = unisig_open_vcc(usp, cvp);
436 rc = (*errp ? CALL_FAILED : CALL_CONNECTED);
439 case T_ATM_ENDSYS_ADDR:
440 case T_ATM_E164_ADDR:
445 *errp = unisig_open_vcc(usp, cvp);
446 rc = (*errp ? CALL_FAILED : CALL_PROCEEDING);
450 *errp = EPROTONOSUPPORT;
459 * Close a UNISIG ATM Connection
461 * All service user requests to terminate a previously open VC
462 * connection (via the atm_close_connection function), which is running
463 * over an interface attached to the UNISIG signalling manager, are
466 * Function will be called at splnet.
469 * vcp pointer to connection's VC control block
470 * errp pointer to an int for extended error information
473 * CALL_PROCEEDING connection termination is in progress
474 * CALL_FAILED connection termination failed
475 * CALL_CLEARED connection has been successfully terminated
479 unisig_release(vcp, errp)
484 struct atm_pif *pip = vcp->vc_pif;
485 struct unisig *usp = (struct unisig *)pip->pif_siginst;
487 ATM_DEBUG1("unisig_release: vcp=%p\n", vcp);
490 * Initialize returned error code
495 * Validate the connection type (PVC or SVC)
497 if (!(vcp->vc_type & (VCC_PVC | VCC_SVC))) {
498 *errp = EPROTONOSUPPORT;
505 *errp = unisig_close_vcc(usp, (struct unisig_vccb *)vcp);
508 * Set the return code
512 } else if (vcp->vc_sstate == UNI_NULL ||
513 vcp->vc_sstate == UNI_FREE) {
516 rc = CALL_PROCEEDING;
524 * Accept a UNISIG Open from a remote host
526 * A user calls this routine (via the atm_accept_call function)
527 * after it is notified that an open request was received for it.
529 * Function will be called at splnet.
532 * vcp pointer to user's VCCB
533 * errp pointer to an int for extended error information
536 * CALL_PROCEEDING connection establishment is in progress
537 * CALL_FAILED connection establishment failed
538 * CALL_CONNECTED connection has been successfully established
542 unisig_accept(vcp, errp)
546 struct unisig_vccb *uvp = (struct unisig_vccb *)vcp;
547 struct atm_pif *pip = uvp->uv_pif;
548 struct unisig *usp = (struct unisig *)pip->pif_siginst;
550 ATM_DEBUG1("unisig_accept: vcp=%p\n", vcp);
553 * Initialize the returned error code
558 * Return an error if we're detaching
560 if (usp->us_state == UNISIG_DETACH) {
566 * Return an error if we lost the connection
568 if (uvp->uv_sstate == UNI_FREE) {
574 * Pass the acceptance to the VC state machine
576 *errp = unisig_vc_state(usp, uvp, UNI_VC_ACCEPT_CALL,
577 (struct unisig_msg *) 0);
581 return(CALL_PROCEEDING);
585 * On error, free the VCCB and return CALL_FAILED
589 uvp->uv_sstate = UNI_FREE;
590 uvp->uv_ustate = VCCU_CLOSED;
591 DEQUEUE(uvp, struct unisig_vccb, uv_sigelem, usp->us_vccq);
592 unisig_free((struct vccb *)uvp);
599 * Reject a UNISIG Open from a remote host
601 * A user calls this routine (via the atm_reject_call function)
602 * after it is notified that an open request was received for it.
604 * Function will be called at splnet.
607 * uvp pointer to user's VCCB
608 * errp pointer to an int for extended error information
611 * CALL_CLEARED call request rejected
612 * CALL_FAILED call rejection failed
616 unisig_reject(vcp, errp)
620 struct unisig_vccb *uvp = (struct unisig_vccb *)vcp;
621 struct atm_pif *pip = uvp->uv_pif;
622 struct unisig *usp = (struct unisig *)pip->pif_siginst;
624 ATM_DEBUG1("unisig_reject: uvp=%p\n", uvp);
627 * Initialize the returned error code
633 * Return an error if we're detaching
635 if (usp->us_state == UNISIG_DETACH) {
641 * Call the VC state machine
643 *errp = unisig_vc_state(usp, uvp, UNI_VC_REJECT_CALL,
644 (struct unisig_msg *) 0);
648 return(CALL_CLEARED);
652 * On error, free the VCCB and return CALL_FAILED
654 uvp->uv_sstate = UNI_FREE;
655 uvp->uv_ustate = VCCU_CLOSED;
656 DEQUEUE(uvp, struct unisig_vccb, uv_sigelem, usp->us_vccq);
657 (void) unisig_free((struct vccb *)uvp);
663 * Abort a UNISIG ATM Connection
665 * All (non-user) requests to abort a previously open VC connection (via
666 * the atm_abort_connection function), which is running over an
667 * interface attached to the UNISIG signalling manager, are handled here.
668 * The VCC owner will be notified of the request, in order to initiate
669 * termination of the connection.
671 * Function will be called at splnet.
674 * vcp pointer to connection's VC control block
677 * 0 connection release was successful
678 * errno connection release failed - reason indicated
686 ATM_DEBUG1("unisig_abort: vcp=%p\n", vcp);
691 if (vcp->vc_ustate == VCCU_ABORT) {
696 * Cancel any timer that might be running
698 UNISIG_VC_CANCEL(vcp);
701 * Set immediate timer to schedule connection termination
703 vcp->vc_ustate = VCCU_ABORT;
704 UNISIG_VC_TIMER(vcp, 0);
711 * Free UNISIG ATM connection resources
713 * All service user requests to free the resources of a closed VCC
714 * connection (via the atm_free_connection function), which is running
715 * over an interface attached to the UNISIG signalling manager, are
718 * Function will be called at splnet.
721 * vcp pointer to connection's VC control block
724 * 0 connection free was successful
725 * errno connection free failed - reason indicated
732 struct atm_pif *pip = vcp->vc_pif;
733 struct unisig *usp = (struct unisig *)pip->pif_siginst;
735 ATM_DEBUG1("unisig_free: vcp = %p\n", vcp);
738 * Make sure VCC has been closed
740 if ((vcp->vc_ustate != VCCU_CLOSED &&
741 vcp->vc_ustate != VCCU_ABORT) ||
742 vcp->vc_sstate != UNI_FREE) {
743 ATM_DEBUG2("unisig_free: bad state, sstate=%d, ustate=%d\n",
744 vcp->vc_sstate, vcp->vc_ustate);
749 * Remove VCCB from protocol queue
751 DEQUEUE(vcp, struct vccb, vc_sigelem, usp->us_vccq);
756 vcp->vc_ustate = VCCU_NULL;
757 vcp->vc_sstate = UNI_NULL;
758 atm_free((caddr_t)vcp);
761 * If we're detaching and this was the last VCC queued,
762 * get rid of the protocol instance
764 if ((usp->us_state == UNISIG_DETACH) &&
765 (Q_HEAD(usp->us_vccq, struct vccb) == NULL)) {
766 struct sigmgr *smp = pip->pif_sigmgr;
769 pip->pif_sigmgr = NULL;
770 pip->pif_siginst = NULL;
773 UNLINK((struct siginst *)usp, struct siginst,
774 smp->sm_prinst, si_next);
775 KM_FREE(usp, sizeof(struct unisig), M_DEVBUF);
783 * UNISIG IOCTL support
785 * Function will be called at splnet.
788 * code PF_ATM sub-operation code
789 * data pointer to code specific parameter data area
790 * arg1 pointer to code specific argument
794 * errno error processing request - reason indicated
798 unisig_ioctl(code, data, arg1)
803 struct atmdelreq *adp;
804 struct atminfreq *aip;
805 struct atmsetreq *asp;
807 struct unisig_vccb *uvp;
808 struct air_vcc_rsp rsp;
812 int err = 0, buf_len, i;
815 ATM_DEBUG1("unisig_ioctl: code=%d\n", code);
824 adp = (struct atmdelreq *)data;
825 usp = (struct unisig *)arg1;
828 * Don't let a user close the UNISIG signalling VC
830 vpi = adp->adr_pvc_vpi;
831 vci = adp->adr_pvc_vci;
832 if ((vpi == UNISIG_SIG_VPI && vci == UNISIG_SIG_VCI))
838 for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb); uvp;
839 uvp = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem)) {
840 if ((uvp->uv_vpi == vpi) && (uvp->uv_vci == vci))
851 if (!(uvp->uv_type & VCC_PVC)) {
856 if (!(uvp->uv_type & VCC_SVC)) {
863 * Schedule VCC termination
865 unisig_cause_attr_from_user(&uvp->uv_connvc->cvc_attr,
866 T_ATM_CAUSE_UNSPECIFIED_NORMAL);
867 err = unisig_abort((struct vccb *)uvp);
872 * Return VCC information
874 aip = (struct atminfreq *)data;
875 usp = (struct unisig *)arg1;
877 buf_addr = aip->air_buf_addr;
878 buf_len = aip->air_buf_len;
881 * Loop through the VCC queue
883 for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb); uvp;
884 uvp = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem)) {
886 * Make sure there's room in the user's buffer
888 if (buf_len < sizeof(rsp)) {
894 * Fill out the response struct for the VCC
896 (void) snprintf(rsp.avp_intf,
897 sizeof(rsp.avp_intf), "%s%d",
898 usp->us_pif->pif_name,
899 usp->us_pif->pif_unit);
900 rsp.avp_vpi = uvp->uv_vpi;
901 rsp.avp_vci = uvp->uv_vci;
902 rsp.avp_type = uvp->uv_type;
903 rsp.avp_aal = uvp->uv_connvc->cvc_attr.aal.type;
904 rsp.avp_sig_proto = uvp->uv_proto;
905 cop = uvp->uv_connvc->cvc_conn;
907 rsp.avp_encaps = cop->co_mpx;
910 rsp.avp_state = uvp->uv_sstate;
911 if (uvp->uv_connvc->cvc_flags & CVCF_CALLER) {
912 rsp.avp_daddr = uvp->uv_connvc->cvc_attr.called.addr;
914 rsp.avp_daddr = uvp->uv_connvc->cvc_attr.calling.addr;
916 rsp.avp_dsubaddr.address_format = T_ATM_ABSENT;
917 rsp.avp_dsubaddr.address_length = 0;
918 rsp.avp_ipdus = uvp->uv_ipdus;
919 rsp.avp_opdus = uvp->uv_opdus;
920 rsp.avp_ibytes = uvp->uv_ibytes;
921 rsp.avp_obytes = uvp->uv_obytes;
922 rsp.avp_ierrors = uvp->uv_ierrors;
923 rsp.avp_oerrors = uvp->uv_oerrors;
924 rsp.avp_tstamp = uvp->uv_tstamp;
925 KM_ZERO(rsp.avp_owners,
926 sizeof(rsp.avp_owners));
927 for (i = 0; cop && i < sizeof(rsp.avp_owners);
929 i += T_ATM_APP_NAME_LEN+1) {
930 strncpy(&rsp.avp_owners[i],
931 cop->co_endpt->ep_getname(cop->co_toku),
936 * Copy the response into the user's buffer
938 if ((err = copyout((caddr_t)&rsp, buf_addr,
941 buf_addr += sizeof(rsp);
942 buf_len -= sizeof(rsp);
946 * Update the buffer pointer and length
948 aip->air_buf_addr = buf_addr;
949 aip->air_buf_len = buf_len;
956 * Get ARP table information or get/set ARP server address
958 err = uniarp_ioctl(code, data, arg1);
965 asp = (struct atmsetreq *)data;
966 usp = (struct unisig *)arg1;
968 if (usp->us_addr.address_format != T_ATM_ABSENT) {
969 if (KM_CMP(asp->asr_prf_pref, usp->us_addr.address,
970 sizeof(asp->asr_prf_pref)) != 0)
974 usp->us_addr.address_format = T_ATM_ENDSYS_ADDR;
975 usp->us_addr.address_length = sizeof(Atm_addr_nsap);
976 KM_COPY(&pip->pif_macaddr,
977 ((Atm_addr_nsap *)usp->us_addr.address)->aan_esi,
978 sizeof(pip->pif_macaddr));
979 KM_COPY((caddr_t) asp->asr_prf_pref,
980 &((Atm_addr_nsap *)usp->us_addr.address)->aan_afi,
981 sizeof(asp->asr_prf_pref));
982 log(LOG_INFO, "uni: set address %s on interface %s\n",
983 unisig_addr_print(&usp->us_addr),
987 * Pass event to signalling manager state machine
989 err = unisig_sigmgr_state(usp, UNISIG_SIGMGR_ADDR_SET,
993 * Clean up if there was an error
996 usp->us_addr.address_format = T_ATM_ABSENT;
997 usp->us_addr.address_length = 0;
1002 * Inform ARP code of new address
1004 uniarp_ifaddr((struct siginst *)usp);