Replace all casts of NULL to something with NULL.
[dragonfly.git] / sys / netproto / atm / uni / unisig_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/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 $
28  */
29
30 /*
31  * ATM Forum UNI 3.0/3.1 Signalling Manager
32  * ----------------------------------------
33  *
34  * System interface module
35  *
36  */
37
38 #include <netproto/atm/kern_include.h>
39
40 #include <netproto/atm/ipatm/ipatm_var.h>
41 #include <netproto/atm/ipatm/ipatm_serv.h>
42 #include "uniip_var.h"
43
44 #include "unisig.h"
45 #include "unisig_var.h"
46 #include "unisig_msg.h"
47
48 /*
49  * Global variables
50  */
51 struct sp_info  unisig_vcpool = {
52         "unisig vcc pool",              /* si_name */
53         sizeof(struct unisig_vccb),     /* si_blksiz */
54         10,                             /* si_blkcnt */
55         50                              /* si_maxallow */
56 };
57
58 struct sp_info  unisig_msgpool = {
59         "unisig message pool",          /* si_name */
60         sizeof(struct unisig_msg),      /* si_blksiz */
61         10,                             /* si_blkcnt */
62         50                              /* si_maxallow */
63 };
64
65 struct sp_info  unisig_iepool = {
66         "unisig ie pool",               /* si_name */
67         sizeof(struct ie_generic),      /* si_blksiz */
68         10,                             /* si_blkcnt */
69         50                              /* si_maxallow */
70 };
71
72
73 /*
74  * Local functions
75  */
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);
84
85
86 /*
87  * Local variables
88  */
89 static struct sigmgr    unisig_mgr30 = {
90         NULL,
91         ATM_SIG_UNI30,
92         NULL,
93         unisig_attach,
94         unisig_detach,
95         unisig_setup,
96         unisig_accept,
97         unisig_reject,
98         unisig_release,
99         unisig_free,
100         unisig_ioctl
101 };
102
103 static struct sigmgr    unisig_mgr31 = {
104         NULL,
105         ATM_SIG_UNI31,
106         NULL,
107         unisig_attach,
108         unisig_detach,
109         unisig_setup,
110         unisig_accept,
111         unisig_reject,
112         unisig_release,
113         unisig_free,
114         unisig_ioctl
115 };
116
117
118 /*
119  * Initialize UNISIG processing
120  *
121  * This will be called during module loading.  We'll just register
122  * the UNISIG protocol descriptor and wait for a UNISIG ATM interface
123  * to come online.
124  *
125  * Arguments:
126  *      none
127  *
128  * Returns:
129  *      0       startup was successful
130  *      errno   startup failed - reason indicated
131  *
132  */
133 int
134 unisig_start(void)
135 {
136         int     err = 0;
137
138         /*      
139          * Verify software version
140          */     
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));
147                 return (EINVAL);
148         }
149
150         /*
151          * Register ourselves with system
152          */
153         err = atm_sigmgr_register(&unisig_mgr30);
154         if (err)
155                 goto done;
156
157         err = atm_sigmgr_register(&unisig_mgr31);
158
159 done:
160         return (err);
161 }
162
163
164 /*
165  * Halt UNISIG processing
166  *
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.
170  *
171  * Arguments:
172  *      none
173  *
174  * Returns:
175  *      0       startup was successful
176  *      errno   startup failed - reason indicated
177  *
178  */
179 int
180 unisig_stop(void)
181 {
182         int     err = 0;
183
184         crit_enter();
185
186         /*
187          * Any protocol instances still registered?
188          */
189         if ((unisig_mgr30.sm_prinst != NULL) ||
190             (unisig_mgr31.sm_prinst != NULL)) {
191
192                 /* Yes, can't stop now */
193                 err = EBUSY;
194                 goto done;
195         }
196
197         /*
198          * De-register from system
199          */
200         atm_sigmgr_deregister(&unisig_mgr30);
201         atm_sigmgr_deregister(&unisig_mgr31);
202
203         /*
204          * Free up our storage pools
205          */
206         atm_release_pool(&unisig_vcpool);
207         atm_release_pool(&unisig_msgpool);
208         atm_release_pool(&unisig_iepool);
209
210 done:
211         crit_exit();
212         return (err);
213 }
214
215
216 /*
217  * Attach a UNISIG-controlled interface
218  *
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.
225  *
226  * Function must be called from a critical section.
227  *
228  * Arguments:
229  *      smp     pointer to UNISIG signalling manager control block
230  *      pip     pointer to ATM physical interface control block
231  *
232  * Returns:
233  *      0       attach successful
234  *      errno   attach failed - reason indicated
235  *
236  */
237 static int
238 unisig_attach(struct sigmgr *smp, struct atm_pif *pip)
239 {
240         int                     err = 0;
241         struct unisig           *usp = NULL;
242
243         ATM_DEBUG2("unisig_attach: smp=%p, pip=%p\n", smp, pip);
244
245         /*
246          * Allocate UNISIG protocol instance control block
247          */
248         usp = KM_ALLOC(sizeof(struct unisig), M_DEVBUF, M_INTWAIT | M_NULLOK);
249         if (usp == NULL) {
250                 err = ENOMEM;
251                 goto done;
252         }
253         KM_ZERO(usp, sizeof(struct unisig));
254
255         /*
256          * Set state in UNISIG protocol instance control block
257          */
258         usp->us_state = UNISIG_NULL;
259         usp->us_proto = smp->sm_proto;
260
261         /*
262          * Set initial call reference allocation value
263          */
264         usp->us_cref = 1;
265
266         /*
267          * Link instance into manager's chain
268          */
269         LINK2TAIL((struct siginst *)usp, struct siginst, smp->sm_prinst,
270                         si_next);
271
272         /*
273          * Link in interface
274          */
275         usp->us_pif = pip;
276         crit_enter();
277         pip->pif_sigmgr = smp;
278         pip->pif_siginst = (struct siginst *) usp;
279         crit_exit();
280
281         /*
282          * Clear our ATM address.  The address will be set by user
283          * command or by registration via ILMI.
284          */
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;
289
290         /*
291          * Set pointer to IP
292          */
293         usp->us_ipserv = &uniip_ipserv;
294
295         /*
296          * Kick-start the UNISIG protocol
297          */
298         UNISIG_TIMER(usp, 0);
299
300         /*
301          * Log the fact that we've attached
302          */
303         log(LOG_INFO, "unisig: attached to interface %s%d\n",
304                         pip->pif_name, pip->pif_unit);
305
306 done:
307         /*
308          * Reset our work if attach fails
309          */
310         if (err) {
311                 if (usp) {
312                         UNISIG_CANCEL(usp);
313                         UNLINK((struct siginst *)usp, struct siginst,
314                                         smp->sm_prinst, si_next);
315                         KM_FREE(usp, sizeof(struct unisig), M_DEVBUF);
316                 }
317                 crit_enter();
318                 pip->pif_sigmgr = NULL;
319                 pip->pif_siginst = NULL;
320                 crit_exit();
321         }
322
323         return (err);
324 }
325
326
327 /*
328  * Detach a UNISIG-controlled interface
329  *
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.
334  *
335  * Function must be called from a critical section.
336  *
337  * Arguments:
338  *      pip     pointer to ATM physical interface control block
339  *
340  * Returns:
341  *      0       detach successful
342  *      errno   detach failed - reason indicated
343  *
344  */
345 static int
346 unisig_detach(struct atm_pif *pip)
347 {
348         struct unisig           *usp;
349         int                     err;
350
351         ATM_DEBUG1("unisig_detach: pip=%p\n", pip);
352
353         /*
354          * Get UNISIG protocol instance
355          */
356         usp = (struct unisig *)pip->pif_siginst;
357
358         /*
359          * Return an error if we're already detaching
360          */
361         if (usp->us_state == UNISIG_DETACH) {
362                 return(EALREADY);
363         }
364
365         /*
366          * Pass the detach event to the signalling manager
367          * state machine
368          */
369         err = unisig_sigmgr_state(usp, UNISIG_SIGMGR_DETACH, NULL);
370
371         /*
372          * Log the fact that we've detached
373          */
374         if (!err)
375                 log(LOG_INFO, "unisig: detached from interface %s%d\n",
376                                 pip->pif_name, pip->pif_unit);
377
378         return (0);
379 }
380
381
382 /*
383  * Open a UNISIG ATM Connection
384  *
385  * All service user requests to open a VC connection (via
386  * atm_open_connection) over an ATM interface attached to the UNISIG
387  * signalling manager are handled here.
388  *
389  * Function will be called from a critical section.
390  *
391  * Arguments:
392  *      cvp     pointer to user's requested connection parameters
393  *      errp    pointer to an int for extended error information
394  *
395  * Returns:
396  *      CALL_PROCEEDING connection establishment is in progress
397  *      CALL_FAILED     connection establishment failed
398  *      CALL_CONNECTED  connection has been successfully established
399  *
400  */
401 static int
402 unisig_setup(Atm_connvc *cvp, int *errp)
403 {
404         struct atm_pif  *pip = cvp->cvc_attr.nif->nif_pif;
405         struct unisig   *usp = (struct unisig *)pip->pif_siginst;
406         int             rc = 0;
407
408         ATM_DEBUG1("unisig_setup: cvp=%p\n", cvp);
409
410         /*
411          * Intialize the returned error code
412          */
413         *errp = 0;
414
415         /*
416          * Open the connection
417          */
418         switch (cvp->cvc_attr.called.addr.address_format) {
419         case T_ATM_PVC_ADDR:
420                 /*
421                  * Create a PVC
422                  */
423                 *errp = unisig_open_vcc(usp, cvp);
424                 rc = (*errp ? CALL_FAILED : CALL_CONNECTED);
425                 break;
426
427         case T_ATM_ENDSYS_ADDR:
428         case T_ATM_E164_ADDR:
429
430                 /*
431                  * Create an SVC
432                  */
433                 *errp = unisig_open_vcc(usp, cvp);
434                 rc = (*errp ? CALL_FAILED : CALL_PROCEEDING);
435                 break;
436
437         default:
438                 *errp = EPROTONOSUPPORT;
439                 rc = CALL_FAILED;
440         }
441
442         return (rc);
443 }
444
445
446 /*
447  * Close a UNISIG ATM Connection
448  *
449  * All service user requests to terminate a previously open VC
450  * connection (via the atm_close_connection function), which is running
451  * over an interface attached to the UNISIG signalling manager, are
452  * handled here.
453  *
454  * Function will be called from a critical section.
455  *
456  * Arguments:
457  *      vcp     pointer to connection's VC control block
458  *      errp    pointer to an int for extended error information
459  *
460  * Returns:
461  *      CALL_PROCEEDING connection termination is in progress
462  *      CALL_FAILED     connection termination failed
463  *      CALL_CLEARED    connection has been successfully terminated
464  *
465  */
466 static int
467 unisig_release(struct vccb *vcp, int *errp)
468 {
469         int             rc = 0;
470         struct atm_pif  *pip = vcp->vc_pif;
471         struct unisig   *usp = (struct unisig *)pip->pif_siginst;
472
473         ATM_DEBUG1("unisig_release: vcp=%p\n", vcp);
474
475         /*
476          * Initialize returned error code
477          */
478         *errp = 0;
479
480         /*
481          * Validate the connection type (PVC or SVC)
482          */
483         if (!(vcp->vc_type & (VCC_PVC | VCC_SVC))) {
484                 *errp = EPROTONOSUPPORT;
485                 return(CALL_FAILED);
486         }
487
488         /*
489          * Close the VCCB
490          */
491         *errp = unisig_close_vcc(usp, (struct unisig_vccb *)vcp);
492
493         /*
494          * Set the return code
495          */
496         if (*errp) {
497                 rc = CALL_FAILED;
498         } else if (vcp->vc_sstate == UNI_NULL ||
499                         vcp->vc_sstate == UNI_FREE) {
500                 rc = CALL_CLEARED;
501         } else {
502                 rc = CALL_PROCEEDING;
503         }
504
505         return (rc);
506 }
507
508
509 /*
510  * Accept a UNISIG Open from a remote host
511  *
512  * A user calls this routine (via the atm_accept_call function)
513  * after it is notified that an open request was received for it.
514  *
515  * Function will be called from a critical section.
516  *
517  * Arguments:
518  *      vcp     pointer to user's VCCB
519  *      errp    pointer to an int for extended error information
520  *
521  * Returns:
522  *      CALL_PROCEEDING connection establishment is in progress
523  *      CALL_FAILED     connection establishment failed
524  *      CALL_CONNECTED  connection has been successfully established
525  *
526  */
527 static int
528 unisig_accept(struct vccb *vcp, int *errp)
529 {
530         struct unisig_vccb      *uvp = (struct unisig_vccb *)vcp;
531         struct atm_pif          *pip = uvp->uv_pif;
532         struct unisig           *usp = (struct unisig *)pip->pif_siginst;
533
534         ATM_DEBUG1("unisig_accept: vcp=%p\n", vcp);
535
536         /*
537          * Initialize the returned error code
538          */
539         *errp = 0;
540
541         /*
542          * Return an error if we're detaching
543          */
544         if (usp->us_state == UNISIG_DETACH) {
545                 *errp = ENETDOWN;
546                 goto free;
547         }
548
549         /*
550          * Return an error if we lost the connection
551          */
552         if (uvp->uv_sstate == UNI_FREE) {
553                 *errp = ENETDOWN;
554                 goto free;
555         }
556
557         /*
558          * Pass the acceptance to the VC state machine
559          */
560         *errp = unisig_vc_state(usp, uvp, UNI_VC_ACCEPT_CALL, NULL);
561         if (*errp)
562                 goto failed;
563
564         return(CALL_PROCEEDING);
565
566 failed:
567         /*
568          * On error, free the VCCB and return CALL_FAILED
569          */
570
571 free:
572         uvp->uv_sstate = UNI_FREE;
573         uvp->uv_ustate = VCCU_CLOSED;
574         DEQUEUE(uvp, struct unisig_vccb, uv_sigelem, usp->us_vccq);
575         unisig_free((struct vccb *)uvp);
576
577         return(CALL_FAILED);
578 }
579
580
581 /*
582  * Reject a UNISIG Open from a remote host
583  *
584  * A user calls this routine (via the atm_reject_call function)
585  * after it is notified that an open request was received for it.
586  *
587  * Function will be called from a critical section.
588  *
589  * Arguments:
590  *      uvp     pointer to user's VCCB
591  *      errp    pointer to an int for extended error information
592  *
593  * Returns:
594  *      CALL_CLEARED    call request rejected
595  *      CALL_FAILED     call rejection failed
596  *
597  */
598 static int
599 unisig_reject(struct vccb *vcp, int *errp)
600 {
601         struct unisig_vccb      *uvp = (struct unisig_vccb *)vcp;
602         struct atm_pif          *pip = uvp->uv_pif;
603         struct unisig           *usp = (struct unisig *)pip->pif_siginst;
604
605         ATM_DEBUG1("unisig_reject: uvp=%p\n", uvp);
606
607         /*
608          * Initialize the returned error code
609          */
610         *errp = 0;
611
612
613         /*
614          * Return an error if we're detaching
615          */
616         if (usp->us_state == UNISIG_DETACH) {
617                 *errp = ENETDOWN;
618                 goto failed;
619         }
620
621         /*
622          * Call the VC state machine
623          */
624         *errp = unisig_vc_state(usp, uvp, UNI_VC_REJECT_CALL, NULL);
625         if (*errp)
626                 goto failed;
627
628         return(CALL_CLEARED);
629
630 failed:
631         /*
632          * On error, free the VCCB and return CALL_FAILED
633          */
634         uvp->uv_sstate = UNI_FREE;
635         uvp->uv_ustate = VCCU_CLOSED;
636         DEQUEUE(uvp, struct unisig_vccb, uv_sigelem, usp->us_vccq);
637         unisig_free((struct vccb *)uvp);
638         return(CALL_FAILED);
639 }
640
641
642 /*
643  * Abort a UNISIG ATM Connection
644  *
645  * All (non-user) requests to abort a previously open VC connection (via
646  * the atm_abort_connection function), which is running over an
647  * interface attached to the UNISIG signalling manager, are handled here.
648  * The VCC owner will be notified of the request, in order to initiate
649  * termination of the connection.
650  *
651  * Function will be called from a critical section.
652  *
653  * Arguments:
654  *      vcp     pointer to connection's VC control block
655  *
656  * Returns:
657  *      0       connection release was successful
658  *      errno   connection release failed - reason indicated
659  *
660  */
661 static int
662 unisig_abort(struct vccb *vcp)
663 {
664
665         ATM_DEBUG1("unisig_abort: vcp=%p\n", vcp);
666
667         /*
668          * Only abort once
669          */
670         if (vcp->vc_ustate == VCCU_ABORT) {
671                 return (EALREADY);
672         }
673
674         /*
675          * Cancel any timer that might be running
676          */
677         UNISIG_VC_CANCEL(vcp);
678
679         /*
680          * Set immediate timer to schedule connection termination
681          */
682         vcp->vc_ustate = VCCU_ABORT;
683         UNISIG_VC_TIMER(vcp, 0);
684
685         return (0);
686 }
687
688
689 /*
690  * Free UNISIG ATM connection resources
691  *
692  * All service user requests to free the resources of a closed VCC
693  * connection (via the atm_free_connection function), which is running
694  * over an interface attached to the UNISIG signalling manager, are
695  *handled here.
696  *
697  * Function will be called from a critical section.
698  *
699  * Arguments:
700  *      vcp     pointer to connection's VC control block
701  *
702  * Returns:
703  *      0       connection free was successful
704  *      errno   connection free failed - reason indicated
705  *
706  */
707 int
708 unisig_free(struct vccb *vcp)
709 {
710         struct atm_pif *pip = vcp->vc_pif;
711         struct unisig *usp = (struct unisig *)pip->pif_siginst;
712
713         ATM_DEBUG1("unisig_free: vcp = %p\n", vcp);
714
715         /*
716          * Make sure VCC has been closed
717          */
718         if ((vcp->vc_ustate != VCCU_CLOSED &&
719                         vcp->vc_ustate != VCCU_ABORT) ||
720                         vcp->vc_sstate != UNI_FREE) {
721                 ATM_DEBUG2("unisig_free: bad state, sstate=%d, ustate=%d\n",
722                                 vcp->vc_sstate, vcp->vc_ustate);
723                 return(EEXIST);
724         }
725
726         /*
727          * Remove VCCB from protocol queue
728          */
729         DEQUEUE(vcp, struct vccb, vc_sigelem, usp->us_vccq);
730
731         /*
732          * Free VCCB storage
733          */
734         vcp->vc_ustate = VCCU_NULL;
735         vcp->vc_sstate = UNI_NULL;
736         atm_free((caddr_t)vcp);
737
738         /*
739          * If we're detaching and this was the last VCC queued,
740          * get rid of the protocol instance
741          */
742         if ((usp->us_state == UNISIG_DETACH) &&
743                         (Q_HEAD(usp->us_vccq, struct vccb) == NULL)) {
744                 struct sigmgr   *smp = pip->pif_sigmgr;
745
746                 crit_enter();
747                 pip->pif_sigmgr = NULL;
748                 pip->pif_siginst = NULL;
749                 crit_exit();
750
751                 UNLINK((struct siginst *)usp, struct siginst,
752                                 smp->sm_prinst, si_next);
753                 KM_FREE(usp, sizeof(struct unisig), M_DEVBUF);
754         }
755
756         return (0);
757 }
758
759
760 /*
761  * UNISIG IOCTL support
762  *
763  * Function will be called from a critical section.
764  *
765  * Arguments:
766  *      code    PF_ATM sub-operation code
767  *      data    pointer to code specific parameter data area
768  *      arg1    pointer to code specific argument
769  *
770  * Returns:
771  *      0       request procesed
772  *      errno   error processing request - reason indicated
773  *
774  */
775 static int
776 unisig_ioctl(int code, caddr_t data, caddr_t arg1)
777 {
778         struct atmdelreq        *adp;
779         struct atminfreq        *aip;
780         struct atmsetreq        *asp;
781         struct unisig           *usp;
782         struct unisig_vccb      *uvp;
783         struct air_vcc_rsp      rsp;
784         struct atm_pif          *pip;
785         Atm_connection          *cop;
786         u_int                   vpi, vci;
787         int                     err = 0, buf_len, i;
788         caddr_t                 buf_addr;
789
790         ATM_DEBUG1("unisig_ioctl: code=%d\n", code);
791
792         switch (code) {
793
794         case AIOCS_DEL_PVC:
795         case AIOCS_DEL_SVC:
796                 /*
797                  * Delete a VCC
798                  */
799                 adp = (struct atmdelreq *)data;
800                 usp = (struct unisig *)arg1;
801
802                 /*
803                  * Don't let a user close the UNISIG signalling VC
804                  */
805                 vpi = adp->adr_pvc_vpi;
806                 vci = adp->adr_pvc_vci;
807                 if ((vpi == UNISIG_SIG_VPI && vci == UNISIG_SIG_VCI))
808                         return(EINVAL);
809
810                 /*
811                  * Find requested VCC
812                  */
813                 for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb); uvp;
814                                 uvp = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem)) {
815                         if ((uvp->uv_vpi == vpi) && (uvp->uv_vci == vci))
816                                 break;
817                 }
818                 if (uvp == NULL)
819                         return (ENOENT);
820
821                 /*
822                  * Check VCC type
823                  */
824                 switch (code) {
825                 case AIOCS_DEL_PVC:
826                         if (!(uvp->uv_type & VCC_PVC)) {
827                                 return(EINVAL);
828                         }
829                         break;
830                 case AIOCS_DEL_SVC:
831                         if (!(uvp->uv_type & VCC_SVC)) {
832                                 return(EINVAL);
833                         }
834                         break;
835                 }
836
837                 /*
838                  * Schedule VCC termination
839                  */
840                 unisig_cause_attr_from_user(&uvp->uv_connvc->cvc_attr,
841                                 T_ATM_CAUSE_UNSPECIFIED_NORMAL);
842                 err = unisig_abort((struct vccb *)uvp);
843                 break;
844
845         case AIOCS_INF_VCC:
846                 /*
847                  * Return VCC information
848                  */
849                 aip = (struct atminfreq *)data;
850                 usp = (struct unisig *)arg1;
851
852                 buf_addr = aip->air_buf_addr;
853                 buf_len = aip->air_buf_len;
854
855                 /*
856                  * Loop through the VCC queue
857                  */
858                 for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb); uvp;
859                                 uvp = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem)) {
860                         /*
861                          * Make sure there's room in the user's buffer
862                          */
863                         if (buf_len < sizeof(rsp)) {
864                                 err = ENOSPC;
865                                 break;
866                         }
867
868                         /*
869                          * Fill out the response struct for the VCC
870                          */
871                         ksnprintf(rsp.avp_intf,
872                                     sizeof(rsp.avp_intf), "%s%d",
873                                         usp->us_pif->pif_name,
874                                         usp->us_pif->pif_unit);
875                         rsp.avp_vpi = uvp->uv_vpi;
876                         rsp.avp_vci = uvp->uv_vci;
877                         rsp.avp_type = uvp->uv_type;
878                         rsp.avp_aal = uvp->uv_connvc->cvc_attr.aal.type;
879                         rsp.avp_sig_proto = uvp->uv_proto;
880                         cop = uvp->uv_connvc->cvc_conn;
881                         if (cop)
882                                 rsp.avp_encaps = cop->co_mpx;
883                         else
884                                 rsp.avp_encaps = 0;
885                         rsp.avp_state = uvp->uv_sstate;
886                         if (uvp->uv_connvc->cvc_flags & CVCF_CALLER) {
887                                 rsp.avp_daddr = uvp->uv_connvc->cvc_attr.called.addr;
888                         } else {
889                                 rsp.avp_daddr = uvp->uv_connvc->cvc_attr.calling.addr;
890                         }
891                         rsp.avp_dsubaddr.address_format = T_ATM_ABSENT;
892                         rsp.avp_dsubaddr.address_length = 0;
893                         rsp.avp_ipdus = uvp->uv_ipdus;
894                         rsp.avp_opdus = uvp->uv_opdus;
895                         rsp.avp_ibytes = uvp->uv_ibytes;
896                         rsp.avp_obytes = uvp->uv_obytes;
897                         rsp.avp_ierrors = uvp->uv_ierrors;
898                         rsp.avp_oerrors = uvp->uv_oerrors;
899                         rsp.avp_tstamp = uvp->uv_tstamp;
900                         KM_ZERO(rsp.avp_owners,
901                                         sizeof(rsp.avp_owners));
902                         for (i = 0; cop && i < sizeof(rsp.avp_owners);
903                                         cop = cop->co_next,
904                                         i += T_ATM_APP_NAME_LEN+1) {
905                                 strncpy(&rsp.avp_owners[i],
906                                         cop->co_endpt->ep_getname(cop->co_toku),
907                                         T_ATM_APP_NAME_LEN);
908                         }
909
910                         /*
911                          * Copy the response into the user's buffer
912                          */
913                         if ((err = copyout((caddr_t)&rsp, buf_addr,
914                                         sizeof(rsp))) != 0)
915                                 break;
916                         buf_addr += sizeof(rsp);
917                         buf_len -= sizeof(rsp);
918                 }
919
920                 /*
921                  * Update the buffer pointer and length
922                  */
923                 aip->air_buf_addr = buf_addr;
924                 aip->air_buf_len = buf_len;
925                 break;
926
927         case AIOCS_INF_ARP:
928         case AIOCS_INF_ASV:
929         case AIOCS_SET_ASV:
930                 /*
931                  * Get ARP table information or get/set ARP server address
932                  */
933                 err = uniarp_ioctl(code, data, arg1);
934                 break;
935
936         case AIOCS_SET_PRF:
937                 /*
938                  * Set NSAP prefix
939                  */
940                 asp = (struct atmsetreq *)data;
941                 usp = (struct unisig *)arg1;
942                 pip = usp->us_pif;
943                 if (usp->us_addr.address_format != T_ATM_ABSENT) {
944                         if (KM_CMP(asp->asr_prf_pref, usp->us_addr.address,
945                                         sizeof(asp->asr_prf_pref)) != 0)
946                                 err = EALREADY;
947                         break;
948                 }
949                 usp->us_addr.address_format = T_ATM_ENDSYS_ADDR;
950                 usp->us_addr.address_length = sizeof(Atm_addr_nsap);
951                 KM_COPY(&pip->pif_macaddr,
952                         ((Atm_addr_nsap *)usp->us_addr.address)->aan_esi,
953                         sizeof(pip->pif_macaddr));
954                 KM_COPY((caddr_t) asp->asr_prf_pref,
955                         &((Atm_addr_nsap *)usp->us_addr.address)->aan_afi,
956                         sizeof(asp->asr_prf_pref));
957                 log(LOG_INFO, "uni: set address %s on interface %s\n",
958                                 unisig_addr_print(&usp->us_addr),
959                                 asp->asr_prf_intf);
960
961                 /*
962                  * Pass event to signalling manager state machine
963                  */
964                 err = unisig_sigmgr_state(usp, UNISIG_SIGMGR_ADDR_SET, NULL);
965
966                 /*
967                  * Clean up if there was an error
968                  */
969                 if (err) {
970                         usp->us_addr.address_format = T_ATM_ABSENT;
971                         usp->us_addr.address_length = 0;
972                         break;
973                 }
974
975                 /*
976                  * Inform ARP code of new address
977                  */
978                 uniarp_ifaddr((struct siginst *)usp);
979                 break;
980
981         default:
982                 err = EOPNOTSUPP;
983         }
984
985         return (err);
986 }