fetch.9: Minor fixes.
[dragonfly.git] / sys / netproto / atm / sigpvc / sigpvc_if.c
blob95ec097e57e742cc231fb609aa451d18deb8ffa0
1 /*
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/sigpvc/sigpvc_if.c,v 1.7 2000/01/17 20:49:46 mks Exp $
27 * @(#) $DragonFly: src/sys/netproto/atm/sigpvc/sigpvc_if.c,v 1.11 2006/12/20 18:14:43 dillon Exp $
31 * PVC-only Signalling Manager
32 * ---------------------------
34 * External interfaces to SigPVC manager. Includes support for
35 * running as a loadable kernel module.
39 #ifndef ATM_SIGPVC_MODULE
40 #include "opt_atm.h"
41 #endif
43 #include <netproto/atm/kern_include.h>
45 #include "sigpvc_var.h"
48 * Global variables
50 struct sp_info sigpvc_vcpool = {
51 "sigpvc vcc pool", /* si_name */
52 sizeof(struct sigpvc_vccb), /* si_blksiz */
53 10, /* si_blkcnt */
54 50 /* si_maxallow */
58 * Local functions
60 static int sigpvc_start (void);
61 static int sigpvc_stop (void);
62 static int sigpvc_attach (struct sigmgr *, struct atm_pif *);
63 static int sigpvc_detach (struct atm_pif *);
64 static int sigpvc_setup (Atm_connvc *, int *);
65 static int sigpvc_release (struct vccb *, int *);
66 static int sigpvc_free (struct vccb *);
67 static int sigpvc_ioctl (int, caddr_t, caddr_t);
70 * Local variables
72 static int sigpvc_registered = 0;
73 static struct sigmgr sigpvc_mgr = {
74 NULL,
75 ATM_SIG_PVC,
76 NULL,
77 sigpvc_attach,
78 sigpvc_detach,
79 sigpvc_setup,
80 NULL,
81 NULL,
82 sigpvc_release,
83 sigpvc_free,
84 sigpvc_ioctl
87 static struct attr_cause sigpvc_cause = {
88 T_ATM_PRESENT,
90 T_ATM_ITU_CODING,
91 T_ATM_LOC_USER,
92 T_ATM_CAUSE_UNSPECIFIED_NORMAL,
93 {0, 0, 0, 0}
99 * Initialize sigpvc processing
101 * This will be called during module loading. We'll just register
102 * the sigpvc protocol descriptor and wait for a SigPVC ATM interface
103 * to come online.
105 * Arguments:
106 * none
108 * Returns:
109 * 0 startup was successful
110 * errno startup failed - reason indicated
113 static int
114 sigpvc_start(void)
116 int err = 0;
119 * Verify software version
121 if (atm_version != ATM_VERSION) {
122 log(LOG_ERR, "version mismatch: sigpvc=%d.%d kernel=%d.%d\n",
123 ATM_VERS_MAJ(ATM_VERSION), ATM_VERS_MIN(ATM_VERSION),
124 ATM_VERS_MAJ(atm_version), ATM_VERS_MIN(atm_version));
125 return (EINVAL);
129 * Register ourselves with system
131 err = atm_sigmgr_register(&sigpvc_mgr);
132 if (err == 0)
133 sigpvc_registered = 1;
135 return (err);
140 * Halt sigpvc processing
142 * This should be called just prior to unloading the module from
143 * memory. All sigpvc interfaces must be deregistered before the
144 * protocol can be shutdown.
146 * Arguments:
147 * none
149 * Returns:
150 * 0 shutdown was successful
151 * errno shutdown failed - reason indicated
154 static int
155 sigpvc_stop(void)
157 int err = 0;
159 crit_enter();
162 * Is protocol even setup?
164 if (sigpvc_registered) {
167 * Any protocol instances still registered??
169 if (sigpvc_mgr.sm_prinst) {
171 /* Yes, can't stop now */
172 err = EBUSY;
173 goto done;
177 * De-register from system
179 err = atm_sigmgr_deregister(&sigpvc_mgr);
180 sigpvc_registered = 0;
183 * Free up our vccb storage pool
185 atm_release_pool(&sigpvc_vcpool);
186 } else
187 err = ENXIO;
189 done:
190 crit_exit();
191 return (err);
196 * Attach a SigPVC-controlled interface
198 * Each ATM physical interface must be attached with the signalling manager for
199 * the interface's signalling protocol (via the atm_sigmgr_attach function).
200 * This function will handle the attachment for SigPVC-controlled interfaces.
201 * A new sigpvc protocol instance will be created and then we'll just sit
202 * around waiting for connection requests.
204 * Function must be called from a critical section.
206 * Arguments:
207 * smp pointer to sigpvc signalling manager control block
208 * pip pointer to atm physical interface control block
210 * Returns:
211 * 0 attach successful
212 * errno attach failed - reason indicated
215 static int
216 sigpvc_attach(struct sigmgr *smp, struct atm_pif *pip)
218 int err = 0;
219 struct sigpvc *pvp = NULL;
222 * Allocate sigpvc protocol instance control block
224 pvp = KM_ALLOC(sizeof(struct sigpvc), M_DEVBUF, M_INTWAIT | M_NULLOK);
225 if (pvp == NULL) {
226 err = ENOMEM;
227 goto done;
229 KM_ZERO(pvp, sizeof(struct sigpvc));
232 * Link instance into manager's chain
234 LINK2TAIL((struct siginst *)pvp, struct siginst,
235 smp->sm_prinst, si_next);
238 * Finally, set state and link in interface
240 pvp->pv_pif = pip;
241 pvp->pv_state = SIGPVC_ACTIVE;
242 pip->pif_sigmgr = smp;
243 pip->pif_siginst = (struct siginst *)pvp;
245 done:
247 * Reset our work if attach fails
249 if (err) {
250 pip->pif_sigmgr = NULL;
251 pip->pif_siginst = NULL;
252 if (pvp) {
253 UNLINK((struct siginst *)pvp, struct siginst,
254 smp->sm_prinst, si_next);
255 KM_FREE(pvp, sizeof(struct sigpvc), M_DEVBUF);
259 return (err);
264 * Detach a SigPVC-controlled interface
266 * Each ATM physical interface may be detached from its signalling manager
267 * (via the atm_sigmgr_detach function). This function will handle the
268 * detachment for all SigPVC-controlled interfaces. All circuits will be
269 * immediately terminated.
271 * Function must be called from a critical section.
273 * Arguments:
274 * pip pointer to atm physical interface control block
276 * Returns:
277 * 0 detach successful
278 * errno detach failed - reason indicated
281 static int
282 sigpvc_detach(struct atm_pif *pip)
284 struct sigpvc *pvp;
285 struct vccb *vcp, *vnext;
288 * Get SigPVC protocol instance
290 pvp = (struct sigpvc *)pip->pif_siginst;
293 * Terminate all of our VCCs
295 for (vcp = Q_HEAD(pvp->pv_vccq, struct vccb); vcp; vcp = vnext){
296 u_char oustate;
298 vnext = Q_NEXT(vcp, struct vccb, vc_sigelem);
301 * Close VCC and notify owner
303 oustate = vcp->vc_ustate;
304 sigpvc_close_vcc(vcp);
305 if (oustate == VCCU_OPEN) {
306 vcp->vc_connvc->cvc_attr.cause = sigpvc_cause;
307 atm_cm_cleared(vcp->vc_connvc);
312 * If there are no vcc's queued, then get rid of the protocol
313 * instance.
315 if (Q_HEAD(pvp->pv_vccq, struct vccb) == NULL) {
316 struct sigmgr *smp = pip->pif_sigmgr;
318 pip->pif_sigmgr = NULL;
319 pip->pif_siginst = NULL;
320 UNLINK((struct siginst *)pvp, struct siginst, smp->sm_prinst,
321 si_next);
322 KM_FREE(pvp, sizeof(struct sigpvc), M_DEVBUF);
323 } else {
326 * Otherwise, set new state indicating detach in progress.
327 * The protocol instance will be freed during sigpvc_free
328 * processing for the last queued vcc.
330 pvp->pv_state = SIGPVC_DETACH;
333 return (0);
338 * Open a SigPVC ATM Connection
340 * All service user requests to open a VC connection (via atm_open_connection)
341 * over an ATM interface attached to the SigPVC signalling manager are handled
342 * here. Only PVC requests are allowed.
344 * Function will be called from a critical section.
346 * Arguments:
347 * cvp pointer to CM's connection VCC
348 * errp location to store an error code if CALL_FAILED is returned
350 * Returns:
351 * CALL_PROCEEDING - connection establishment is in progress
352 * CALL_FAILED - connection establishment failed
353 * CALL_CONNECTED - connection has been successfully established
356 static int
357 sigpvc_setup(Atm_connvc *cvp, int *errp)
359 struct sigpvc *pvp =
360 (struct sigpvc *)cvp->cvc_attr.nif->nif_pif->pif_siginst;
361 int ret;
364 * See what signalling has to say
366 switch (pvp->pv_state) {
368 case SIGPVC_ACTIVE:
369 break;
371 default:
372 *errp = ENXIO;
373 ret = CALL_FAILED;
374 goto done;
378 * Open requested type of connection
380 switch (cvp->cvc_attr.called.addr.address_format) {
382 case T_ATM_PVC_ADDR:
384 * Create a PVC
386 ret = sigpvc_create_pvc(pvp, cvp, errp);
387 break;
389 default:
390 *errp = EPROTONOSUPPORT;
391 ret = CALL_FAILED;
394 done:
395 return (ret);
400 * Close a SigPVC ATM Connection
402 * All service user requests to terminate a previously open VC connection
403 * (via the atm_close_connection function), which is running over an interface
404 * attached to the SigPVC signalling manager, are handled here.
406 * Function will be called from a critical section.
408 * Arguments:
409 * vcp pointer to connection's VC control block
410 * errp location to store an error code if CALL_FAILED is returned
412 * Returns:
413 * CALL_PROCEEDING - connection termination is in progress
414 * CALL_FAILED - connection termination failed
415 * CALL_CLEARED - connection has been successfully terminated
418 static int
419 sigpvc_release(struct vccb *vcp, int *errp)
423 * Make sure VCC is open
425 if ((vcp->vc_sstate == VCCS_NULL) || (vcp->vc_sstate == VCCS_FREE) ||
426 (vcp->vc_ustate == VCCU_NULL) || (vcp->vc_ustate == VCCU_CLOSED)) {
427 *errp = EALREADY;
428 return (CALL_FAILED);
432 * Not much else to do except close the vccb
434 sigpvc_close_vcc(vcp);
436 return (CALL_CLEARED);
441 * Free SigPVC ATM Connection Resources
443 * All service user requests to free the resources of a closed VCC connection
444 * (via the atm_free_connection function), which is running over an interface
445 * attached to the SigPVC signalling manager, are handled here.
447 * Function will be called from a critical section.
449 * Arguments:
450 * vcp pointer to connection's VCC control block
452 * Returns:
453 * 0 connection free was successful
454 * errno connection free failed - reason indicated
457 static int
458 sigpvc_free(struct vccb *vcp)
460 struct atm_pif *pip = vcp->vc_pif;
461 struct sigpvc *pvp = (struct sigpvc *)pip->pif_siginst;
464 * Make sure VCC has been closed
466 if ((vcp->vc_ustate != VCCU_CLOSED) || (vcp->vc_sstate != VCCS_FREE))
467 return (EEXIST);
470 * Remove vccb from protocol queue
472 DEQUEUE(vcp, struct vccb, vc_sigelem, pvp->pv_vccq);
475 * Free vccb storage
477 vcp->vc_ustate = VCCU_NULL;
478 vcp->vc_sstate = VCCS_NULL;
479 atm_free((caddr_t)vcp);
482 * If we're detaching and this was the last vcc queued,
483 * get rid of the protocol instance
485 if ((pvp->pv_state == SIGPVC_DETACH) &&
486 (Q_HEAD(pvp->pv_vccq, struct vccb) == NULL)) {
487 struct sigmgr *smp = pip->pif_sigmgr;
489 pip->pif_sigmgr = NULL;
490 pip->pif_siginst = NULL;
491 UNLINK((struct siginst *)pvp, struct siginst, smp->sm_prinst,
492 si_next);
493 KM_FREE(pvp, sizeof(struct sigpvc), M_DEVBUF);
496 return (0);
501 * Process Signalling Manager PF_ATM ioctls
503 * Function will be called from a critical section.
505 * Arguments:
506 * code PF_ATM sub-operation code
507 * data pointer to code specific parameter data area
508 * arg1 pointer to code specific argument
510 * Returns:
511 * 0 request procesed
512 * errno error processing request - reason indicated
515 static int
516 sigpvc_ioctl(int code, caddr_t data, caddr_t arg1)
518 struct atmdelreq *adp;
519 struct atminfreq *aip;
520 struct air_vcc_rsp avr;
521 struct sigpvc *pvp;
522 struct vccb *vcp;
523 Atm_connection *cop;
524 caddr_t cp;
525 u_int vpi, vci;
526 int i, space, err = 0;
529 switch (code) {
531 case AIOCS_DEL_PVC:
533 * Delete a PVC
535 adp = (struct atmdelreq *)data;
536 pvp = (struct sigpvc *)arg1;
539 * Find requested VCC
541 vpi = adp->adr_pvc_vpi;
542 vci = adp->adr_pvc_vci;
543 for (vcp = Q_HEAD(pvp->pv_vccq, struct vccb); vcp;
544 vcp = Q_NEXT(vcp, struct vccb, vc_sigelem)) {
545 if ((vcp->vc_vpi == vpi) && (vcp->vc_vci == vci))
546 break;
548 if (vcp == NULL)
549 return (ENOENT);
552 * Schedule VCC termination
554 err = atm_cm_abort(vcp->vc_connvc, &sigpvc_cause.v);
555 break;
557 case AIOCS_DEL_SVC:
559 * Delete a SVC
561 err = ENOENT;
562 break;
564 case AIOCS_INF_VCC:
566 * Get VCC information
568 aip = (struct atminfreq *)data;
569 pvp = (struct sigpvc *)arg1;
571 cp = aip->air_buf_addr;
572 space = aip->air_buf_len;
575 * Get info for all VCCs on interface
577 for (vcp = Q_HEAD(pvp->pv_vccq, struct vccb); vcp;
578 vcp = Q_NEXT(vcp, struct vccb, vc_sigelem)) {
580 * Make sure there's room in user buffer
582 if (space < sizeof(avr)) {
583 err = ENOSPC;
584 break;
588 * Fill in info to be returned
590 ksnprintf(avr.avp_intf, sizeof(avr.avp_intf),
591 "%s%d",
592 pvp->pv_pif->pif_name, pvp->pv_pif->pif_unit);
593 avr.avp_vpi = vcp->vc_vpi;
594 avr.avp_vci = vcp->vc_vci;
595 avr.avp_type = vcp->vc_type;
596 avr.avp_sig_proto = ATM_SIG_PVC;
597 avr.avp_aal = vcp->vc_connvc->cvc_attr.aal.type;
598 cop = vcp->vc_connvc->cvc_conn;
599 if (cop)
600 avr.avp_encaps = cop->co_mpx;
601 else
602 avr.avp_encaps = 0;
603 KM_ZERO(avr.avp_owners, sizeof(avr.avp_owners));
604 for (i = 0; cop && i < sizeof(avr.avp_owners);
605 cop = cop->co_next,
606 i += T_ATM_APP_NAME_LEN+1) {
607 strncpy(&avr.avp_owners[i],
608 cop->co_endpt->ep_getname(cop->co_toku),
609 T_ATM_APP_NAME_LEN);
611 avr.avp_state = vcp->vc_sstate;
612 avr.avp_daddr.address_format = T_ATM_ABSENT;
613 avr.avp_dsubaddr.address_format = T_ATM_ABSENT;
614 avr.avp_ipdus = vcp->vc_ipdus;
615 avr.avp_opdus = vcp->vc_opdus;
616 avr.avp_ibytes = vcp->vc_ibytes;
617 avr.avp_obytes = vcp->vc_obytes;
618 avr.avp_ierrors = vcp->vc_ierrors;
619 avr.avp_oerrors = vcp->vc_oerrors;
620 avr.avp_tstamp = vcp->vc_tstamp;
623 * Copy data to user buffer and update buffer info
625 if ((err = copyout((caddr_t)&avr, cp, sizeof(avr))) != 0)
626 break;
627 cp += sizeof(avr);
628 space -= sizeof(avr);
632 * Update buffer pointer/count
634 aip->air_buf_addr = cp;
635 aip->air_buf_len = space;
636 break;
638 case AIOCS_INF_ARP:
639 case AIOCS_INF_ASV:
641 * Get ARP table/server information
643 /* We don't maintain any ARP information */
644 break;
646 default:
647 err = EOPNOTSUPP;
650 return (err);
654 #ifdef ATM_SIGPVC_MODULE
656 *******************************************************************
658 * Loadable Module Support
660 *******************************************************************
662 static int sigpvc_doload (void);
663 static int sigpvc_dounload (void);
666 * Generic module load processing
668 * This function is called by an OS-specific function when this
669 * module is being loaded.
671 * Arguments:
672 * none
674 * Returns:
675 * 0 load was successful
676 * errno load failed - reason indicated
679 static int
680 sigpvc_doload(void)
682 int err = 0;
685 * Start us up
687 err = sigpvc_start();
688 if (err)
689 /* Problems, clean up */
690 sigpvc_stop();
692 return (err);
697 * Generic module unload processing
699 * This function is called by an OS-specific function when this
700 * module is being unloaded.
702 * Arguments:
703 * none
705 * Returns:
706 * 0 unload was successful
707 * errno unload failed - reason indicated
710 static int
711 sigpvc_dounload(void)
713 int err = 0;
716 * OK, try to clean up our mess
718 err = sigpvc_stop();
720 return (err);
723 #include <sys/exec.h>
724 #include <sys/sysent.h>
725 #include <sys/lkm.h>
728 * Loadable miscellaneous module description
730 MOD_MISC(sigpvc);
734 * Loadable module support "load" entry point
736 * This is the routine called by the lkm driver whenever the
737 * modload(1) command is issued for this module.
739 * Arguments:
740 * lkmtp pointer to lkm drivers's structure
741 * cmd lkm command code
743 * Returns:
744 * 0 command was successful
745 * errno command failed - reason indicated
748 static int
749 sigpvc_load(struct lkm_table *lkmtp, int cmd)
751 return(sigpvc_doload());
756 * Loadable module support "unload" entry point
758 * This is the routine called by the lkm driver whenever the
759 * modunload(1) command is issued for this module.
761 * Arguments:
762 * lkmtp pointer to lkm drivers's structure
763 * cmd lkm command code
765 * Returns:
766 * 0 command was successful
767 * errno command failed - reason indicated
770 static int
771 sigpvc_unload(struct lkm_table *lkmtp, int cmd)
773 return(sigpvc_dounload());
778 * Loadable module support entry point
780 * This is the routine called by the lkm driver for all loadable module
781 * functions for this driver. This routine name must be specified
782 * on the modload(1) command. This routine will be called whenever the
783 * modload(1), modunload(1) or modstat(1) commands are issued for this
784 * module.
786 * Arguments:
787 * lkmtp pointer to lkm drivers's structure
788 * cmd lkm command code
789 * ver lkm version
791 * Returns:
792 * 0 command was successful
793 * errno command failed - reason indicated
797 sigpvc_mod(struct lkm_table *lkmtp, int cmd, int ver)
799 MOD_DISPATCH(sigpvc, lkmtp, cmd, ver,
800 sigpvc_load, sigpvc_unload, lkm_nullcmd);
803 #else /* !ATM_SIGPVC_MODULE */
806 *******************************************************************
808 * Kernel Compiled Module Support
810 *******************************************************************
812 static void sigpvc_doload (void *);
814 SYSINIT(atmsigpvc, SI_SUB_PROTO_END, SI_ORDER_ANY, sigpvc_doload, NULL)
817 * Kernel initialization
819 * Arguments:
820 * arg Not used
822 * Returns:
823 * none
826 static void
827 sigpvc_doload(void *arg)
829 int err = 0;
832 * Start us up
834 err = sigpvc_start();
835 if (err) {
836 /* Problems, clean up */
837 sigpvc_stop();
839 log(LOG_ERR, "ATM SIGPVC unable to initialize (%d)!!\n", err);
841 return;
843 #endif /* ATM_SIGPVC_MODULE */