* Remove (void) casts for discarded return values.
[dragonfly.git] / sys / netproto / atm / spans / spans_if.c
1 /*
2  *
3  * ===================================
4  * HARP  |  Host ATM Research Platform
5  * ===================================
6  *
7  *
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.
12  *
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.
20  *
21  * Copyright 1994-1998 Network Computing Services, Inc.
22  *
23  * Copies of this Software may be made, however, the above copyright
24  * notice must be reproduced on all copies.
25  *
26  *      @(#) $FreeBSD: src/sys/netatm/spans/spans_if.c,v 1.6 1999/08/28 00:48:49 peter Exp $
27  *      @(#) $DragonFly: src/sys/netproto/atm/spans/spans_if.c,v 1.10 2006/01/14 13:36:39 swildner Exp $
28  */
29
30 /*
31  * SPANS Signalling Manager
32  * ---------------------------
33  *
34  * External interfaces to SPANS manager.  Includes support for
35  * running as a loadable kernel module.
36  *
37  */
38
39 #ifndef ATM_SPANS_MODULE
40 #include "opt_atm.h"
41 #endif
42
43 #include <netproto/atm/kern_include.h>
44
45 #include "spans_xdr.h"
46 #include "spans_var.h"
47
48 /*
49  * Global variables
50  */
51 struct sp_info  spans_vcpool = {
52         "spans vcc pool",               /* si_name */
53         sizeof(struct spans_vccb),      /* si_blksiz */
54         10,                             /* si_blkcnt */
55         50                              /* si_maxallow */
56 };
57
58 struct sp_info  spans_msgpool = {
59         "spans message pool",           /* si_name */
60         sizeof(spans_msg),              /* si_blksiz */
61         10,                             /* si_blkcnt */
62         50                              /* si_maxallow */
63 };
64
65 /*
66  * Local functions
67  */
68 static int      spans_start (void);
69 static int      spans_stop (void);
70 static int      spans_attach (struct sigmgr *, struct atm_pif *);
71 static int      spans_detach (struct atm_pif *);
72 static int      spans_setup (Atm_connvc *, int *);
73 static int      spans_release (struct vccb *, int *);
74 static int      spans_accept (struct vccb *, int *);
75 static int      spans_reject (struct vccb *, int *);
76 static int      spans_ioctl (int, caddr_t, caddr_t);
77
78 /*
79  * Local variables
80  */
81 static struct sigmgr    *spans_mgr = NULL;
82
83
84 /*
85  * Initialize SPANS processing
86  *
87  * This will be called during module loading.  We'll just register
88  * the SPANS protocol descriptor and wait for a SPANS ATM interface
89  * to come online.
90  *
91  * Arguments:
92  *      none
93  *
94  * Returns:
95  *      0       startup was successful
96  *      errno   startup failed - reason indicated
97  *
98  */
99 static int
100 spans_start(void)
101 {
102         int     err = 0;
103
104         /*
105          * Verify software version
106          */
107         if (atm_version != ATM_VERSION) {
108                 log(LOG_ERR, "version mismatch: spans=%d.%d kernel=%d.%d\n",
109                                 ATM_VERS_MAJ(ATM_VERSION),
110                                 ATM_VERS_MIN(ATM_VERSION),
111                                 ATM_VERS_MAJ(atm_version),
112                                 ATM_VERS_MIN(atm_version));
113                 return (EINVAL);
114         }
115
116         /*
117          * Allocate protocol definition structure
118          */
119         spans_mgr = KM_ALLOC(sizeof(struct sigmgr),
120                         M_DEVBUF, M_INTWAIT | M_NULLOK);
121         if (spans_mgr == NULL) {
122                 err = ENOMEM;
123                 goto done;
124         }
125         KM_ZERO(spans_mgr, sizeof(struct sigmgr));
126
127         /*
128          * Initialize protocol invariant values
129          */
130         spans_mgr->sm_proto = ATM_SIG_SPANS;
131         spans_mgr->sm_attach = spans_attach;
132         spans_mgr->sm_detach = spans_detach;
133         spans_mgr->sm_setup = spans_setup;
134         spans_mgr->sm_release = spans_release;
135         spans_mgr->sm_accept = spans_accept;
136         spans_mgr->sm_reject = spans_reject;
137         spans_mgr->sm_free = spans_free;
138         spans_mgr->sm_ioctl = spans_ioctl;
139
140         /*
141          * Register ourselves with system
142          */
143         err = atm_sigmgr_register(spans_mgr);
144         if (err)
145                 goto done;
146
147         /*
148          * Start up Connectionless Service
149          */
150         err = spanscls_start();
151         if (err)
152                 goto done;
153
154 done:
155         return (err);
156 }
157
158
159 /*
160  * Halt SPANS processing
161  *
162  * This should be called just prior to unloading the module from
163  * memory.  All SPANS interfaces must be deregistered before the
164  * protocol can be shutdown.
165  *
166  * Arguments:
167  *      none
168  *
169  * Returns:
170  *      0       startup was successful
171  *      errno   startup failed - reason indicated
172  *
173  */
174 static int
175 spans_stop(void)
176 {
177         int     err = 0;
178
179         crit_enter();
180
181         /*
182          * Is protocol even set up?
183          */
184         if (spans_mgr) {
185
186                 /*
187                  * Any protocol instances still registered?
188                  */
189                 if (spans_mgr->sm_prinst) {
190
191                         /* Yes, can't stop now */
192                         err = EBUSY;
193                         goto done;
194                 }
195
196                 /*
197                  * Stop Connectionless Service
198                  */
199                 spanscls_stop();
200
201                 /*
202                  * De-register from system
203                  */
204                 err = atm_sigmgr_deregister(spans_mgr);
205
206                 /*
207                  * Free up protocol block
208                  */
209                 KM_FREE(spans_mgr, sizeof(struct sigmgr), M_DEVBUF);
210                 spans_mgr = NULL;
211
212                 /*
213                  * Free up our storage pools
214                  */
215                 atm_release_pool(&spans_vcpool);
216                 atm_release_pool(&spans_msgpool);
217         } else
218                 err = ENXIO;
219
220 done:
221         crit_exit();
222         return (err);
223 }
224
225
226 /*
227  * Attach a SPANS-controlled interface
228  *
229  * Each ATM physical interface must be attached with the signalling
230  * manager for the interface's signalling protocol (via the
231  * atm_sigmgr_attach function).  This function will handle the
232  * attachment for SPANS-controlled interfaces.  A new SPANS protocol
233  * instance will be created and then we'll just sit around waiting for
234  * status or connection requests.
235  *
236  * Function must be called from a critical section.
237  *
238  * Arguments:
239  *      smp     pointer to SPANS signalling manager control block
240  *      pip     pointer to ATM physical interface control block
241  *
242  * Returns:
243  *      0       attach successful
244  *      errno   attach failed - reason indicated
245  *
246  */
247 static int
248 spans_attach(struct sigmgr *smp, struct atm_pif *pip)
249 {
250         int             err = 0, n = 0;
251         struct spans    *spp = NULL;
252         struct atm_nif  *np;
253
254         ATM_DEBUG2("spans_attach: smp=%p, pip=%p\n", smp, pip);
255
256         /*
257          * Count network interfaces attached to the physical interface.
258          * If there are more or less than one, we have big problems.
259          */
260         np = pip->pif_nif;
261         while (np) {
262                 n++;
263                 np = np->nif_pnext;
264         }
265         if (n != 1) {
266                 err = ETOOMANYREFS;
267                 goto done;
268         }
269
270         /*
271          * Allocate SPANS protocol instance control block
272          */
273         spp = KM_ALLOC(sizeof(struct spans),
274                         M_DEVBUF, M_INTWAIT | M_NULLOK);
275         if (spp == NULL) {
276                 err = ENOMEM;
277                 goto done;
278         }
279         KM_ZERO(spp, sizeof(struct spans));
280
281         /*
282          * Set variables in SPANS protocol instance control block
283          */
284         spp->sp_state = SPANS_INIT;
285         spp->sp_h_epoch = time_second;
286         spp->sp_s_epoch = 0;
287         spp->sp_addr.address_format = T_ATM_ABSENT;
288         spp->sp_addr.address_length = 0;
289         spp->sp_subaddr.address_format = T_ATM_ABSENT;
290         spp->sp_subaddr.address_length = 0;
291         spp->sp_probe_ct = 0;
292         spp->sp_alloc_vci = SPANS_MIN_VCI;
293         spp->sp_alloc_vpi = SPANS_VPI;
294         spp->sp_min_vci = SPANS_MIN_VCI;
295         spp->sp_max_vci = pip->pif_maxvci;
296
297         /*
298          * Link instance into manager's chain
299          */
300         LINK2TAIL((struct siginst *)spp, struct siginst, smp->sm_prinst,
301                         si_next);
302
303         /*
304          * Link in interface
305          */
306         spp->sp_pif = pip;
307         pip->pif_sigmgr = smp;
308         pip->pif_siginst = (struct siginst *) spp;
309
310         /*
311          * Kick-start the SPANS protocol
312          */
313         SPANS_TIMER(spp, 0);
314
315         /*
316          * Notify Connectionless Service
317          */
318         err = spanscls_attach(spp);
319
320         /*
321          * Log the fact that we've attached
322          */
323         if (!err)
324                 log(LOG_INFO, "spans: attached to interface %s%d\n",
325                                 pip->pif_name, pip->pif_unit);
326
327 done:
328         /*
329          * Reset our work if attach fails
330          */
331         if (err) {
332                 if (spp) {
333                         SPANS_CANCEL(spp);
334                         UNLINK((struct siginst *)spp, struct siginst,
335                                         smp->sm_prinst, si_next);
336                         KM_FREE(spp, sizeof(struct spans), M_DEVBUF);
337                 }
338                 crit_enter();
339                 pip->pif_sigmgr = NULL;
340                 pip->pif_siginst = NULL;
341                 crit_exit();
342         }
343
344         return (err);
345 }
346
347
348 /*
349  * Detach a SPANS-controlled interface
350  *
351  * Each ATM physical interface may be detached from its signalling
352  * manager (via the atm_sigmgr_detach function).  This function will
353  * handle the detachment for all SPANS-controlled interfaces.  All
354  * circuits will be immediately terminated.
355  *
356  * Function must be called from a critical section.
357  *
358  * Arguments:
359  *      pip     pointer to ATM physical interface control block
360  *
361  * Returns:
362  *      0       detach successful
363  *      errno   detach failed - reason indicated
364  *
365  */
366 static int
367 spans_detach(struct atm_pif *pip)
368 {
369         struct spans            *spp;
370         struct vccb             *vcp, *vnext;
371         Atm_connection          *cop;
372         int                     err;
373
374         ATM_DEBUG1("spans_detach: pip=%p\n", pip);
375
376         /*
377          * Get SPANS protocol instance
378          */
379         spp = (struct spans *)pip->pif_siginst;
380
381         /*
382          * Return an error if we're already detaching
383          */
384         if (spp->sp_state == SPANS_DETACH) {
385                 return(EALREADY);
386         }
387
388         /*
389          * Cancel any outstanding timer
390          */
391         SPANS_CANCEL(spp);
392
393         /*
394          * Notify Connectionless Service
395          */
396         spanscls_detach(spp);
397
398         /*
399          * Terminate all of our VCCs
400          */
401         for (vcp = Q_HEAD(spp->sp_vccq, struct vccb); vcp; vcp = vnext) {
402
403                 vnext = Q_NEXT(vcp, struct vccb, vc_sigelem);
404
405                 /*
406                  * Don't close the signalling VCC yet
407                  */
408                 if (vcp->vc_connvc && vcp->vc_connvc->cvc_conn ==
409                                 spp->sp_conn)
410                         continue;
411
412                 /*
413                  * Close VCC and notify owner
414                  */
415                 err = spans_clear_vcc(spp, (struct spans_vccb *)vcp);
416                 if (err) {
417                         log(LOG_ERR, "spans: error %d clearing VCCB %p\n",
418                                         err, vcp);
419                 }
420         }
421
422         /*
423          * Now close the SPANS signalling VCC
424          */
425         if ((cop = spp->sp_conn) != NULL) {
426                 err = atm_cm_release(cop, &spans_cause);
427                 if (err)
428                         ATM_DEBUG2(
429                                         "spans_detach: close failed for SPANS signalling channel; cop=%p, err=%d\n",
430                                         cop, err);
431         }
432         
433
434         /*
435          * Get rid of protocol instance if there are no VCCs queued
436          */
437         if (Q_HEAD(spp->sp_vccq, struct vccb) == NULL) {
438                 struct sigmgr   *smp = pip->pif_sigmgr;
439
440                 pip->pif_sigmgr = NULL;
441                 pip->pif_siginst = NULL;
442                 UNLINK((struct siginst *)spp, struct siginst,
443                                 smp->sm_prinst, si_next);
444                 KM_FREE(spp, sizeof(struct spans), M_DEVBUF);
445         } else {
446                 /*
447                  * Otherwise, wait for protocol instance to be freed
448                  * during spans_free processing for the last queued VCC.
449                  */
450                 spp->sp_state = SPANS_DETACH;
451         }
452
453         /*
454          * Log the fact that we've detached
455          */
456         log(LOG_INFO, "spans: detached from interface %s%d\n",
457                         pip->pif_name, pip->pif_unit);
458
459         return (0);
460 }
461
462
463 /*
464  * Open a SPANS ATM Connection
465  *
466  * All service user requests to open a VC connection (via
467  * atm_open_connection) over an ATM interface attached to the SPANS
468  * signalling manager are handled here.
469  *
470  * Function will be called from a critical section.
471  *
472  * Arguments:
473  *      cvp     pointer to user's requested connection parameters
474  *      errp    pointer to an int for extended error information
475  *
476  * Returns:
477  *      CALL_PROCEEDING connection establishment is in progress
478  *      CALL_FAILED     connection establishment failed
479  *      CALL_CONNECTED  connection has been successfully established
480  *
481  */
482 static int
483 spans_setup(Atm_connvc *cvp, int *errp)
484 {
485         struct atm_pif  *pip = cvp->cvc_attr.nif->nif_pif;
486         struct spans    *spp = (struct spans *)pip->pif_siginst;
487         int             rc = 0;
488
489         ATM_DEBUG1("spans_setup: cvp=%p\n", cvp);
490
491         /*
492          * Intialize the returned error code
493          */
494         *errp = 0;
495
496         /*
497          * Open the connection
498          */
499         switch (cvp->cvc_attr.called.addr.address_format) {
500         case T_ATM_PVC_ADDR:
501                 /*
502                  * Create a PVC
503                  */
504                 *errp = spans_open_vcc(spp, cvp);
505                 rc = (*errp ? CALL_FAILED : CALL_CONNECTED);
506                 break;
507
508         case T_ATM_SPANS_ADDR:
509
510                 /*
511                  * Create an SVC
512                  */
513                 *errp = spans_open_vcc(spp, cvp);
514                 rc = (*errp ? CALL_FAILED : CALL_PROCEEDING);
515                 break;
516
517         default:
518                 *errp = EPROTONOSUPPORT;
519                 rc = CALL_FAILED;
520         }
521
522         return (rc);
523 }
524
525
526 /*
527  * Close a SPANS ATM Connection
528  *
529  * All service user requests to terminate a previously open VC
530  * connection (via the atm_close_connection function), which is running
531  * over an interface attached to the SPANS signalling manager, are
532  * handled here.
533  *
534  * Function will be called from a critical section.
535  *
536  * Arguments:
537  *      vcp     pointer to connection's VC control block
538  *      errp    pointer to an int for extended error information
539  *
540  * Returns:
541  *      CALL_PROCEEDING connection termination is in progress
542  *      CALL_FAILED     connection termination failed
543  *      CALL_CLEARED    connection has been successfully terminated
544  *
545  */
546 static int
547 spans_release(struct vccb *vcp, int *errp)
548 {
549         int             rc = 0;
550         struct atm_pif  *pip = vcp->vc_pif;
551         struct spans    *spp = (struct spans *)pip->pif_siginst;
552
553         ATM_DEBUG1("spans_release: vcp=%p\n", vcp);
554
555         /*
556          * Initialize returned error code
557          */
558         *errp = 0;
559
560         /*
561          * Make sure VCC is open
562          */
563         if ((vcp->vc_sstate == SPANS_VC_NULL) ||
564                         (vcp->vc_sstate == SPANS_VC_CLOSE) ||
565                         (vcp->vc_sstate == SPANS_VC_FREE) ||
566                         (vcp->vc_ustate == VCCU_NULL) ||
567                         (vcp->vc_ustate == VCCU_CLOSED)) {
568                 *errp = EALREADY;
569                 return(CALL_FAILED);
570         }
571
572         /*
573          * Validate the connection type (PVC or SVC)
574          */
575         if (!(vcp->vc_type & (VCC_PVC | VCC_SVC))) {
576                 *errp = EPROTONOSUPPORT;
577                 return(CALL_FAILED);
578         }
579
580         /*
581          * Close the VCCB
582          */
583         *errp = spans_close_vcc(spp, (struct spans_vccb *)vcp, FALSE);
584
585         /*
586          * Set the return code
587          */
588         if (vcp->vc_type & VCC_PVC) {
589                 rc = (*errp ? CALL_FAILED : CALL_CLEARED);
590         } else {
591                 rc = (*errp ? CALL_FAILED : CALL_PROCEEDING);
592         }
593
594         return (rc);
595 }
596
597
598 /*
599  * Accept a SPANS Open from a remote host
600  *
601  * A user calls this routine (via the atm_accept_call function)
602  * after it is notified that an open request was received for it.
603  *
604  * Function will be called from a critical section.
605  *
606  * Arguments:
607  *      vcp     pointer to user's VCCB
608  *      errp    pointer to an int for extended error information
609  *
610  * Returns:
611  *      CALL_PROCEEDING connection establishment is in progress
612  *      CALL_FAILED     connection establishment failed
613  *      CALL_CONNECTED  connection has been successfully established
614  *
615  */
616 static int
617 spans_accept(struct vccb *vcp, int *errp)
618 {
619         struct atm_pif          *pip = vcp->vc_pif;
620         struct spans            *spp = (struct spans *)pip->pif_siginst;
621         struct spans_vccb       *svp = (struct spans_vccb *)vcp;
622
623         ATM_DEBUG1("spans_accept: vcp=%p\n", vcp);
624
625         /*
626          * Initialize the returned error code
627          */
628         *errp = 0;
629
630         /*
631          * Return an error if we're detaching
632          */
633         if (spp->sp_state == SPANS_DETACH) {
634                 *errp = ENETDOWN;
635                 ATM_DEBUG0("spans_accept: detaching\n");
636                 return(CALL_FAILED);
637         }
638
639         /*
640          * Respond to the open request
641          */
642         *errp = spans_send_open_rsp(spp, svp, SPANS_OK);
643         if (*errp) {
644                 ATM_DEBUG0("spans_accept: spans_send_open_rsp failed\n");
645                 goto failed;
646         }
647
648         /*
649          * Update the VCC states
650          */
651         svp->sv_sstate = SPANS_VC_OPEN;
652         svp->sv_ustate = VCCU_OPEN;
653
654         return(CALL_CONNECTED);
655
656 failed:
657         /*
658          * On error, free the VCCB and return CALL_FAILED
659          */
660         svp->sv_sstate = SPANS_VC_FREE;
661         svp->sv_ustate = VCCU_CLOSED;
662         DEQUEUE(svp, struct spans_vccb, sv_sigelem, spp->sp_vccq);
663         spans_free((struct vccb *)svp);
664
665         return(CALL_FAILED);
666 }
667
668
669 /*
670  * Reject a SPANS Open from a remote host
671  *
672  * A user calls this routine (via the atm_reject_call function)
673  * after it is notified that an open request was received for it.
674  *
675  * Function will be called from a critical section.
676  *
677  * Arguments:
678  *      vcp     pointer to user's VCCB
679  *      errp    pointer to an int for extended error information
680  *
681  * Returns:
682  *      CALL_CLEARED    call request rejected
683  *      CALL_FAILED     call rejection failed
684  *
685  */
686 static int
687 spans_reject(struct vccb *vcp, int *errp)
688 {
689         struct atm_pif          *pip = vcp->vc_pif;
690         struct spans            *spp = (struct spans *)pip->pif_siginst;
691         struct spans_vccb       *svp = (struct spans_vccb *)vcp;
692
693         ATM_DEBUG1("spans_reject: vcp=%p\n", vcp);
694
695         /*
696          * Initialize the returned error code
697          */
698         *errp = 0;
699
700         /*
701          * Return an error if we're detaching
702          */
703         if (spp->sp_state == SPANS_DETACH) {
704                 *errp = ENETDOWN;
705                 ATM_DEBUG0("spans_reject: detaching\n");
706                 return(CALL_FAILED);
707         }
708
709         ATM_DEBUG1("spans_reject: cause code is %d\n",
710                         vcp->vc_connvc->cvc_attr.cause.v.cause_value);
711
712         /*
713          * Clean up the VCCB--the connection manager will free it
714          * spans_close_vcc will send a SPANS open response
715          */
716         if ((*errp = spans_close_vcc(spp, svp, TRUE)) != 0) {
717                 ATM_DEBUG0("spans_reject: spans_close_vcc failed\n");
718                 return(CALL_FAILED);
719         }
720
721         return(CALL_CLEARED);
722 }
723
724
725 /*
726  * Abort a SPANS ATM Connection
727  *
728  * All (non-user) requests to abort a previously open VC connection (via
729  * the atm_abort_connection function), which is running over an
730  * interface attached to the SPANS signalling manager, are handled here.
731  * The VCC owner will be notified of the request, in order to initiate
732  * termination of the connection.
733  *
734  * Function will be called from a critical section.
735  *
736  * Arguments:
737  *      vcp     pointer to connection's VC control block
738  *
739  * Returns:
740  *      0       connection release was succesful
741  *      errno   connection release failed - reason indicated
742  *
743  */
744 int
745 spans_abort(struct vccb *vcp)
746 {
747
748         /*
749          * Make sure VCC is available
750          */
751         if ((vcp->vc_sstate == SPANS_VC_NULL) ||
752                         (vcp->vc_sstate == SPANS_VC_CLOSE) ||
753                         (vcp->vc_sstate == SPANS_VC_FREE) ||
754                         (vcp->vc_ustate == VCCU_NULL) ||
755                         (vcp->vc_ustate == VCCU_CLOSED)) {
756                 return(EALREADY);
757         }
758
759         /*
760          * Only abort once
761          */
762         if (vcp->vc_sstate == SPANS_VC_ABORT) {
763                 return (EALREADY);
764         }
765
766         /*
767          * Cancel any timer that might be running
768          */
769         SPANS_VC_CANCEL(vcp);
770
771         /*
772          * Set immediate timer to schedule connection termination
773          */
774         vcp->vc_sstate = SPANS_VC_ABORT;
775         SPANS_VC_TIMER(vcp, 0);
776
777         return (0);
778 }
779
780
781 /*
782  * Free SPANS ATM connection resources
783  *
784  * All service user requests to free the resources of a closed
785  * VCC connection (via the atm_free_connection function), which
786  * is running over an interface attached to the SigPVC signalling
787  * manager, are handled here.
788  *
789  * Function will be called from a critical section.
790  *
791  * Arguments:
792  *      vcp     pointer to connection's VC control block
793  *
794  * Returns:
795  *      0       connection free was successful
796  *      errno   connection free failed - reason indicated
797  *
798  */
799 int
800 spans_free(struct vccb *vcp)
801 {
802         struct atm_pif *pip = vcp->vc_pif;
803         struct spans *spp = (struct spans *)pip->pif_siginst;
804
805         ATM_DEBUG1("spans_free: vcp = %p\n", vcp);
806
807         /*
808          * Make sure VCC has been closed
809          */
810         if ((vcp->vc_ustate != VCCU_CLOSED) ||
811                         (vcp->vc_sstate != SPANS_VC_FREE)) {
812                 ATM_DEBUG2("spans_free: bad state, sstate=%d, ustate=%d\n",
813                                 vcp->vc_sstate, vcp->vc_ustate);
814                 return(EEXIST);
815         }
816
817         /*
818          * Remove VCCB from protocol queue
819          */
820         DEQUEUE(vcp, struct vccb, vc_sigelem, spp->sp_vccq);
821
822         /*
823          * Free VCCB storage
824          */
825         vcp->vc_ustate = VCCU_NULL;
826         vcp->vc_sstate = SPANS_VC_NULL;
827         atm_free((caddr_t)vcp);
828
829         /*
830          * If we're detaching and this was the last VCC queued,
831          * get rid of the protocol instance
832          */
833         if ((spp->sp_state == SPANS_DETACH) &&
834                         (Q_HEAD(spp->sp_vccq, struct vccb) == NULL)) {
835                 struct sigmgr   *smp = pip->pif_sigmgr;
836
837                 pip->pif_sigmgr = NULL;
838                 pip->pif_siginst = NULL;
839                 UNLINK((struct siginst *)spp, struct siginst, smp->sm_prinst,
840                                 si_next);
841                 KM_FREE(spp, sizeof(struct spans), M_DEVBUF);
842         }
843
844         return (0);
845 }
846
847
848 /*
849  * SPANS IOCTL support
850  *
851  * Function will be called from a critical section.
852  *
853  * Arguments:
854  *      code    PF_ATM sub-operation code
855  *      data    pointer to code specific parameter data area
856  *      arg1    pointer to code specific argument
857  *
858  * Returns:
859  *      0       request procesed
860  *      errno   error processing request - reason indicated
861  *
862  */
863 static int
864 spans_ioctl(int code, caddr_t data, caddr_t arg1)
865 {
866         struct atmdelreq        *adp;
867         struct atminfreq        *aip;
868         struct spans            *spp;
869         struct spans_vccb       *svp;
870         struct air_vcc_rsp      rsp;
871         Atm_connection          *cop;
872         int                     buf_len, err = 0, i, vpi, vci;
873         caddr_t                 buf_addr;
874
875
876         switch (code) {
877
878         case AIOCS_DEL_PVC:
879         case AIOCS_DEL_SVC:
880                 /*
881                  * Delete a VCC
882                  */
883                 adp = (struct atmdelreq *)data;
884                 spp = (struct spans *)arg1;
885
886                 /*
887                  * Don't let a user close the SPANS signalling VC or
888                  * the SPANS CLS VC
889                  */
890                 vpi = adp->adr_pvc_vpi;
891                 vci = adp->adr_pvc_vci;
892                 if ((vpi == SPANS_SIG_VPI && vci == SPANS_SIG_VCI) ||
893                                 (vpi == SPANS_CLS_VPI &&
894                                 vci == SPANS_CLS_VCI))
895                         return(EINVAL);
896
897                 /*
898                  * Find requested VCC
899                  */
900                 for (svp = Q_HEAD(spp->sp_vccq, struct spans_vccb); svp;
901                                 svp = Q_NEXT(svp, struct spans_vccb, sv_sigelem)) {
902                         if ((svp->sv_vpi == vpi) && (svp->sv_vci == vci))
903                                 break;
904                 }
905                 if (svp == NULL)
906                         return (ENOENT);
907
908                 /*
909                  * Check VCC type
910                  */
911                 switch (code) {
912                 case AIOCS_DEL_PVC:
913                         if (!(svp->sv_type & VCC_PVC)) {
914                                 return(EINVAL);
915                         }
916                         break;
917                 case AIOCS_DEL_SVC:
918                         if (!(svp->sv_type & VCC_SVC)) {
919                                 return(EINVAL);
920                         }
921                         break;
922                 }
923
924                 /*
925                  * Schedule VCC termination
926                  */
927                 err = spans_abort((struct vccb *)svp);
928                 break;
929
930         case AIOCS_INF_VCC:
931                 /*
932                  * Return VCC information
933                  */
934                 aip = (struct atminfreq *)data;
935                 spp = (struct spans *)arg1;
936
937                 buf_addr = aip->air_buf_addr;
938                 buf_len = aip->air_buf_len;
939
940                 /*
941                  * Loop through the VCC queue
942                  */
943                 for (svp = Q_HEAD(spp->sp_vccq, struct spans_vccb); svp;
944                                 svp = Q_NEXT(svp, struct spans_vccb, sv_sigelem)) {
945                         /*
946                          * Make sure there's room in the user's buffer
947                          */
948                         if (buf_len < sizeof(rsp)) {
949                                 err = ENOSPC;
950                                 break;
951                         }
952
953                         /*
954                          * Fill out the response struct for the VCC
955                          */
956                         snprintf(rsp.avp_intf,
957                                     sizeof(rsp.avp_intf), "%s%d",
958                                         spp->sp_pif->pif_name,
959                                         spp->sp_pif->pif_unit);
960                         rsp.avp_vpi = svp->sv_vpi;
961                         rsp.avp_vci = svp->sv_vci;
962                         rsp.avp_type = svp->sv_type;
963                         rsp.avp_aal = svp->sv_connvc->cvc_attr.aal.type;
964                         rsp.avp_sig_proto = svp->sv_proto;
965                         cop = svp->sv_connvc->cvc_conn;
966                         if (cop)
967                                 rsp.avp_encaps = cop->co_mpx;
968                         else
969                                 rsp.avp_encaps = 0;
970                         rsp.avp_state = svp->sv_sstate;
971                         KM_ZERO(rsp.avp_owners, sizeof(rsp.avp_owners));
972                         for (i = 0; cop && i < sizeof(rsp.avp_owners);
973                                         cop = cop->co_next,
974                                         i += T_ATM_APP_NAME_LEN+1) {
975                                 strncpy(&rsp.avp_owners[i],
976                                         cop->co_endpt->ep_getname(cop->co_toku),
977                                         T_ATM_APP_NAME_LEN);
978                         }
979                         rsp.avp_daddr.address_format = T_ATM_SPANS_ADDR;
980                         rsp.avp_daddr.address_length = 
981                                         sizeof(Atm_addr_spans);
982                         if (svp->sv_type & VCC_OUT) {
983                                 spans_addr_copy(&svp->sv_conn.con_dst,
984                                                 rsp.avp_daddr.address);
985                         } else {
986                                 spans_addr_copy(&svp->sv_conn.con_src,
987                                                 rsp.avp_daddr.address);
988                         }
989                         rsp.avp_dsubaddr.address_format = T_ATM_ABSENT;
990                         rsp.avp_dsubaddr.address_length = 0;
991                         rsp.avp_ipdus = svp->sv_ipdus;
992                         rsp.avp_opdus = svp->sv_opdus;
993                         rsp.avp_ibytes = svp->sv_ibytes;
994                         rsp.avp_obytes = svp->sv_obytes;
995                         rsp.avp_ierrors = svp->sv_ierrors;
996                         rsp.avp_oerrors = svp->sv_oerrors;
997                         rsp.avp_tstamp = svp->sv_tstamp;
998
999                         /*
1000                          * Copy the response into the user's buffer
1001                          */
1002                         if ((err = copyout((caddr_t)&rsp, buf_addr,
1003                                         sizeof(rsp))) != 0)
1004                                 break;
1005                         buf_addr += sizeof(rsp);
1006                         buf_len -= sizeof(rsp);
1007                 }
1008
1009                 /*
1010                  * Update the buffer pointer and length
1011                  */
1012                 aip->air_buf_addr = buf_addr;
1013                 aip->air_buf_len = buf_len;
1014                 break;
1015
1016         case AIOCS_ADD_ARP:
1017         case AIOCS_DEL_ARP:
1018         case AIOCS_INF_ARP:
1019         case AIOCS_INF_ASV:
1020                 /*
1021                  * ARP specific ioctl's
1022                  */
1023                 err = spansarp_ioctl(code, data, arg1);
1024                 break;
1025
1026         default:
1027                 err = EOPNOTSUPP;
1028         }
1029
1030         return (err);
1031 }
1032
1033
1034 #ifdef ATM_SPANS_MODULE
1035 /*
1036  *******************************************************************
1037  *
1038  * Loadable Module Support
1039  *
1040  *******************************************************************
1041  */
1042 static int      spans_doload (void);
1043 static int      spans_dounload (void);
1044
1045 /*
1046  * Generic module load processing
1047  * 
1048  * This function is called by an OS-specific function when this
1049  * module is being loaded.
1050  *
1051  * Arguments:
1052  *      none
1053  *
1054  * Returns:
1055  *      0       load was successful 
1056  *      errno   load failed - reason indicated
1057  *
1058  */
1059 static int
1060 spans_doload(void)
1061 {
1062         int     err = 0;
1063
1064         /*
1065          * Start us up
1066          */
1067         err = spans_start();
1068         if (err)
1069                 /* Problems, clean up */
1070                 spans_stop();
1071
1072         return (err);
1073 }
1074
1075
1076 /*
1077  * Generic module unload processing
1078  * 
1079  * This function is called by an OS-specific function when this
1080  * module is being unloaded.
1081  *
1082  * Arguments:
1083  *      none
1084  *
1085  * Returns:
1086  *      0       unload was successful 
1087  *      errno   unload failed - reason indicated
1088  *
1089  */
1090 static int
1091 spans_dounload(void)
1092 {
1093         int     err = 0;
1094
1095         /*
1096          * OK, try to clean up our mess
1097          */
1098         err = spans_stop();
1099
1100         return (err);
1101 }
1102
1103 #include <sys/exec.h>
1104 #include <sys/sysent.h>
1105 #include <sys/lkm.h>
1106
1107 /*
1108  * Loadable miscellaneous module description
1109  */
1110 MOD_MISC(spans);
1111
1112
1113 /*
1114  * Loadable module support "load" entry point
1115  * 
1116  * This is the routine called by the lkm driver whenever the
1117  * modload(1) command is issued for this module.
1118  *
1119  * Arguments:
1120  *      lkmtp   pointer to lkm drivers's structure
1121  *      cmd     lkm command code
1122  *
1123  * Returns:
1124  *      0       command was successful 
1125  *      errno   command failed - reason indicated
1126  *
1127  */
1128 static int
1129 spans_load(struct lkm_table *lkmtp, int cmd)
1130 {
1131         return(spans_doload());
1132 }
1133
1134
1135 /*
1136  * Loadable module support "unload" entry point
1137  * 
1138  * This is the routine called by the lkm driver whenever the
1139  * modunload(1) command is issued for this module.
1140  *
1141  * Arguments:
1142  *      lkmtp   pointer to lkm drivers's structure
1143  *      cmd     lkm command code
1144  *
1145  * Returns:
1146  *      0       command was successful 
1147  *      errno   command failed - reason indicated
1148  *
1149  */
1150 static int
1151 spans_unload(struct lkm_table *lkmtp, int cmd)
1152 {
1153         return(spans_dounload());
1154 }
1155
1156
1157 /*
1158  * Loadable module support entry point
1159  * 
1160  * This is the routine called by the lkm driver for all loadable module
1161  * functions for this driver.  This routine name must be specified
1162  * on the modload(1) command.  This routine will be called whenever the
1163  * modload(1), modunload(1) or modstat(1) commands are issued for this
1164  * module.
1165  *
1166  * Arguments:
1167  *      lkmtp   pointer to lkm drivers's structure
1168  *      cmd     lkm command code
1169  *      ver     lkm version
1170  *
1171  * Returns:
1172  *      0       command was successful 
1173  *      errno   command failed - reason indicated
1174  *
1175  */
1176 int
1177 spans_mod(struct lkm_table *lkmtp, int cmd, int ver)
1178 {
1179         MOD_DISPATCH(spans, lkmtp, cmd, ver,
1180                 spans_load, spans_unload, lkm_nullcmd);
1181 }
1182
1183 #else   /* !ATM_SPANS_MODULE */
1184
1185 /*
1186  *******************************************************************
1187  *
1188  * Kernel Compiled Module Support
1189  *
1190  *******************************************************************
1191  */
1192 static void     spans_doload (void *);
1193
1194 SYSINIT(atmspans, SI_SUB_PROTO_END, SI_ORDER_ANY, spans_doload, NULL)
1195
1196 /*
1197  * Kernel initialization
1198  * 
1199  * Arguments:
1200  *      arg     Not used
1201  *
1202  * Returns:
1203  *      none
1204  *
1205  */
1206 static void
1207 spans_doload(void *arg)
1208 {
1209         int     err = 0;
1210
1211         /*
1212          * Start us up
1213          */
1214         err = spans_start();
1215         if (err) {
1216                 /* Problems, clean up */
1217                 spans_stop();
1218
1219                 log(LOG_ERR, "ATM SPANS unable to initialize (%d)!!\n", err);
1220         }
1221         return;
1222 }
1223 #endif  /* ATM_SPANS_MODULE */