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.
27 * PVC-only Signalling Manager
28 * ---------------------------
30 * External interfaces to SigPVC manager. Includes support for
31 * running as a loadable kernel module.
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
37 #ifndef ATM_SIGPVC_MODULE
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/types.h>
44 #include <sys/errno.h>
45 #include <sys/malloc.h>
47 #include <sys/kernel.h>
48 #include <sys/socket.h>
49 #include <sys/socketvar.h>
50 #include <sys/syslog.h>
52 #include <netatm/port.h>
53 #include <netatm/queue.h>
54 #include <netatm/atm.h>
55 #include <netatm/atm_sys.h>
56 #include <netatm/atm_sap.h>
57 #include <netatm/atm_cm.h>
58 #include <netatm/atm_if.h>
59 #include <netatm/atm_vc.h>
60 #include <netatm/atm_ioctl.h>
61 #include <netatm/atm_sigmgr.h>
62 #include <netatm/atm_stack.h>
63 #include <netatm/atm_pcb.h>
64 #include <netatm/atm_var.h>
66 #include <netatm/sigpvc/sigpvc_var.h>
73 uma_zone_t sigpvc_vc_zone;
78 static int sigpvc_start(void);
79 static int sigpvc_stop(void);
80 static int sigpvc_attach(struct sigmgr *, struct atm_pif *);
81 static int sigpvc_detach(struct atm_pif *);
82 static int sigpvc_setup(Atm_connvc *, int *);
83 static int sigpvc_release(struct vccb *, int *);
84 static int sigpvc_free(struct vccb *);
85 static int sigpvc_ioctl(int, caddr_t, caddr_t);
90 static int sigpvc_registered = 0;
91 static struct sigmgr sigpvc_mgr = {
105 static struct attr_cause sigpvc_cause = {
110 T_ATM_CAUSE_UNSPECIFIED_NORMAL,
117 * Initialize sigpvc processing
119 * This will be called during module loading. We'll just register
120 * the sigpvc protocol descriptor and wait for a SigPVC ATM interface
127 * 0 startup was successful
128 * errno startup failed - reason indicated
137 * Verify software version
139 if (atm_version != ATM_VERSION) {
140 log(LOG_ERR, "version mismatch: sigpvc=%d.%d kernel=%d.%d\n",
141 ATM_VERS_MAJ(ATM_VERSION), ATM_VERS_MIN(ATM_VERSION),
142 ATM_VERS_MAJ(atm_version), ATM_VERS_MIN(atm_version));
146 sigpvc_vc_zone = uma_zcreate("sigpvc vc", sizeof(struct sigpvc_vccb),
147 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
148 if (sigpvc_vc_zone == NULL)
152 * Register ourselves with system
154 err = atm_sigmgr_register(&sigpvc_mgr);
156 sigpvc_registered = 1;
163 * Halt sigpvc processing
165 * This should be called just prior to unloading the module from
166 * memory. All sigpvc interfaces must be deregistered before the
167 * protocol can be shutdown.
173 * 0 shutdown was successful
174 * errno shutdown failed - reason indicated
184 * Is protocol even setup?
186 if (sigpvc_registered) {
189 * Any protocol instances still registered??
191 if (sigpvc_mgr.sm_prinst) {
193 /* Yes, can't stop now */
199 * De-register from system
201 err = atm_sigmgr_deregister(&sigpvc_mgr);
202 sigpvc_registered = 0;
205 * Free up our vccb storage pool
207 uma_zdestroy(sigpvc_vc_zone);
218 * Attach a SigPVC-controlled interface
220 * Each ATM physical interface must be attached with the signalling manager for
221 * the interface's signalling protocol (via the atm_sigmgr_attach function).
222 * This function will handle the attachment for SigPVC-controlled interfaces.
223 * A new sigpvc protocol instance will be created and then we'll just sit
224 * around waiting for connection requests.
226 * Function must be called at splnet.
229 * smp pointer to sigpvc signalling manager control block
230 * pip pointer to atm physical interface control block
233 * 0 attach successful
234 * errno attach failed - reason indicated
238 sigpvc_attach(smp, pip)
243 struct sigpvc *pvp = NULL;
246 * Allocate sigpvc protocol instance control block
248 pvp = malloc(sizeof(struct sigpvc), M_DEVBUF, M_NOWAIT | M_ZERO);
255 * Link instance into manager's chain
257 LINK2TAIL((struct siginst *)pvp, struct siginst,
258 smp->sm_prinst, si_next);
261 * Finally, set state and link in interface
264 pvp->pv_state = SIGPVC_ACTIVE;
265 pip->pif_sigmgr = smp;
266 pip->pif_siginst = (struct siginst *)pvp;
270 * Reset our work if attach fails
273 pip->pif_sigmgr = NULL;
274 pip->pif_siginst = NULL;
276 UNLINK((struct siginst *)pvp, struct siginst,
277 smp->sm_prinst, si_next);
287 * Detach a SigPVC-controlled interface
289 * Each ATM physical interface may be detached from its signalling manager
290 * (via the atm_sigmgr_detach function). This function will handle the
291 * detachment for all SigPVC-controlled interfaces. All circuits will be
292 * immediately terminated.
294 * Function must be called at splnet.
297 * pip pointer to atm physical interface control block
300 * 0 detach successful
301 * errno detach failed - reason indicated
309 struct vccb *vcp, *vnext;
312 * Get SigPVC protocol instance
314 pvp = (struct sigpvc *)pip->pif_siginst;
317 * Terminate all of our VCCs
319 for (vcp = Q_HEAD(pvp->pv_vccq, struct vccb); vcp; vcp = vnext){
322 vnext = Q_NEXT(vcp, struct vccb, vc_sigelem);
325 * Close VCC and notify owner
327 oustate = vcp->vc_ustate;
328 sigpvc_close_vcc(vcp);
329 if (oustate == VCCU_OPEN) {
330 vcp->vc_connvc->cvc_attr.cause = sigpvc_cause;
331 atm_cm_cleared(vcp->vc_connvc);
336 * If there are no vcc's queued, then get rid of the protocol
339 if (Q_HEAD(pvp->pv_vccq, struct vccb) == NULL) {
340 struct sigmgr *smp = pip->pif_sigmgr;
342 pip->pif_sigmgr = NULL;
343 pip->pif_siginst = NULL;
344 UNLINK((struct siginst *)pvp, struct siginst, smp->sm_prinst,
350 * Otherwise, set new state indicating detach in progress.
351 * The protocol instance will be freed during sigpvc_free
352 * processing for the last queued vcc.
354 pvp->pv_state = SIGPVC_DETACH;
362 * Open a SigPVC ATM Connection
364 * All service user requests to open a VC connection (via atm_open_connection)
365 * over an ATM interface attached to the SigPVC signalling manager are handled
366 * here. Only PVC requests are allowed.
368 * Function will be called at splnet.
371 * cvp pointer to CM's connection VCC
372 * errp location to store an error code if CALL_FAILED is returned
375 * CALL_PROCEEDING - connection establishment is in progress
376 * CALL_FAILED - connection establishment failed
377 * CALL_CONNECTED - connection has been successfully established
381 sigpvc_setup(cvp, errp)
386 (struct sigpvc *)cvp->cvc_attr.nif->nif_pif->pif_siginst;
390 * See what signalling has to say
392 switch (pvp->pv_state) {
404 * Open requested type of connection
406 switch (cvp->cvc_attr.called.addr.address_format) {
412 ret = sigpvc_create_pvc(pvp, cvp, errp);
416 *errp = EPROTONOSUPPORT;
426 * Close a SigPVC ATM Connection
428 * All service user requests to terminate a previously open VC connection
429 * (via the atm_close_connection function), which is running over an interface
430 * attached to the SigPVC signalling manager, are handled here.
432 * Function will be called at splnet.
435 * vcp pointer to connection's VC control block
436 * errp location to store an error code if CALL_FAILED is returned
439 * CALL_PROCEEDING - connection termination is in progress
440 * CALL_FAILED - connection termination failed
441 * CALL_CLEARED - connection has been successfully terminated
445 sigpvc_release(vcp, errp)
451 * Make sure VCC is open
453 if ((vcp->vc_sstate == VCCS_NULL) || (vcp->vc_sstate == VCCS_FREE) ||
454 (vcp->vc_ustate == VCCU_NULL) || (vcp->vc_ustate == VCCU_CLOSED)) {
456 return (CALL_FAILED);
460 * Not much else to do except close the vccb
462 sigpvc_close_vcc(vcp);
464 return (CALL_CLEARED);
469 * Free SigPVC ATM Connection Resources
471 * All service user requests to free the resources of a closed VCC connection
472 * (via the atm_free_connection function), which is running over an interface
473 * attached to the SigPVC signalling manager, are handled here.
475 * Function will be called at splnet.
478 * vcp pointer to connection's VCC control block
481 * 0 connection free was successful
482 * errno connection free failed - reason indicated
489 struct atm_pif *pip = vcp->vc_pif;
490 struct sigpvc *pvp = (struct sigpvc *)pip->pif_siginst;
493 * Make sure VCC has been closed
495 if ((vcp->vc_ustate != VCCU_CLOSED) || (vcp->vc_sstate != VCCS_FREE))
499 * Remove vccb from protocol queue
501 DEQUEUE(vcp, struct vccb, vc_sigelem, pvp->pv_vccq);
506 vcp->vc_ustate = VCCU_NULL;
507 vcp->vc_sstate = VCCS_NULL;
508 uma_zfree(sigpvc_vc_zone, vcp);
511 * If we're detaching and this was the last vcc queued,
512 * get rid of the protocol instance
514 if ((pvp->pv_state == SIGPVC_DETACH) &&
515 (Q_HEAD(pvp->pv_vccq, struct vccb) == NULL)) {
516 struct sigmgr *smp = pip->pif_sigmgr;
518 pip->pif_sigmgr = NULL;
519 pip->pif_siginst = NULL;
520 UNLINK((struct siginst *)pvp, struct siginst, smp->sm_prinst,
530 * Process Signalling Manager PF_ATM ioctls
532 * Function will be called at splnet.
535 * code PF_ATM sub-operation code
536 * data pointer to code specific parameter data area
537 * arg1 pointer to code specific argument
541 * errno error processing request - reason indicated
545 sigpvc_ioctl(code, data, arg1)
550 struct atmdelreq *adp;
551 struct atminfreq *aip;
552 struct air_vcc_rsp avr;
569 adp = (struct atmdelreq *)data;
570 pvp = (struct sigpvc *)arg1;
575 vpi = adp->adr_pvc_vpi;
576 vci = adp->adr_pvc_vci;
577 for (vcp = Q_HEAD(pvp->pv_vccq, struct vccb); vcp;
578 vcp = Q_NEXT(vcp, struct vccb, vc_sigelem)) {
579 if ((vcp->vc_vpi == vpi) && (vcp->vc_vci == vci))
586 * Schedule VCC termination
588 err = atm_cm_abort(vcp->vc_connvc, &sigpvc_cause.v);
600 * Get VCC information
602 aip = (struct atminfreq *)data;
603 pvp = (struct sigpvc *)arg1;
605 cp = aip->air_buf_addr;
606 space = aip->air_buf_len;
609 * Get info for all VCCs on interface
611 for (vcp = Q_HEAD(pvp->pv_vccq, struct vccb); vcp;
612 vcp = Q_NEXT(vcp, struct vccb, vc_sigelem)) {
614 * Make sure there's room in user buffer
616 if (space < sizeof(avr)) {
622 * Fill in info to be returned
624 (void) snprintf(avr.avp_intf, sizeof(avr.avp_intf),
626 pvp->pv_pif->pif_name, pvp->pv_pif->pif_unit);
627 avr.avp_vpi = vcp->vc_vpi;
628 avr.avp_vci = vcp->vc_vci;
629 avr.avp_type = vcp->vc_type;
630 avr.avp_sig_proto = ATM_SIG_PVC;
631 avr.avp_aal = vcp->vc_connvc->cvc_attr.aal.type;
632 cop = vcp->vc_connvc->cvc_conn;
634 avr.avp_encaps = cop->co_mpx;
637 bzero(avr.avp_owners, sizeof(avr.avp_owners));
638 for (tlen = 0; cop && tlen < sizeof(avr.avp_owners);
640 tlen += T_ATM_APP_NAME_LEN + 1) {
641 strncpy(&avr.avp_owners[tlen],
642 cop->co_endpt->ep_getname(cop->co_toku),
645 avr.avp_state = vcp->vc_sstate;
646 avr.avp_daddr.address_format = T_ATM_ABSENT;
647 avr.avp_dsubaddr.address_format = T_ATM_ABSENT;
648 avr.avp_ipdus = vcp->vc_ipdus;
649 avr.avp_opdus = vcp->vc_opdus;
650 avr.avp_ibytes = vcp->vc_ibytes;
651 avr.avp_obytes = vcp->vc_obytes;
652 avr.avp_ierrors = vcp->vc_ierrors;
653 avr.avp_oerrors = vcp->vc_oerrors;
654 avr.avp_tstamp = vcp->vc_tstamp;
657 * Copy data to user buffer and update buffer info
659 if ((err = copyout((caddr_t)&avr, cp, sizeof(avr))) != 0)
662 space -= sizeof(avr);
666 * Update buffer pointer/count
668 aip->air_buf_addr = cp;
669 aip->air_buf_len = space;
675 * Get ARP table/server information
677 /* We don't maintain any ARP information */
688 #ifdef ATM_SIGPVC_MODULE
690 *******************************************************************
692 * Loadable Module Support
694 *******************************************************************
696 static int sigpvc_doload(void);
697 static int sigpvc_dounload(void);
700 * Generic module load processing
702 * This function is called by an OS-specific function when this
703 * module is being loaded.
709 * 0 load was successful
710 * errno load failed - reason indicated
721 err = sigpvc_start();
723 /* Problems, clean up */
731 * Generic module unload processing
733 * This function is called by an OS-specific function when this
734 * module is being unloaded.
740 * 0 unload was successful
741 * errno unload failed - reason indicated
750 * OK, try to clean up our mess
760 #include <sys/exec.h>
761 #include <sys/sysent.h>
765 * Loadable miscellaneous module description
771 * Loadable module support "load" entry point
773 * This is the routine called by the lkm driver whenever the
774 * modload(1) command is issued for this module.
777 * lkmtp pointer to lkm drivers's structure
778 * cmd lkm command code
781 * 0 command was successful
782 * errno command failed - reason indicated
786 sigpvc_load(lkmtp, cmd)
787 struct lkm_table *lkmtp;
790 return(sigpvc_doload());
795 * Loadable module support "unload" entry point
797 * This is the routine called by the lkm driver whenever the
798 * modunload(1) command is issued for this module.
801 * lkmtp pointer to lkm drivers's structure
802 * cmd lkm command code
805 * 0 command was successful
806 * errno command failed - reason indicated
810 sigpvc_unload(lkmtp, cmd)
811 struct lkm_table *lkmtp;
814 return(sigpvc_dounload());
819 * Loadable module support entry point
821 * This is the routine called by the lkm driver for all loadable module
822 * functions for this driver. This routine name must be specified
823 * on the modload(1) command. This routine will be called whenever the
824 * modload(1), modunload(1) or modstat(1) commands are issued for this
828 * lkmtp pointer to lkm drivers's structure
829 * cmd lkm command code
833 * 0 command was successful
834 * errno command failed - reason indicated
838 sigpvc_mod(lkmtp, cmd, ver)
839 struct lkm_table *lkmtp;
843 MOD_DISPATCH(sigpvc, lkmtp, cmd, ver,
844 sigpvc_load, sigpvc_unload, lkm_nullcmd);
847 #else /* !ATM_SIGPVC_MODULE */
850 *******************************************************************
852 * Kernel Compiled Module Support
854 *******************************************************************
856 static void sigpvc_doload(void *);
858 SYSINIT(atmsigpvc, SI_SUB_PROTO_END, SI_ORDER_ANY, sigpvc_doload, NULL)
861 * Kernel initialization
871 sigpvc_doload(void *arg)
878 err = sigpvc_start();
880 /* Problems, clean up */
883 log(LOG_ERR, "ATM SIGPVC unable to initialize (%d)!!\n", err);
887 #endif /* ATM_SIGPVC_MODULE */