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.9 2006/12/20 18:14:43 dillon Exp $
31 * ATM Forum UNI 3.0/3.1 Signalling Manager
32 * ----------------------------------------
34 * System interface module
38 #include <netproto/atm/kern_include.h>
40 #include <netproto/atm/ipatm/ipatm_var.h>
41 #include <netproto/atm/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 (struct sigmgr
*, struct atm_pif
*);
77 static int unisig_detach (struct atm_pif
*);
78 static int unisig_setup (Atm_connvc
*, int *);
79 static int unisig_release (struct vccb
*, int *);
80 static int unisig_accept (struct vccb
*, int *);
81 static int unisig_reject (struct vccb
*, int *);
82 static int unisig_abort (struct vccb
*);
83 static int unisig_ioctl (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 atm_sigmgr_deregister(&unisig_mgr30
);
201 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 from a critical section.
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(struct sigmgr
*smp
, struct atm_pif
*pip
)
241 struct unisig
*usp
= NULL
;
243 ATM_DEBUG2("unisig_attach: smp=%p, pip=%p\n", smp
, pip
);
246 * Allocate UNISIG protocol instance control block
248 usp
= KM_ALLOC(sizeof(struct unisig
), M_DEVBUF
, M_INTWAIT
| M_NULLOK
);
253 KM_ZERO(usp
, sizeof(struct unisig
));
256 * Set state in UNISIG protocol instance control block
258 usp
->us_state
= UNISIG_NULL
;
259 usp
->us_proto
= smp
->sm_proto
;
262 * Set initial call reference allocation value
267 * Link instance into manager's chain
269 LINK2TAIL((struct siginst
*)usp
, struct siginst
, smp
->sm_prinst
,
277 pip
->pif_sigmgr
= smp
;
278 pip
->pif_siginst
= (struct siginst
*) usp
;
282 * Clear our ATM address. The address will be set by user
283 * command or by registration via ILMI.
285 usp
->us_addr
.address_format
= T_ATM_ABSENT
;
286 usp
->us_addr
.address_length
= 0;
287 usp
->us_subaddr
.address_format
= T_ATM_ABSENT
;
288 usp
->us_subaddr
.address_length
= 0;
293 usp
->us_ipserv
= &uniip_ipserv
;
296 * Kick-start the UNISIG protocol
298 UNISIG_TIMER(usp
, 0);
301 * Log the fact that we've attached
303 log(LOG_INFO
, "unisig: attached to interface %s%d\n",
304 pip
->pif_name
, pip
->pif_unit
);
308 * Reset our work if attach fails
313 UNLINK((struct siginst
*)usp
, struct siginst
,
314 smp
->sm_prinst
, si_next
);
315 KM_FREE(usp
, sizeof(struct unisig
), M_DEVBUF
);
318 pip
->pif_sigmgr
= NULL
;
319 pip
->pif_siginst
= NULL
;
328 * Detach a UNISIG-controlled interface
330 * Each ATM physical interface may be detached from its signalling
331 * manager (via the atm_sigmgr_detach function). This function will
332 * handle the detachment for all UNISIG-controlled interfaces. All
333 * circuits will be immediately terminated.
335 * Function must be called from a critical section.
338 * pip pointer to ATM physical interface control block
341 * 0 detach successful
342 * errno detach failed - reason indicated
346 unisig_detach(struct atm_pif
*pip
)
351 ATM_DEBUG1("unisig_detach: pip=%p\n", pip
);
354 * Get UNISIG protocol instance
356 usp
= (struct unisig
*)pip
->pif_siginst
;
359 * Return an error if we're already detaching
361 if (usp
->us_state
== UNISIG_DETACH
) {
366 * Pass the detach event to the signalling manager
369 err
= unisig_sigmgr_state(usp
, UNISIG_SIGMGR_DETACH
,
373 * Log the fact that we've detached
376 log(LOG_INFO
, "unisig: detached from interface %s%d\n",
377 pip
->pif_name
, pip
->pif_unit
);
384 * Open a UNISIG ATM Connection
386 * All service user requests to open a VC connection (via
387 * atm_open_connection) over an ATM interface attached to the UNISIG
388 * signalling manager are handled here.
390 * Function will be called from a critical section.
393 * cvp pointer to user's requested connection parameters
394 * errp pointer to an int for extended error information
397 * CALL_PROCEEDING connection establishment is in progress
398 * CALL_FAILED connection establishment failed
399 * CALL_CONNECTED connection has been successfully established
403 unisig_setup(Atm_connvc
*cvp
, int *errp
)
405 struct atm_pif
*pip
= cvp
->cvc_attr
.nif
->nif_pif
;
406 struct unisig
*usp
= (struct unisig
*)pip
->pif_siginst
;
409 ATM_DEBUG1("unisig_setup: cvp=%p\n", cvp
);
412 * Intialize the returned error code
417 * Open the connection
419 switch (cvp
->cvc_attr
.called
.addr
.address_format
) {
424 *errp
= unisig_open_vcc(usp
, cvp
);
425 rc
= (*errp
? CALL_FAILED
: CALL_CONNECTED
);
428 case T_ATM_ENDSYS_ADDR
:
429 case T_ATM_E164_ADDR
:
434 *errp
= unisig_open_vcc(usp
, cvp
);
435 rc
= (*errp
? CALL_FAILED
: CALL_PROCEEDING
);
439 *errp
= EPROTONOSUPPORT
;
448 * Close a UNISIG ATM Connection
450 * All service user requests to terminate a previously open VC
451 * connection (via the atm_close_connection function), which is running
452 * over an interface attached to the UNISIG signalling manager, are
455 * Function will be called from a critical section.
458 * vcp pointer to connection's VC control block
459 * errp pointer to an int for extended error information
462 * CALL_PROCEEDING connection termination is in progress
463 * CALL_FAILED connection termination failed
464 * CALL_CLEARED connection has been successfully terminated
468 unisig_release(struct vccb
*vcp
, int *errp
)
471 struct atm_pif
*pip
= vcp
->vc_pif
;
472 struct unisig
*usp
= (struct unisig
*)pip
->pif_siginst
;
474 ATM_DEBUG1("unisig_release: vcp=%p\n", vcp
);
477 * Initialize returned error code
482 * Validate the connection type (PVC or SVC)
484 if (!(vcp
->vc_type
& (VCC_PVC
| VCC_SVC
))) {
485 *errp
= EPROTONOSUPPORT
;
492 *errp
= unisig_close_vcc(usp
, (struct unisig_vccb
*)vcp
);
495 * Set the return code
499 } else if (vcp
->vc_sstate
== UNI_NULL
||
500 vcp
->vc_sstate
== UNI_FREE
) {
503 rc
= CALL_PROCEEDING
;
511 * Accept a UNISIG Open from a remote host
513 * A user calls this routine (via the atm_accept_call function)
514 * after it is notified that an open request was received for it.
516 * Function will be called from a critical section.
519 * vcp pointer to user's VCCB
520 * errp pointer to an int for extended error information
523 * CALL_PROCEEDING connection establishment is in progress
524 * CALL_FAILED connection establishment failed
525 * CALL_CONNECTED connection has been successfully established
529 unisig_accept(struct vccb
*vcp
, int *errp
)
531 struct unisig_vccb
*uvp
= (struct unisig_vccb
*)vcp
;
532 struct atm_pif
*pip
= uvp
->uv_pif
;
533 struct unisig
*usp
= (struct unisig
*)pip
->pif_siginst
;
535 ATM_DEBUG1("unisig_accept: vcp=%p\n", vcp
);
538 * Initialize the returned error code
543 * Return an error if we're detaching
545 if (usp
->us_state
== UNISIG_DETACH
) {
551 * Return an error if we lost the connection
553 if (uvp
->uv_sstate
== UNI_FREE
) {
559 * Pass the acceptance to the VC state machine
561 *errp
= unisig_vc_state(usp
, uvp
, UNI_VC_ACCEPT_CALL
,
562 (struct unisig_msg
*) 0);
566 return(CALL_PROCEEDING
);
570 * On error, free the VCCB and return CALL_FAILED
574 uvp
->uv_sstate
= UNI_FREE
;
575 uvp
->uv_ustate
= VCCU_CLOSED
;
576 DEQUEUE(uvp
, struct unisig_vccb
, uv_sigelem
, usp
->us_vccq
);
577 unisig_free((struct vccb
*)uvp
);
584 * Reject a UNISIG Open from a remote host
586 * A user calls this routine (via the atm_reject_call function)
587 * after it is notified that an open request was received for it.
589 * Function will be called from a critical section.
592 * uvp pointer to user's VCCB
593 * errp pointer to an int for extended error information
596 * CALL_CLEARED call request rejected
597 * CALL_FAILED call rejection failed
601 unisig_reject(struct vccb
*vcp
, int *errp
)
603 struct unisig_vccb
*uvp
= (struct unisig_vccb
*)vcp
;
604 struct atm_pif
*pip
= uvp
->uv_pif
;
605 struct unisig
*usp
= (struct unisig
*)pip
->pif_siginst
;
607 ATM_DEBUG1("unisig_reject: uvp=%p\n", uvp
);
610 * Initialize the returned error code
616 * Return an error if we're detaching
618 if (usp
->us_state
== UNISIG_DETACH
) {
624 * Call the VC state machine
626 *errp
= unisig_vc_state(usp
, uvp
, UNI_VC_REJECT_CALL
,
627 (struct unisig_msg
*) 0);
631 return(CALL_CLEARED
);
635 * On error, free the VCCB and return CALL_FAILED
637 uvp
->uv_sstate
= UNI_FREE
;
638 uvp
->uv_ustate
= VCCU_CLOSED
;
639 DEQUEUE(uvp
, struct unisig_vccb
, uv_sigelem
, usp
->us_vccq
);
640 unisig_free((struct vccb
*)uvp
);
646 * Abort a UNISIG ATM Connection
648 * All (non-user) requests to abort a previously open VC connection (via
649 * the atm_abort_connection function), which is running over an
650 * interface attached to the UNISIG signalling manager, are handled here.
651 * The VCC owner will be notified of the request, in order to initiate
652 * termination of the connection.
654 * Function will be called from a critical section.
657 * vcp pointer to connection's VC control block
660 * 0 connection release was successful
661 * errno connection release failed - reason indicated
665 unisig_abort(struct vccb
*vcp
)
668 ATM_DEBUG1("unisig_abort: vcp=%p\n", vcp
);
673 if (vcp
->vc_ustate
== VCCU_ABORT
) {
678 * Cancel any timer that might be running
680 UNISIG_VC_CANCEL(vcp
);
683 * Set immediate timer to schedule connection termination
685 vcp
->vc_ustate
= VCCU_ABORT
;
686 UNISIG_VC_TIMER(vcp
, 0);
693 * Free UNISIG ATM connection resources
695 * All service user requests to free the resources of a closed VCC
696 * connection (via the atm_free_connection function), which is running
697 * over an interface attached to the UNISIG signalling manager, are
700 * Function will be called from a critical section.
703 * vcp pointer to connection's VC control block
706 * 0 connection free was successful
707 * errno connection free failed - reason indicated
711 unisig_free(struct vccb
*vcp
)
713 struct atm_pif
*pip
= vcp
->vc_pif
;
714 struct unisig
*usp
= (struct unisig
*)pip
->pif_siginst
;
716 ATM_DEBUG1("unisig_free: vcp = %p\n", vcp
);
719 * Make sure VCC has been closed
721 if ((vcp
->vc_ustate
!= VCCU_CLOSED
&&
722 vcp
->vc_ustate
!= VCCU_ABORT
) ||
723 vcp
->vc_sstate
!= UNI_FREE
) {
724 ATM_DEBUG2("unisig_free: bad state, sstate=%d, ustate=%d\n",
725 vcp
->vc_sstate
, vcp
->vc_ustate
);
730 * Remove VCCB from protocol queue
732 DEQUEUE(vcp
, struct vccb
, vc_sigelem
, usp
->us_vccq
);
737 vcp
->vc_ustate
= VCCU_NULL
;
738 vcp
->vc_sstate
= UNI_NULL
;
739 atm_free((caddr_t
)vcp
);
742 * If we're detaching and this was the last VCC queued,
743 * get rid of the protocol instance
745 if ((usp
->us_state
== UNISIG_DETACH
) &&
746 (Q_HEAD(usp
->us_vccq
, struct vccb
) == NULL
)) {
747 struct sigmgr
*smp
= pip
->pif_sigmgr
;
750 pip
->pif_sigmgr
= NULL
;
751 pip
->pif_siginst
= NULL
;
754 UNLINK((struct siginst
*)usp
, struct siginst
,
755 smp
->sm_prinst
, si_next
);
756 KM_FREE(usp
, sizeof(struct unisig
), M_DEVBUF
);
764 * UNISIG IOCTL support
766 * Function will be called from a critical section.
769 * code PF_ATM sub-operation code
770 * data pointer to code specific parameter data area
771 * arg1 pointer to code specific argument
775 * errno error processing request - reason indicated
779 unisig_ioctl(int code
, caddr_t data
, caddr_t arg1
)
781 struct atmdelreq
*adp
;
782 struct atminfreq
*aip
;
783 struct atmsetreq
*asp
;
785 struct unisig_vccb
*uvp
;
786 struct air_vcc_rsp rsp
;
790 int err
= 0, buf_len
, i
;
793 ATM_DEBUG1("unisig_ioctl: code=%d\n", code
);
802 adp
= (struct atmdelreq
*)data
;
803 usp
= (struct unisig
*)arg1
;
806 * Don't let a user close the UNISIG signalling VC
808 vpi
= adp
->adr_pvc_vpi
;
809 vci
= adp
->adr_pvc_vci
;
810 if ((vpi
== UNISIG_SIG_VPI
&& vci
== UNISIG_SIG_VCI
))
816 for (uvp
= Q_HEAD(usp
->us_vccq
, struct unisig_vccb
); uvp
;
817 uvp
= Q_NEXT(uvp
, struct unisig_vccb
, uv_sigelem
)) {
818 if ((uvp
->uv_vpi
== vpi
) && (uvp
->uv_vci
== vci
))
829 if (!(uvp
->uv_type
& VCC_PVC
)) {
834 if (!(uvp
->uv_type
& VCC_SVC
)) {
841 * Schedule VCC termination
843 unisig_cause_attr_from_user(&uvp
->uv_connvc
->cvc_attr
,
844 T_ATM_CAUSE_UNSPECIFIED_NORMAL
);
845 err
= unisig_abort((struct vccb
*)uvp
);
850 * Return VCC information
852 aip
= (struct atminfreq
*)data
;
853 usp
= (struct unisig
*)arg1
;
855 buf_addr
= aip
->air_buf_addr
;
856 buf_len
= aip
->air_buf_len
;
859 * Loop through the VCC queue
861 for (uvp
= Q_HEAD(usp
->us_vccq
, struct unisig_vccb
); uvp
;
862 uvp
= Q_NEXT(uvp
, struct unisig_vccb
, uv_sigelem
)) {
864 * Make sure there's room in the user's buffer
866 if (buf_len
< sizeof(rsp
)) {
872 * Fill out the response struct for the VCC
874 ksnprintf(rsp
.avp_intf
,
875 sizeof(rsp
.avp_intf
), "%s%d",
876 usp
->us_pif
->pif_name
,
877 usp
->us_pif
->pif_unit
);
878 rsp
.avp_vpi
= uvp
->uv_vpi
;
879 rsp
.avp_vci
= uvp
->uv_vci
;
880 rsp
.avp_type
= uvp
->uv_type
;
881 rsp
.avp_aal
= uvp
->uv_connvc
->cvc_attr
.aal
.type
;
882 rsp
.avp_sig_proto
= uvp
->uv_proto
;
883 cop
= uvp
->uv_connvc
->cvc_conn
;
885 rsp
.avp_encaps
= cop
->co_mpx
;
888 rsp
.avp_state
= uvp
->uv_sstate
;
889 if (uvp
->uv_connvc
->cvc_flags
& CVCF_CALLER
) {
890 rsp
.avp_daddr
= uvp
->uv_connvc
->cvc_attr
.called
.addr
;
892 rsp
.avp_daddr
= uvp
->uv_connvc
->cvc_attr
.calling
.addr
;
894 rsp
.avp_dsubaddr
.address_format
= T_ATM_ABSENT
;
895 rsp
.avp_dsubaddr
.address_length
= 0;
896 rsp
.avp_ipdus
= uvp
->uv_ipdus
;
897 rsp
.avp_opdus
= uvp
->uv_opdus
;
898 rsp
.avp_ibytes
= uvp
->uv_ibytes
;
899 rsp
.avp_obytes
= uvp
->uv_obytes
;
900 rsp
.avp_ierrors
= uvp
->uv_ierrors
;
901 rsp
.avp_oerrors
= uvp
->uv_oerrors
;
902 rsp
.avp_tstamp
= uvp
->uv_tstamp
;
903 KM_ZERO(rsp
.avp_owners
,
904 sizeof(rsp
.avp_owners
));
905 for (i
= 0; cop
&& i
< sizeof(rsp
.avp_owners
);
907 i
+= T_ATM_APP_NAME_LEN
+1) {
908 strncpy(&rsp
.avp_owners
[i
],
909 cop
->co_endpt
->ep_getname(cop
->co_toku
),
914 * Copy the response into the user's buffer
916 if ((err
= copyout((caddr_t
)&rsp
, buf_addr
,
919 buf_addr
+= sizeof(rsp
);
920 buf_len
-= sizeof(rsp
);
924 * Update the buffer pointer and length
926 aip
->air_buf_addr
= buf_addr
;
927 aip
->air_buf_len
= buf_len
;
934 * Get ARP table information or get/set ARP server address
936 err
= uniarp_ioctl(code
, data
, arg1
);
943 asp
= (struct atmsetreq
*)data
;
944 usp
= (struct unisig
*)arg1
;
946 if (usp
->us_addr
.address_format
!= T_ATM_ABSENT
) {
947 if (KM_CMP(asp
->asr_prf_pref
, usp
->us_addr
.address
,
948 sizeof(asp
->asr_prf_pref
)) != 0)
952 usp
->us_addr
.address_format
= T_ATM_ENDSYS_ADDR
;
953 usp
->us_addr
.address_length
= sizeof(Atm_addr_nsap
);
954 KM_COPY(&pip
->pif_macaddr
,
955 ((Atm_addr_nsap
*)usp
->us_addr
.address
)->aan_esi
,
956 sizeof(pip
->pif_macaddr
));
957 KM_COPY((caddr_t
) asp
->asr_prf_pref
,
958 &((Atm_addr_nsap
*)usp
->us_addr
.address
)->aan_afi
,
959 sizeof(asp
->asr_prf_pref
));
960 log(LOG_INFO
, "uni: set address %s on interface %s\n",
961 unisig_addr_print(&usp
->us_addr
),
965 * Pass event to signalling manager state machine
967 err
= unisig_sigmgr_state(usp
, UNISIG_SIGMGR_ADDR_SET
,
971 * Clean up if there was an error
974 usp
->us_addr
.address_format
= T_ATM_ABSENT
;
975 usp
->us_addr
.address_length
= 0;
980 * Inform ARP code of new address
982 uniarp_ifaddr((struct siginst
*)usp
);