kernel: Remove newlines from the panic messages that have one.
[dragonfly.git] / sys / netproto / atm / uni / unisig_vc_state.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_vc_state.c,v 1.6.2.1 2001/07/25 20:53:44 pirzyk Exp $
27  */
28
29 /*
30  * ATM Forum UNI 3.0/3.1 Signalling Manager
31  * ----------------------------------------
32  *
33  * VC state machine
34  *
35  */
36
37 #include <netproto/atm/kern_include.h>
38
39 #include "unisig_var.h"
40 #include "unisig_msg.h"
41
42 /*
43  * Local functions
44  */
45 static int      unisig_vc_invalid (struct unisig *, struct unisig_vccb *,
46                         struct unisig_msg *);
47 static int      unisig_vc_act01 (struct unisig *, struct unisig_vccb *,
48                         struct unisig_msg *);
49 static int      unisig_vc_act02 (struct unisig *, struct unisig_vccb *,
50                         struct unisig_msg *);
51 static int      unisig_vc_act03 (struct unisig *, struct unisig_vccb *,
52                         struct unisig_msg *);
53 static int      unisig_vc_act04 (struct unisig *, struct unisig_vccb *,
54                         struct unisig_msg *);
55 static int      unisig_vc_act05 (struct unisig *, struct unisig_vccb *,
56                         struct unisig_msg *);
57 static int      unisig_vc_act06 (struct unisig *, struct unisig_vccb *,
58                         struct unisig_msg *);
59 static int      unisig_vc_act07 (struct unisig *, struct unisig_vccb *,
60                         struct unisig_msg *);
61 static int      unisig_vc_act08 (struct unisig *, struct unisig_vccb *,
62                         struct unisig_msg *);
63 static int      unisig_vc_act09 (struct unisig *, struct unisig_vccb *,
64                         struct unisig_msg *);
65 static int      unisig_vc_act10 (struct unisig *, struct unisig_vccb *,
66                         struct unisig_msg *);
67 static int      unisig_vc_act11 (struct unisig *, struct unisig_vccb *,
68                         struct unisig_msg *);
69 static int      unisig_vc_act12 (struct unisig *, struct unisig_vccb *,
70                         struct unisig_msg *);
71 static int      unisig_vc_act13 (struct unisig *, struct unisig_vccb *,
72                         struct unisig_msg *);
73 static int      unisig_vc_act14 (struct unisig *, struct unisig_vccb *,
74                         struct unisig_msg *);
75 static int      unisig_vc_act15 (struct unisig *, struct unisig_vccb *,
76                         struct unisig_msg *);
77 static int      unisig_vc_act16 (struct unisig *, struct unisig_vccb *,
78                         struct unisig_msg *);
79 static int      unisig_vc_act17 (struct unisig *, struct unisig_vccb *,
80                         struct unisig_msg *);
81 static int      unisig_vc_act18 (struct unisig *, struct unisig_vccb *,
82                         struct unisig_msg *);
83 static int      unisig_vc_act19 (struct unisig *, struct unisig_vccb *,
84                         struct unisig_msg *);
85 static int      unisig_vc_act20 (struct unisig *, struct unisig_vccb *,
86                         struct unisig_msg *);
87 static int      unisig_vc_act21 (struct unisig *, struct unisig_vccb *,
88                         struct unisig_msg *);
89 static int      unisig_vc_act22 (struct unisig *, struct unisig_vccb *,
90                         struct unisig_msg *);
91 static int      unisig_vc_act23 (struct unisig *, struct unisig_vccb *,
92                         struct unisig_msg *);
93 static int      unisig_vc_act24 (struct unisig *, struct unisig_vccb *,
94                         struct unisig_msg *);
95 static int      unisig_vc_act25 (struct unisig *, struct unisig_vccb *,
96                         struct unisig_msg *);
97 static int      unisig_vc_act26 (struct unisig *, struct unisig_vccb *,
98                         struct unisig_msg *);
99 static int      unisig_vc_act27 (struct unisig *, struct unisig_vccb *,
100                         struct unisig_msg *);
101 static int      unisig_vc_act28 (struct unisig *, struct unisig_vccb *,
102                         struct unisig_msg *);
103 static int      unisig_vc_act29 (struct unisig *, struct unisig_vccb *,
104                         struct unisig_msg *);
105 static int      unisig_vc_act30 (struct unisig *, struct unisig_vccb *,
106                         struct unisig_msg *);
107 static int      unisig_vc_act31 (struct unisig *, struct unisig_vccb *,
108                         struct unisig_msg *);
109 static int      unisig_vc_clear_call (struct unisig *,
110                         struct unisig_vccb *,
111                         struct unisig_msg *,
112                         int);
113
114
115 /*
116  * State table
117  */
118 static int      unisig_vc_states[21][17] = {
119 /* 0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16 */
120 {  0,  2, 99,  5, 99, 99,  0, 99, 12, 99,  0, 14,  0,  3,  0,  0,  0 },
121 { 29,  4, 99, 17, 99, 99, 17, 99, 17, 99, 17, 17, 17,  0,  0,  0,  0 },
122 { 29,  6, 99,  6, 99, 99, 17, 99, 17, 99, 17, 17, 17,  0,  0,  0,  0 },
123 { 29, 17, 99, 17, 99, 99, 17, 99, 10, 99, 17, 17, 17,  0,  0,  0,  0 },
124 {  8, 17, 99, 17, 99, 99, 17, 99, 17, 99, 17, 17, 17,  0,  0,  0,  0 },
125 { 29,  7, 99, 15, 99, 99, 15, 99, 15, 99, 15, 16, 17,  0,  0,  0,  0 },
126 { 19,  3, 99,  3, 99, 99,  3, 99,  3, 99,  3, 13,  3,  0,  0,  0,  0 },
127 { 21, 21, 99, 21, 99, 99, 21, 99, 21, 99, 21, 21, 21,  0,  0,  0,  0 },
128 { 22, 22, 99, 22, 99, 99, 22, 99, 22, 99, 22, 22, 22,  0,  0,  0,  0 },
129 { 29, 17, 99, 17, 99, 99, 17, 99, 17, 99, 23, 17, 17,  0,  0,  0,  0 },
130 { 29, 17, 99, 17, 99, 99, 17, 99, 17, 99, 17, 17, 17,  0,  0,  0,  0 },
131 { 29, 17, 99, 17, 99, 99, 17, 99, 17, 99, 17, 17, 17,  0,  0,  0,  0 },
132 { 29, 17, 99, 17, 99, 99, 17, 99, 17, 99, 17, 17, 17,  0,  0,  0,  0 },
133 { 29, 17, 99, 17, 99, 99, 17, 99, 17, 99, 17, 17, 17,  0,  0,  0,  0 },
134 {  1, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99 },
135 { 99, 25, 99, 25, 99, 99,  9, 99, 25, 99, 25, 25, 25, 25, 31, 25, 25 },
136 { 99, 25, 99, 25, 99, 99, 11, 99, 25, 99, 25, 25, 25, 25, 19, 25, 25 },
137 { 99, 12, 99, 12, 99, 99, 25, 99, 12, 99, 12, 19, 19, 30, 19, 99, 99 },
138 { 99, 12, 99, 12, 99, 99, 12, 99, 12, 99, 12,  3,  3,  3, 24, 26, 26 },
139 { 99,  3, 99,  3, 99, 99, 30, 99,  3, 99, 18,  3,  3,  0, 19, 27, 19 },
140 { 99,  7, 99,  7, 99, 99, 30, 99,  7, 99, 19, 19, 19, 20, 19, 19, 28 }
141 };
142
143
144 /*
145  * Action vector
146  *
147  * A given state, action pair selects an action number from the
148  * state table.  This vector holds the address of the action routine
149  * for each action number.
150  */
151 #define MAX_ACTION      32
152 static int (*unisig_vc_act_vec[MAX_ACTION])
153                 (struct unisig *, struct unisig_vccb *,
154                         struct unisig_msg *) = {
155         unisig_vc_invalid,
156         unisig_vc_act01,        
157         unisig_vc_act02,
158         unisig_vc_act03,
159         unisig_vc_act04,
160         unisig_vc_act05,
161         unisig_vc_act06,
162         unisig_vc_act07,
163         unisig_vc_act08,
164         unisig_vc_act09,
165         unisig_vc_act10,
166         unisig_vc_act11,
167         unisig_vc_act12,
168         unisig_vc_act13,
169         unisig_vc_act14,
170         unisig_vc_act15,
171         unisig_vc_act16,
172         unisig_vc_act17,
173         unisig_vc_act18,
174         unisig_vc_act19,
175         unisig_vc_act20,
176         unisig_vc_act21,
177         unisig_vc_act22,
178         unisig_vc_act23,
179         unisig_vc_act24,
180         unisig_vc_act25,
181         unisig_vc_act26,
182         unisig_vc_act27,
183         unisig_vc_act28,
184         unisig_vc_act29,
185         unisig_vc_act30,
186         unisig_vc_act31
187 };
188
189
190 /*
191  * Process an event on a VC
192  *
193  * Arguments:
194  *      usp     pointer to the UNISIG instance
195  *      uvp     pointer to the VCCB for the affected VCC
196  *      event   a numeric indication of which event has occured
197  *      msg     pointer to a signalling message structure
198  *
199  * Returns:
200  *      0       success
201  *      errno   error encountered
202  *
203  */
204 int
205 unisig_vc_state(struct unisig *usp, struct unisig_vccb *uvp, int event,
206                 struct unisig_msg *msg)
207 {
208         int     action, rc, state;
209
210         /*
211          * Select an action from the state table
212          */
213         if (uvp)
214                 state = uvp->uv_sstate;
215         else
216                 state = UNI_NULL;
217         action = unisig_vc_states[event][state];
218         if (action >= MAX_ACTION || action < 0)
219                 panic("unisig_vc_state: invalid action");
220
221         /*
222          * Perform the requested action
223          */
224         ATM_DEBUG4("unisig_vc_state: uvp=%p, state=%d, event=%d, action=%d\n",
225                         uvp, state, event, action);
226         rc = unisig_vc_act_vec[action](usp, uvp, msg);
227
228         return(rc);
229 }
230
231
232 /*
233  * VC state machine action 0
234  * Unexpected action - log an error message
235  *
236  * Arguments:
237  *      usp     pointer to protocol instance block
238  *      uvp     pointer to the VCCB for the affected connection (may
239                 be null)
240  *      msg     pointer to a UNISIG message structure
241  *
242  * Returns:
243  *      0       success
244  *      errno   error encountered
245  *
246  */
247 static int
248 unisig_vc_invalid(struct unisig *usp, struct unisig_vccb *uvp,
249                   struct unisig_msg *msg)
250 {
251         log(LOG_ERR, "unisig_vc_state: unexpected action\n");
252         return(EINVAL);
253 }
254
255
256 /*
257  * VC state machine action 1
258  * Setup handler called
259  *
260  * Send SETUP, start timer T303, go to UNI_CALL_INITIATED state
261  *
262  * Arguments:
263  *      usp     pointer to protocol instance block
264  *      uvp     pointer to the VCCB for the affected connection
265  *      msg     pointer to a UNISIG message structure
266  *
267  * Returns:
268  *      0       success
269  *      errno   error encountered
270  *
271  */
272 static int
273 unisig_vc_act01(struct unisig *usp, struct unisig_vccb *uvp,
274                 struct unisig_msg *msg)
275 {
276         int             rc;
277
278         /*
279          * Send the setup message
280          */
281         rc = unisig_send_setup(usp, uvp);
282         if (rc)
283                 return(rc);
284
285         /*
286          * Set timer T303
287          */
288         uvp->uv_retry = 0;
289         UNISIG_VC_TIMER((struct vccb *) uvp, UNI_T303);
290
291         /*
292          * Set the new state
293          */
294         uvp->uv_sstate = UNI_CALL_INITIATED;
295
296         /*
297          * Mark the time
298          */
299         uvp->uv_tstamp = time_second;
300
301         return(0);
302 }
303
304
305 /*
306  * VC state machine action 2
307  * Timeout while waiting for CALL PROCEEDING or CONNECT
308  *
309  * If this is the second expiration, clear the call.  Otherwise,
310  * retransmit the SETUP message and restart T303.
311  *
312  * Arguments:
313  *      usp     pointer to protocol instance block
314  *      uvp     pointer to the VCCB for the affected connection
315  *      msg     pointer to a UNISIG message structure
316  *
317  * Returns:
318  *      0       success
319  *      errno   error encountered
320  *
321  */
322 static int
323 unisig_vc_act02(struct unisig *usp, struct unisig_vccb *uvp,
324                 struct unisig_msg *msg)
325 {
326         int     rc = 0;
327
328         if (uvp->uv_retry) {
329                 /*
330                  * Clear the call
331                  */
332                 rc = unisig_clear_vcc(usp, uvp,
333                                 T_ATM_CAUSE_NO_ROUTE_TO_DESTINATION);
334         } else {
335                 uvp->uv_retry++;
336                 unisig_send_setup(usp, uvp);
337                 UNISIG_VC_TIMER((struct vccb *) uvp, UNI_T303);
338         }
339         
340         return(rc);
341 }
342
343
344 /*
345  * VC state machine action 3
346  *
347  * Clear the call internally
348  *
349  * Arguments:
350  *      usp     pointer to protocol instance block
351  *      uvp     pointer to the VCCB for the affected connection
352  *      msg     pointer to a UNISIG message structure
353  *
354  * Returns:
355  *      0       success
356  *      errno   error encountered
357  *
358  */
359 static int
360 unisig_vc_act03(struct unisig *usp, struct unisig_vccb *uvp,
361                 struct unisig_msg *msg)
362 {
363         int     rc, cause;
364
365         /*
366          * Set cause code
367          */
368         if ((msg != NULL) && (msg->msg_ie_caus != NULL)) {
369                 unisig_cause_attr_from_ie(&uvp->uv_connvc->cvc_attr,
370                         msg->msg_ie_caus);
371                 cause = T_ATM_ABSENT;
372         } else
373                 cause = T_ATM_CAUSE_DESTINATION_OUT_OF_ORDER;
374
375         /*
376          * Clear the VCCB
377          */
378         rc = unisig_clear_vcc(usp, uvp, cause);
379
380         return(rc);
381 }
382
383
384 /*
385  * VC state machine action 4
386  * Received CALL PROCEEDING
387  *
388  * Start timer T310, go to UNI_CALL_OUT_PROC
389  *
390  * Arguments:
391  *      usp     pointer to protocol instance block
392  *      uvp     pointer to the VCCB for the affected connection
393  *      msg     pointer to a UNISIG message structure
394  *
395  * Returns:
396  *      0       success
397  *      errno   error encountered
398  *
399  */
400 static int
401 unisig_vc_act04(struct unisig *usp, struct unisig_vccb *uvp,
402                 struct unisig_msg *msg)
403 {
404         int                     cause, rc, vpi, vci;
405         struct atm_pif          *pip = usp->us_pif;
406         struct ie_generic       *iep;
407
408         /*
409          * Clear any running timer
410          */
411         UNISIG_VC_CANCEL((struct vccb *) uvp);
412
413         /*
414          * Make sure a Connection ID is part of the message
415          */
416         if (msg->msg_ie_cnid) {
417                 vpi = msg->msg_ie_cnid->ie_cnid_vpci;
418                 vci = msg->msg_ie_cnid->ie_cnid_vci;
419         } else {
420                 iep = (struct ie_generic *)atm_allocate(&unisig_iepool);
421                 if (!iep)
422                         return(ENOMEM);
423                 iep->ie_ident = UNI_IE_CNID;
424                 iep->ie_err_cause = UNI_IE_CAUS_MISSING;
425                 MSG_IE_ADD(msg, iep, UNI_MSG_IE_ERR);
426                 cause = UNI_IE_CAUS_MISSING;
427                 ATM_DEBUG0("unisig_vc_act04: no CNID in Call Proc\n");
428                 goto response04;
429         }
430
431         /*
432          * Make sure we can handle the specified VPI and VCI
433          */
434         if (vpi > pip->pif_maxvpi  || vci > pip->pif_maxvci ||
435                         vci < UNI_IE_CNID_MIN_VCI) {
436                 cause = UNI_IE_CAUS_BAD_VCC;
437                 ATM_DEBUG0("unisig_vc_act04: VPI/VCI invalid\n");
438                 goto response04;
439         }
440
441         /*
442          * Make sure the specified VPI and VCI are not in use
443          */
444         if (unisig_find_vpvc(usp, vpi, vci, VCC_OUT)) {
445                 cause = UNI_IE_CAUS_NA_VCC;
446                 ATM_DEBUG0("unisig_vc_act04: VPI/VCI in use\n");
447                 goto response04;
448         }
449
450         /*
451          * Start timer T310
452          */
453         UNISIG_VC_TIMER((struct vccb *) uvp, UNI_T310);
454
455         /*
456          * Save the specified VPI and VCI
457          */
458         uvp->uv_vpi = vpi;
459         uvp->uv_vci = vci;
460
461         /*
462          * Set the state
463          */
464         uvp->uv_sstate = UNI_CALL_OUT_PROC;
465
466         /*
467          * Mark the time
468          */
469         uvp->uv_tstamp = time_second;
470
471         return(0);
472
473 response04:
474         /*
475          * Initiate call clearing
476          */
477         rc = unisig_vc_clear_call(usp, uvp, msg, cause);
478
479         return(rc);
480 }
481
482
483 /*
484  * VC state machine action 5
485  * Timeout in UNI_CALL_OUT_PROC
486  * 
487  * Clear call towards network
488  *
489  * Arguments:
490  *      usp     pointer to protocol instance block
491  *      uvp     pointer to the VCCB for the affected connection
492  *      msg     pointer to a UNISIG message structure
493  *
494  * Returns:
495  *      0       success
496  *      errno   error encountered
497  *
498  */
499 static int
500 unisig_vc_act05(struct unisig *usp, struct unisig_vccb *uvp,
501                 struct unisig_msg *msg)
502 {
503         int                     rc;
504         struct unisig_msg       *rls_msg;
505         struct ie_generic       *cause_ie;
506
507         /*
508          * Send a RELEASE message
509          */
510         rls_msg = (struct unisig_msg *) atm_allocate(&unisig_msgpool);
511         if (rls_msg == NULL)
512                 return(ENOMEM);
513         cause_ie = (struct ie_generic *) atm_allocate(&unisig_iepool);
514         if (cause_ie == NULL) {
515                 atm_free(rls_msg);
516                 return(ENOMEM);
517         }
518
519         /*
520          * Fill out the RELEASE message
521          */
522         rls_msg->msg_call_ref = uvp->uv_call_ref;
523         rls_msg->msg_type = UNI_MSG_RLSE;
524         rls_msg->msg_type_flag = 0;
525         rls_msg->msg_type_action = 0;
526         rls_msg->msg_ie_caus = cause_ie;
527
528         /*
529          * Fill out the cause IE
530          */
531         cause_ie->ie_caus_loc = UNI_IE_CAUS_LOC_USER;
532         cause_ie->ie_caus_cause = UNI_IE_CAUS_TIMER;
533         KM_COPY("310", cause_ie->ie_caus_diagnostic, 3);
534
535         /*
536          * Send the RELEASE message.
537          */
538         rc = unisig_send_msg(usp, rls_msg);
539         unisig_free_msg(rls_msg);
540
541         /*
542          * Start timer T308
543          */
544         UNISIG_VC_TIMER((struct vccb *) uvp, UNI_T308);
545
546         /*
547          * Set the new state
548          */
549         uvp->uv_sstate = UNI_RELEASE_REQUEST;
550         uvp->uv_ustate = VCCU_CLOSED;
551
552         /*
553          * Mark the time
554          */
555         uvp->uv_tstamp = time_second;
556
557         return(rc);
558 }
559
560
561 /*
562  * VC state machine action 6
563  * Received CONNECT
564  *
565  * Send CONNECT ACK, go to UNI_ACTIVE state
566  *
567  * Arguments:
568  *      usp     pointer to protocol instance block
569  *      uvp     pointer to the VCCB for the affected connection
570  *      msg     pointer to a UNISIG message structure
571  *
572  * Returns:
573  *      0       success
574  *      errno   error encountered
575  *
576  */
577 static int
578 unisig_vc_act06(struct unisig *usp, struct unisig_vccb *uvp,
579                 struct unisig_msg *msg)
580 {
581         int                     cause, rc, vci, vpi;
582         struct atm_pif          *pip = usp->us_pif;
583         struct unisig_msg       *cack_msg;
584         struct ie_generic       *iep;
585         Atm_attributes          *ap;
586
587         /*
588          * Clear any running timer
589          */
590         UNISIG_VC_CANCEL((struct vccb *) uvp);
591
592         ap = &uvp->uv_connvc->cvc_attr;
593
594         /*
595          * See if a VPI/VCI is specified
596          */
597         if (msg->msg_ie_cnid) {
598                 /*
599                  * Yes--VPI/VCI must be the first specification or must
600                  * match what was specified before
601                  */
602                 vpi = msg->msg_ie_cnid->ie_cnid_vpci;
603                 vci = msg->msg_ie_cnid->ie_cnid_vci;
604                 if ((uvp->uv_vpi || uvp->uv_vci) &&
605                                 (vpi != uvp->uv_vpi ||
606                                 vci != uvp->uv_vci)) {
607                         cause = UNI_IE_CAUS_BAD_VCC;
608                         ATM_DEBUG0("unisig_vc_act06: VPI/VCI invalid\n");
609                         goto response06;
610                 }
611
612                 /*
613                  * Specified VPI/VCI must be within range
614                  */
615                 if (vpi > pip->pif_maxvpi || vci > pip->pif_maxvci ||
616                                 vci < UNI_IE_CNID_MIN_VCI) {
617                         cause = UNI_IE_CAUS_BAD_VCC;
618                         ATM_DEBUG0("unisig_vc_act06: VPI/VCI invalid\n");
619                         goto response06;
620                 }
621                 uvp->uv_vpi = vpi;
622                 uvp->uv_vci = vci;
623         } else {
624                 /*
625                  * No--VCI must have been specified earlier
626                  */
627                 if (!uvp->uv_vci) {
628                         iep = (struct ie_generic *)atm_allocate(
629                                         &unisig_iepool);
630                         if (!iep)
631                                 return(ENOMEM);
632                         iep->ie_ident = UNI_IE_CNID;
633                         iep->ie_err_cause = UNI_IE_CAUS_MISSING;
634                         MSG_IE_ADD(msg, iep, UNI_MSG_IE_ERR);
635                         cause = UNI_IE_CAUS_MISSING;
636                         ATM_DEBUG0("unisig_vc_act06: CNID missing\n");
637                         goto response06;
638                 }
639         }
640
641         /*
642          * Handle AAL parameters negotiation
643          */
644         if (msg->msg_ie_aalp) {
645                 struct ie_generic       *aalp = msg->msg_ie_aalp;
646
647                 /*
648                  * AAL parameters must have been sent in SETUP
649                  */
650                 if ((ap->aal.tag != T_ATM_PRESENT) ||
651                     (ap->aal.type != aalp->ie_aalp_aal_type)) {
652                         cause = UNI_IE_CAUS_IECONTENT;
653                         goto response06;
654                 }
655
656                 switch (aalp->ie_aalp_aal_type) {
657
658                 case UNI_IE_AALP_AT_AAL3:
659                         /*
660                          * Maximum SDU size negotiation
661                          */
662                         if (aalp->ie_aalp_4_fwd_max_sdu == T_ATM_ABSENT)
663                                 break;
664                         if ((ap->aal.v.aal4.forward_max_SDU_size < 
665                                         aalp->ie_aalp_4_fwd_max_sdu) ||
666                             (ap->aal.v.aal4.backward_max_SDU_size <
667                                         aalp->ie_aalp_4_bkwd_max_sdu)) {
668                                 cause = UNI_IE_CAUS_IECONTENT;
669                                 goto response06;
670                         } else {
671                                 ap->aal.v.aal4.forward_max_SDU_size =
672                                         aalp->ie_aalp_4_fwd_max_sdu;
673                                 ap->aal.v.aal4.backward_max_SDU_size =
674                                         aalp->ie_aalp_4_bkwd_max_sdu;
675                         }
676                         break;
677
678                 case UNI_IE_AALP_AT_AAL5:
679                         /*
680                          * Maximum SDU size negotiation
681                          */
682                         if (aalp->ie_aalp_5_fwd_max_sdu == T_ATM_ABSENT)
683                                 break;
684                         if ((ap->aal.v.aal5.forward_max_SDU_size < 
685                                         aalp->ie_aalp_5_fwd_max_sdu) ||
686                             (ap->aal.v.aal5.backward_max_SDU_size <
687                                         aalp->ie_aalp_5_bkwd_max_sdu)) {
688                                 cause = UNI_IE_CAUS_IECONTENT;
689                                 goto response06;
690                         } else {
691                                 ap->aal.v.aal5.forward_max_SDU_size =
692                                         aalp->ie_aalp_5_fwd_max_sdu;
693                                 ap->aal.v.aal5.backward_max_SDU_size =
694                                         aalp->ie_aalp_5_bkwd_max_sdu;
695                         }
696                         break;
697                 }
698         }
699
700         /*
701          * Get memory for a CONNECT ACK message
702          */
703         cack_msg = (struct unisig_msg *) atm_allocate(&unisig_msgpool);
704         if (cack_msg == NULL)
705                 return(ENOMEM);
706
707         /*
708          * Fill out the CONNECT ACK message
709          */
710         cack_msg->msg_call_ref = uvp->uv_call_ref;
711         cack_msg->msg_type = UNI_MSG_CACK;
712         cack_msg->msg_type_flag = 0;
713         cack_msg->msg_type_action = 0;
714
715         /*
716          * Send the CONNECT ACK message
717          */
718         rc = unisig_send_msg(usp, cack_msg);
719         unisig_free_msg(cack_msg);
720
721         /*
722          * Set the new state
723          */
724         uvp->uv_sstate = UNI_ACTIVE;
725         uvp->uv_ustate = VCCU_OPEN;
726
727         /*
728          * Mark the time
729          */
730         uvp->uv_tstamp = time_second;
731
732         /*
733          * Notify the user that the connection is now active
734          */
735         atm_cm_connected(uvp->uv_connvc);
736
737         return(0);
738
739 response06:
740         /*
741          * Initiate call clearing
742          */
743         rc = unisig_vc_clear_call(usp, uvp, msg, cause);
744
745         return(rc);
746 }
747
748
749 /*
750  * VC state machine action 7
751  * Abort routine called or signalling SAAL session reset while in
752  * one of the call setup states
753  *
754  * Clear the call, send RELEASE COMPLETE, notify the user.
755  *
756  * Arguments:
757  *      usp     pointer to protocol instance block
758  *      uvp     pointer to the VCCB for the affected connection
759  *      msg     pointer to a UNISIG message structure
760  *
761  * Returns:
762  *      0       success
763  *      errno   error encountered
764  *
765  */
766 static int
767 unisig_vc_act07(struct unisig *usp, struct unisig_vccb *uvp,
768                 struct unisig_msg *msg)
769 {
770         int                     rc;
771
772         /*
773          * Clear any running timer
774          */
775         UNISIG_VC_CANCEL((struct vccb *) uvp);
776
777         /*
778          * Send a RELEASE COMPLETE message rejecting the connection
779          */
780         rc = unisig_send_release_complete(usp, uvp, msg,
781                         UNI_IE_CAUS_TEMP);
782
783         /*
784          * Clear the call VCCB
785          */
786         uvp->uv_sstate = UNI_FREE;
787         uvp->uv_ustate = VCCU_CLOSED;
788
789         /*
790          * Mark the time
791          */
792         uvp->uv_tstamp = time_second;
793
794         /*
795          * Notify the user
796          */
797         if ((msg != NULL) && (msg->msg_ie_caus != NULL))
798                 unisig_cause_attr_from_ie(&uvp->uv_connvc->cvc_attr,
799                         msg->msg_ie_caus);
800         else
801                 unisig_cause_attr_from_user(&uvp->uv_connvc->cvc_attr,
802                         T_ATM_CAUSE_NORMAL_CALL_CLEARING);
803         atm_cm_cleared(uvp->uv_connvc);
804
805         return(rc);
806 }
807
808
809 /*
810  * VC state machine action 8
811  * Received SETUP
812  *
813  * Check call paramaters, notify user that a call has been received,
814  * set UNI_CALL_PRESENT state
815  *
816  * Arguments:
817  *      usp     pointer to protocol instance block
818  *      uvp     pointer to the VCCB for the affected connection
819  *      msg     pointer to a UNISIG message structure
820  *
821  * Returns:
822  *      0       success
823  *      errno   error encountered
824  *
825  */
826 static int
827 unisig_vc_act08(struct unisig *usp, struct unisig_vccb *uvp,
828                 struct unisig_msg *msg)
829 {
830         int                     cause = 0, rc, vpi, vci;
831         struct atm_pif          *pip = usp->us_pif;
832         struct atm_nif          *nip;
833         Atm_addr_nsap           *nap;
834         Atm_attributes          attr;
835
836         ATM_DEBUG3("unisig_vc_act08: usp=%p, uvp=%p, msg=%p\n",
837                         usp, uvp, msg);
838
839         /*
840          * Make sure that the called address is the right format
841          */
842         if (msg->msg_ie_cdad->ie_cdad_plan != UNI_IE_CDAD_PLAN_NSAP) {
843                 cause = UNI_IE_CAUS_IECONTENT;
844                 ATM_DEBUG0("unisig_vc_act08: bad address format\n");
845                 goto response08;
846         }
847
848         /*
849          * Make sure that the called address is ours
850          */
851         nap = (Atm_addr_nsap *) msg->msg_ie_cdad->ie_cdad_addr.address;
852         if (bcmp(usp->us_addr.address, nap,     /* XXX */
853                         sizeof(Atm_addr_nsap)-1)) {
854                 cause = UNI_IE_CAUS_IECONTENT;
855                 ATM_DEBUG0("unisig_vc_act08: address not mine\n");
856                 goto response08;
857         }
858
859         /*
860          * Find the right NIF for the given selector byte
861          */
862         nip = pip->pif_nif;
863         while (nip && nip->nif_sel != nap->aan_sel) {
864                 nip = nip->nif_pnext;
865         }
866         if (!nip) {
867                 cause = UNI_IE_CAUS_IECONTENT;
868                 ATM_DEBUG0("unisig_vc_act08: bad selector byte\n");
869                 goto response08;
870         }
871
872         /*
873          * See if we recognize the specified AAL
874          */
875         if (msg->msg_ie_aalp->ie_aalp_aal_type != UNI_IE_AALP_AT_AAL3 &&
876                         msg->msg_ie_aalp->ie_aalp_aal_type !=
877                         UNI_IE_AALP_AT_AAL5) {
878                 cause = UNI_IE_CAUS_UAAL;
879                 ATM_DEBUG0("unisig_vc_act08: bad AAL\n");
880                 goto response08;
881         }
882
883         /*
884          * Should verify that we can handle requested
885          * connection QOS
886          */
887
888         /*
889          * Make sure the specified VPI/VCI is valid
890          */
891         vpi = msg->msg_ie_cnid->ie_cnid_vpci;
892         vci = msg->msg_ie_cnid->ie_cnid_vci;
893         if (vpi > pip->pif_maxvpi ||
894                         vci > pip->pif_maxvci ||
895                         vci < UNI_IE_CNID_MIN_VCI) {
896                 cause = UNI_IE_CAUS_BAD_VCC;
897                 ATM_DEBUG0("unisig_vc_act08: VPI/VCI invalid\n");
898                 goto response08;
899         }
900
901         /*
902          * Make sure the specified VPI/VCI isn't in use already
903          */
904         if (unisig_find_vpvc(usp, vpi, vci, VCC_IN)) {
905                 cause = UNI_IE_CAUS_NA_VCC;
906                 ATM_DEBUG0("unisig_vc_act08: VPI/VCI in use\n");
907                 goto response08;
908         }
909
910         /*
911          * Make sure it's a point-to-point connection
912          */
913         if (msg->msg_ie_bbcp->ie_bbcp_conn_config !=
914                         UNI_IE_BBCP_CC_PP) {
915                 cause = UNI_IE_CAUS_NI_BC;
916                 ATM_DEBUG0("unisig_vc_act08: conn not pt-pt\n");
917                 goto response08;
918         }
919
920         /*
921          * Fill in the VCCB fields that we can at this point
922          */
923         uvp->uv_type = VCC_SVC | VCC_IN | VCC_OUT;
924         uvp->uv_proto = pip->pif_sigmgr->sm_proto;
925         uvp->uv_sstate = UNI_CALL_PRESENT;
926         uvp->uv_ustate = VCCU_POPEN;
927         uvp->uv_pif = pip;
928         uvp->uv_nif = nip;
929         uvp->uv_vpi = msg->msg_ie_cnid->ie_cnid_vpci;
930         uvp->uv_vci = msg->msg_ie_cnid->ie_cnid_vci;
931         uvp->uv_tstamp = time_second;
932
933         /*
934          * Copy the connection attributes from the SETUP message
935          * to an attribute block
936          */
937         KM_ZERO(&attr, sizeof(attr));
938         attr.nif = nip;
939         attr.aal.tag = T_ATM_ABSENT;
940         attr.traffic.tag = T_ATM_ABSENT;
941         attr.bearer.tag = T_ATM_ABSENT;
942         attr.bhli.tag = T_ATM_ABSENT;
943         attr.blli.tag_l2 = T_ATM_ABSENT;
944         attr.blli.tag_l3 = T_ATM_ABSENT;
945         attr.llc.tag = T_ATM_ABSENT;
946         attr.called.tag = T_ATM_ABSENT;
947         attr.calling.tag = T_ATM_ABSENT;
948         attr.qos.tag = T_ATM_ABSENT;
949         attr.transit.tag = T_ATM_ABSENT;
950         attr.cause.tag = T_ATM_ABSENT;
951         unisig_save_attrs(usp, msg, &attr);
952
953         /*
954          * Notify the connection manager of the new VCC
955          */
956         ATM_DEBUG0("unisig_vc_act08: notifying user of connection\n");
957         rc = atm_cm_incoming((struct vccb *)uvp, &attr);
958         if (rc)
959                 goto response08;
960
961         /*
962          * Wait for the connection recipient to issue an accept
963          * or reject
964          */
965         return(0);
966
967 response08:
968         ATM_DEBUG1("unisig_vc_act08: reject with cause=%d\n", cause);
969
970         /*
971          * Clear the VCCB state
972          */
973         uvp->uv_sstate = UNI_NULL;
974
975         /*
976          * Mark the time
977          */
978         uvp->uv_tstamp = time_second;
979
980         /*
981          * Some problem was detected with the request.  Send a Q.2931
982          * message rejecting the connection.
983          */
984         rc = unisig_send_release_complete(usp, uvp, msg, cause);
985
986         return(rc);
987 }
988
989
990 /*
991  * VC state machine action 9
992  * Accept routine called by user
993  *
994  * Send CONNECT, start timer T313, go to UNI_CONNECT_REQUEST state
995  *
996  * Arguments:
997  *      usp     pointer to protocol instance block
998  *      uvp     pointer to the VCCB for the affected connection
999  *      msg     pointer to a UNISIG message structure
1000  *
1001  * Returns:
1002  *      0       success
1003  *      errno   error encountered
1004  *
1005  */
1006 static int
1007 unisig_vc_act09(struct unisig *usp, struct unisig_vccb *uvp,
1008                 struct unisig_msg *msg)
1009 {
1010         int                     rc;
1011         struct unisig_msg       *conn_msg;
1012
1013         conn_msg = (struct unisig_msg *) atm_allocate(&unisig_msgpool);
1014         if (conn_msg == NULL)
1015                 return(ENOMEM);
1016
1017         /*
1018          * Fill out the response
1019          */
1020         conn_msg->msg_call_ref = uvp->uv_call_ref;
1021         conn_msg->msg_type = UNI_MSG_CONN;
1022         conn_msg->msg_type_flag = 0;
1023         conn_msg->msg_type_action = 0;
1024
1025         /*
1026          * Send the CONNECT message.  If the send fails, the other
1027          * side will eventually time out and close the connection.
1028          */
1029         rc = unisig_send_msg(usp, conn_msg);
1030         unisig_free_msg(conn_msg);
1031         if (rc) {
1032                 return(rc);
1033         }
1034
1035         /*
1036          * Start timer T313
1037          */
1038         UNISIG_VC_TIMER((struct vccb *) uvp, UNI_T313);
1039
1040         /*
1041          * Set the new state
1042          */
1043         uvp->uv_sstate = UNI_CONNECT_REQUEST;
1044
1045         /*
1046          * Mark the time
1047          */
1048         uvp->uv_tstamp = time_second;
1049
1050         return(0);
1051 }
1052
1053
1054 /*
1055  * VC state machine action 10
1056  * Received CONNECT ACK
1057  *
1058  * Go to UNI_ACTIVE state
1059  *
1060  * Arguments:
1061  *      usp     pointer to protocol instance block
1062  *      uvp     pointer to the VCCB for the affected connection
1063  *      msg     pointer to a UNISIG message structure
1064  *
1065  * Returns:
1066  *      0       success
1067  *      errno   error encountered
1068  *
1069  */
1070 static int
1071 unisig_vc_act10(struct unisig *usp, struct unisig_vccb *uvp,
1072                 struct unisig_msg *msg)
1073 {
1074         /*
1075          * Clear any running timer
1076          */
1077         UNISIG_VC_CANCEL((struct vccb *) uvp);
1078
1079         /*
1080          * Set the state
1081          */
1082         uvp->uv_sstate = UNI_ACTIVE;
1083         uvp->uv_ustate = VCCU_OPEN;
1084
1085         /*
1086          * Mark the time
1087          */
1088         uvp->uv_tstamp = time_second;
1089
1090         /*
1091          * Notify the user that the call is up
1092          */
1093         atm_cm_connected(uvp->uv_connvc);
1094
1095         return (0);
1096 }
1097
1098
1099 /*
1100  * VC state machine action 11
1101  * Reject handler called
1102  *
1103  * Send RELEASE COMPLETE, clear the call
1104  *
1105  * Arguments:
1106  *      usp     pointer to protocol instance block
1107  *      uvp     pointer to the VCCB for the affected connection
1108  *      msg     pointer to a UNISIG message structure
1109  *
1110  * Returns:
1111  *      0       success
1112  *      errno   error encountered
1113  *
1114  */
1115 static int
1116 unisig_vc_act11(struct unisig *usp, struct unisig_vccb *uvp,
1117                 struct unisig_msg *msg)
1118 {
1119         int                     rc, cause;
1120
1121         /*
1122          * Send generic cause code if one is not already set
1123          */
1124         if (uvp->uv_connvc->cvc_attr.cause.tag == T_ATM_PRESENT)
1125                 cause = T_ATM_ABSENT;
1126         else
1127                 cause = T_ATM_CAUSE_CALL_REJECTED;
1128
1129         /*
1130          * Send a RELEASE COMPLETE message
1131          */
1132         rc = unisig_send_release_complete(usp, uvp, msg, cause);
1133
1134         /*
1135          * Clear the call VCCB
1136          */
1137         uvp->uv_sstate = UNI_FREE;
1138         uvp->uv_ustate = VCCU_CLOSED;
1139
1140         /*
1141          * Mark the time
1142          */
1143         uvp->uv_tstamp = time_second;
1144
1145         return(rc);
1146 }
1147
1148
1149 /*
1150  * VC state machine action 12
1151  * Release or abort routine called
1152  *
1153  * Send RELEASE, start timer T308, go to UNI_RELEASE_REQUEST state
1154  *
1155  * Arguments:
1156  *      usp     pointer to protocol instance block
1157  *      uvp     pointer to the VCCB for the affected connection
1158  *      msg     pointer to a UNISIG message structure
1159  *
1160  * Returns:
1161  *      0       success
1162  *      errno   error encountered
1163  *
1164  */
1165 static int
1166 unisig_vc_act12(struct unisig *usp, struct unisig_vccb *uvp,
1167                 struct unisig_msg *msg)
1168 {
1169         int                     rc;
1170
1171         /*
1172          * Clear any running timer
1173          */
1174         UNISIG_VC_CANCEL((struct vccb *) uvp);
1175
1176         /*
1177          * Send the RELEASE message
1178          */
1179         rc = unisig_vc_clear_call(usp, uvp, NULL, T_ATM_ABSENT);
1180
1181         return(rc);
1182 }
1183
1184
1185 /*
1186  * VC state machine action 13
1187  * RELEASE COMPLETE received
1188  *
1189  * Clear the call
1190  *
1191  * Arguments:
1192  *      usp     pointer to protocol instance block
1193  *      uvp     pointer to the VCCB for the affected connection
1194  *      msg     pointer to a UNISIG message structure
1195  *
1196  * Returns:
1197  *      0       success
1198  *      errno   error encountered
1199  *
1200  */
1201 static int
1202 unisig_vc_act13(struct unisig *usp, struct unisig_vccb *uvp,
1203                 struct unisig_msg *msg)
1204 {
1205         /*
1206          * Clear any running timer
1207          */
1208         UNISIG_VC_CANCEL((struct vccb *) uvp);
1209
1210         /*
1211          * Set the state
1212          */
1213         uvp->uv_sstate = UNI_FREE;
1214         if (uvp->uv_ustate != VCCU_ABORT)
1215                 uvp->uv_ustate = VCCU_CLOSED;
1216
1217         /*
1218          * Mark the time
1219          */
1220         uvp->uv_tstamp = time_second;
1221
1222         /*
1223          * Notify the user that the call is now closed
1224          */
1225         if (msg->msg_ie_caus != NULL)
1226                 unisig_cause_attr_from_ie(&uvp->uv_connvc->cvc_attr,
1227                         msg->msg_ie_caus);
1228         atm_cm_cleared(uvp->uv_connvc);
1229
1230         return(0);
1231 }
1232
1233
1234 /*
1235  * VC state machine action 14
1236  * Timer expired while waiting for RELEASE COMPLETE
1237  *
1238  * If this is the second expiration, just clear the call.  Otherwise,
1239  * retransmit the RELEASE message and restart timer T308.
1240  *
1241  * Arguments:
1242  *      usp     pointer to protocol instance block
1243  *      uvp     pointer to the VCCB for the affected connection
1244  *      msg     pointer to a UNISIG message structure
1245  *
1246  * Returns:
1247  *      0       success
1248  *      errno   error encountered
1249  *
1250  */
1251 static int
1252 unisig_vc_act14(struct unisig *usp, struct unisig_vccb *uvp,
1253                 struct unisig_msg *msg)
1254 {
1255         int                     rc;
1256
1257         /*
1258          * Check the retry count
1259          */
1260         if (uvp->uv_retry) {
1261                 /*
1262                  * Clear the connection
1263                  */
1264                 rc = unisig_clear_vcc(usp, uvp,
1265                                 T_ATM_CAUSE_NORMAL_CALL_CLEARING);
1266         } else {
1267                 /*
1268                  * Increment the retry count
1269                  */
1270                 uvp->uv_retry++;
1271
1272                 /*
1273                  * Resend the RELEASE message
1274                  */
1275                 rc = unisig_send_release(usp, uvp, NULL, T_ATM_ABSENT);
1276                 if (rc)
1277                         return(rc);
1278
1279                 /*
1280                  * Restart timer T308
1281                  */
1282                 UNISIG_VC_TIMER((struct vccb *) uvp, UNI_T308);
1283         }
1284
1285         return(0);
1286 }
1287
1288
1289 /*
1290  * VC state machine action 15
1291  * RELEASE received in UNI_ACTIVE state
1292  *
1293  * Send RELEASE COMPLETE, go to UNI_FREE, notify the user
1294  *
1295  * Arguments:
1296  *      usp     pointer to protocol instance block
1297  *      uvp     pointer to the VCCB for the affected connection
1298  *      msg     pointer to a UNISIG message structure
1299  *
1300  * Returns:
1301  *      0       success
1302  *      errno   error encountered
1303  *
1304  */
1305 static int
1306 unisig_vc_act15(struct unisig *usp, struct unisig_vccb *uvp,
1307                 struct unisig_msg *msg)
1308 {
1309         int                     cause, rc;
1310         struct ie_generic       *iep;
1311
1312         /*
1313          * Clear any running timer
1314          */
1315         UNISIG_VC_CANCEL((struct vccb *) uvp);
1316
1317         /*
1318          * If there was no Cause IE, flag an error
1319          */
1320         if (!msg->msg_ie_caus) {
1321                 cause = UNI_IE_CAUS_MISSING;
1322                 for (iep=msg->msg_ie_err; iep; iep=iep->ie_next) {
1323                         if (iep->ie_ident == UNI_IE_CAUS &&
1324                                         iep->ie_err_cause ==
1325                                         UNI_IE_CAUS_IECONTENT) {
1326                                 cause = UNI_IE_CAUS_IECONTENT;
1327                         }
1328                 }
1329                 if (cause == UNI_IE_CAUS_MISSING) {
1330                         iep = (struct ie_generic *)atm_allocate(
1331                                         &unisig_iepool);
1332                         if (!iep)
1333                                 return(ENOMEM);
1334                         iep->ie_ident = UNI_IE_CNID;
1335                         iep->ie_err_cause = UNI_IE_CAUS_MISSING;
1336                         MSG_IE_ADD(msg, iep, UNI_MSG_IE_ERR);
1337                 }
1338         } else {
1339                 cause = UNI_IE_CAUS_NORM_UNSP;
1340         }
1341
1342         /*
1343          * Send a RELEASE COMPLETE message
1344          */
1345         rc = unisig_send_release_complete(usp, uvp, msg, cause);
1346
1347         /*
1348          * Set the state
1349          */
1350         uvp->uv_sstate = UNI_FREE;
1351         uvp->uv_ustate = VCCU_CLOSED;
1352
1353         /*
1354          * Mark the time
1355          */
1356         uvp->uv_tstamp = time_second;
1357
1358         /*
1359          * Notify the user that the call is cleared
1360          */
1361         if (msg->msg_ie_caus != NULL)
1362                 unisig_cause_attr_from_ie(&uvp->uv_connvc->cvc_attr,
1363                         msg->msg_ie_caus);
1364         else
1365                 unisig_cause_attr_from_user(&uvp->uv_connvc->cvc_attr,
1366                         T_ATM_CAUSE_UNSPECIFIED_NORMAL);
1367         atm_cm_cleared(uvp->uv_connvc);
1368
1369         return(rc);
1370 }
1371
1372
1373 /*
1374  * VC state machine action 16
1375  * RELEASE received in UNI_RELEASE_REQUEST state
1376  *
1377  * Clear the call
1378  *
1379  * Arguments:
1380  *      usp     pointer to protocol instance block
1381  *      uvp     pointer to the VCCB for the affected connection
1382  *      msg     pointer to a UNISIG message structure
1383  *
1384  * Returns:
1385  *      0       success
1386  *      errno   error encountered
1387  *
1388  */
1389 static int
1390 unisig_vc_act16(struct unisig *usp, struct unisig_vccb *uvp,
1391                 struct unisig_msg *msg)
1392 {
1393         int     rc;
1394
1395         /*
1396          * Clear any running timer
1397          */
1398         UNISIG_VC_CANCEL((struct vccb *) uvp);
1399
1400         /*
1401          * Clear the VCCB
1402          */
1403         rc = unisig_clear_vcc(usp, uvp, T_ATM_ABSENT);
1404
1405         return(rc);
1406 }
1407
1408
1409 /*
1410  * VC state machine action 17
1411  * Protocol error
1412  *
1413  * Send a STATUS message with cause 101, "message not compatible with
1414  * call state"
1415  *
1416  * Arguments:
1417  *      usp     pointer to protocol instance block
1418  *      uvp     pointer to the VCCB for the affected connection
1419  *      msg     pointer to a UNISIG message structure
1420  *
1421  * Returns:
1422  *      0       success
1423  *      errno   error encountered
1424  *
1425  */
1426 static int
1427 unisig_vc_act17(struct unisig *usp, struct unisig_vccb *uvp,
1428                 struct unisig_msg *msg)
1429 {
1430         int                     rc;
1431
1432         ATM_DEBUG3("unisig_vc_perror: usp=%p, uvp=%p, msg=%p\n",
1433                         usp, uvp, msg);
1434
1435         /*
1436          * Clear any running timer
1437          */
1438         UNISIG_VC_CANCEL((struct vccb *) uvp);
1439
1440         /*
1441          * Send a STATUS message
1442          */
1443         rc = unisig_send_status(usp, uvp, msg, UNI_IE_CAUS_STATE);
1444
1445         return(rc ? rc : EINVAL);
1446 }
1447
1448
1449 /*
1450  * VC state machine action 18
1451  * Signalling AAL connection has been lost
1452  *
1453  * Start timer T309.  If the timer expires before the SAAL connection
1454  * comes back, the VCC will be cleared.
1455  *
1456  * Arguments:
1457  *      usp     pointer to protocol instance block
1458  *      uvp     pointer to the VCCB for the affected connection
1459  *      msg     pointer to a UNISIG message structure
1460  *
1461  * Returns:
1462  *      0       success
1463  *      errno   error encountered
1464  *
1465  */
1466 static int
1467 unisig_vc_act18(struct unisig *usp, struct unisig_vccb *uvp,
1468                 struct unisig_msg *msg)
1469 {
1470         /*
1471          * Clear any running timer
1472          */
1473         UNISIG_VC_CANCEL((struct vccb *) uvp);
1474
1475         /*
1476          * Start timer T309
1477          */
1478         UNISIG_VC_TIMER((struct vccb *) uvp, UNI_T309);
1479
1480         /*
1481          * Set new state
1482          */
1483         uvp->uv_sstate = UNI_SSCF_RECOV;
1484
1485         return(0);
1486 }
1487
1488
1489 /*
1490  * VC state machine action 19
1491  * Ignore the event
1492  *
1493  * Arguments:
1494  *      usp     pointer to protocol instance block
1495  *      uvp     pointer to the VCCB for the affected connection
1496  *      msg     pointer to a UNISIG message structure
1497  *
1498  * Returns:
1499  *      0       success
1500  *      errno   error encountered
1501  *
1502  */
1503 static int
1504 unisig_vc_act19(struct unisig *usp, struct unisig_vccb *uvp,
1505                 struct unisig_msg *msg)
1506 {
1507         return(0);
1508 }
1509
1510
1511 /*
1512  * VC state machine action 20
1513  * SSCF establish indication in UNI_SSCF_RECOV state -- signalling
1514  * AAL has come up after an outage
1515  *
1516  * Send STATUS ENQ to make sure we're in compatible state with other end
1517  *
1518  * Arguments:
1519  *      usp     pointer to protocol instance block
1520  *      uvp     pointer to the VCCB for the affected connection
1521  *      msg     pointer to a UNISIG message structure
1522  *
1523  * Returns:
1524  *      0       success
1525  *      errno   error encountered
1526  *
1527  */
1528 static int
1529 unisig_vc_act20(struct unisig *usp, struct unisig_vccb *uvp,
1530                 struct unisig_msg *msg)
1531 {
1532         int                     rc;
1533         struct unisig_msg       *stat_msg;
1534
1535         /*
1536          * Clear any running timer
1537          */
1538         UNISIG_VC_CANCEL((struct vccb *) uvp);
1539
1540         /*
1541          * Get memory for a STATUS ENQUIRY message
1542          */
1543         stat_msg = (struct unisig_msg *)atm_allocate(&unisig_msgpool);
1544         if (stat_msg == NULL)
1545                 return(ENOMEM);
1546
1547         /*
1548          * Fill out the message
1549          */
1550         stat_msg->msg_call_ref = uvp->uv_call_ref;
1551         stat_msg->msg_type = UNI_MSG_SENQ;
1552         stat_msg->msg_type_flag = 0;
1553         stat_msg->msg_type_action = 0;
1554
1555         /*
1556          * Send the STATUS ENQUIRY message
1557          */
1558         rc = unisig_send_msg(usp, stat_msg);
1559         unisig_free_msg(stat_msg);
1560
1561         /*
1562          * Return to active state
1563          */
1564         uvp->uv_sstate = UNI_ACTIVE;
1565
1566         return(rc);
1567 }
1568
1569
1570 /*
1571  * VC state machine action 21
1572  * STATUS received
1573  *
1574  * Arguments:
1575  *      usp     pointer to protocol instance block
1576  *      uvp     pointer to the VCCB for the affected connection (may
1577  *              be NULL)
1578  *      msg     pointer to a UNISIG message structure
1579  *
1580  * Returns:
1581  *      0       success
1582  *      errno   error encountered
1583  *
1584  */
1585 static int
1586 unisig_vc_act21(struct unisig *usp, struct unisig_vccb *uvp,
1587                 struct unisig_msg *msg)
1588 {
1589         int     cause, rc;
1590
1591         /*
1592          * Ignore a STATUS message with the global call reference
1593          */
1594         if (GLOBAL_CREF(msg->msg_call_ref)) {
1595                 return(0);
1596         }
1597
1598         /*
1599          * If the network thinks we're in NULL state, clear the VCC
1600          */
1601         if (msg->msg_ie_clst->ie_clst_state == UNI_NULL) {
1602                 if (uvp) {
1603                         unisig_clear_vcc(usp, uvp,
1604                                         T_ATM_CAUSE_DESTINATION_OUT_OF_ORDER);
1605                 }
1606                 return(0);
1607         }
1608
1609         /*
1610          * If we are in NULL state, send a RELEASE COMPLETE
1611          */
1612         if (!uvp || (uvp->uv_sstate == UNI_FREE) ||
1613                         (uvp->uv_sstate == UNI_NULL)) {
1614                 rc = unisig_send_release_complete(usp,
1615                                 uvp, msg, UNI_IE_CAUS_STATE);
1616                 return(rc);
1617         }
1618
1619         /*
1620          * If the reported state doesn't match our state, close the VCC
1621          * unless we're in UNI_RELEASE_REQUEST or UNI_RELEASE_IND
1622          */
1623         if (msg->msg_ie_clst->ie_clst_state != uvp->uv_sstate) {
1624                 if (uvp->uv_sstate == UNI_RELEASE_REQUEST ||
1625                                 uvp->uv_sstate == UNI_RELEASE_IND) {
1626                         return(0);
1627                 }
1628                 rc = unisig_clear_vcc(usp, uvp,
1629                         T_ATM_CAUSE_MESSAGE_INCOMPATIBLE_WITH_CALL_STATE);
1630         }
1631
1632         /*
1633          * States match, check for an error on one of our messages
1634          */
1635         cause = msg->msg_ie_caus->ie_caus_cause;
1636         if (cause == UNI_IE_CAUS_MISSING ||
1637                         cause == UNI_IE_CAUS_MTEXIST ||
1638                         cause == UNI_IE_CAUS_IEEXIST ||
1639                         cause == UNI_IE_CAUS_IECONTENT ||
1640                         cause == UNI_IE_CAUS_STATE) {
1641                 ATM_DEBUG2("unisig_vc_act21: error %d on message 0x%x\n",
1642                                 cause,
1643                                 msg->msg_ie_caus->ie_caus_diagnostic[0]);
1644                 if (uvp) {
1645                         unisig_clear_vcc(usp, uvp, cause);
1646                 }
1647         }
1648
1649         return(0);
1650 }
1651
1652
1653 /*
1654  * VC state machine action 22
1655  * Received STATUS ENQ
1656  *
1657  * Send STATUS with cause 30 "response to STATUS ENQUIRY" and
1658  * current state
1659  *
1660  * Arguments:
1661  *      usp     pointer to protocol instance block
1662  *      uvp     pointer to the VCCB for the affected connection (may
1663  *              be NULL)
1664  *      msg     pointer to a UNISIG message structure
1665  *
1666  * Returns:
1667  *      0       success
1668  *      errno   error encountered
1669  *
1670  */
1671 static int
1672 unisig_vc_act22(struct unisig *usp, struct unisig_vccb *uvp,
1673                 struct unisig_msg *msg)
1674 {
1675         int                     rc;
1676         struct unisig_msg       *status;
1677         struct ie_generic       *callst_ie, *cause_ie;
1678
1679         ATM_DEBUG3("unisig_vc_perror: usp=%p, uvp=%p, msg=%p\n",
1680                         usp, uvp, msg);
1681
1682         /*
1683          * Get memory for a STATUS message
1684          */
1685         status = (struct unisig_msg *) atm_allocate(&unisig_msgpool);
1686         if (status == NULL)
1687                 return(ENOMEM);
1688         callst_ie = (struct ie_generic *) atm_allocate(&unisig_iepool);
1689         if (callst_ie == NULL) {
1690                 atm_free(status);
1691                 return(ENOMEM);
1692         }
1693         cause_ie = (struct ie_generic *) atm_allocate(&unisig_iepool);
1694         if (cause_ie == NULL) {
1695                 atm_free(status);
1696                 atm_free(callst_ie);
1697                 return(ENOMEM);
1698         }
1699
1700         /*
1701          * Fill out the response
1702          */
1703         if (uvp) {
1704                 status->msg_call_ref = uvp->uv_call_ref;
1705         } else if (msg) {
1706                 if (msg->msg_call_ref & UNI_MSG_CALL_REF_RMT)
1707                         status->msg_call_ref = msg->msg_call_ref &
1708                                         UNI_MSG_CALL_REF_MASK;
1709                 else
1710                         status->msg_call_ref = msg->msg_call_ref |
1711                                         UNI_MSG_CALL_REF_RMT;
1712         } else {
1713                 status->msg_call_ref = UNI_MSG_CALL_REF_GLOBAL;
1714         }
1715         status->msg_type = UNI_MSG_STAT;
1716         status->msg_type_flag = 0;
1717         status->msg_type_action = 0;
1718         status->msg_ie_clst = callst_ie;
1719         status->msg_ie_caus = cause_ie;
1720
1721         /*
1722          * Fill out the call state IE
1723          */
1724         callst_ie->ie_ident = UNI_IE_CLST;
1725         callst_ie->ie_coding = 0;
1726         callst_ie->ie_flag = 0;
1727         callst_ie->ie_action = 0;
1728         if (uvp) {
1729                 switch(uvp->uv_sstate) {
1730                 case UNI_FREE:
1731                         callst_ie->ie_clst_state = UNI_NULL;
1732                         break;
1733                 default:
1734                         callst_ie->ie_clst_state = uvp->uv_sstate;
1735                 }
1736         } else {
1737                 callst_ie->ie_clst_state = UNI_NULL;
1738         }
1739
1740         /*
1741          * Fill out the cause IE
1742          */
1743         cause_ie->ie_ident = UNI_IE_CAUS;
1744         cause_ie->ie_coding = 0;
1745         cause_ie->ie_flag = 0;
1746         cause_ie->ie_action = 0;
1747         cause_ie->ie_caus_loc = UNI_IE_CAUS_LOC_USER;
1748         cause_ie->ie_caus_cause = UNI_IE_CAUS_SENQ;
1749
1750         /*
1751          * Send the STATUS message
1752          */
1753         rc = unisig_send_msg(usp, status);
1754         unisig_free_msg(status);
1755         return(rc);
1756 }
1757
1758
1759 /*
1760  * VC state machine action 23
1761  * Received ADD PARTY
1762  *
1763  * We don't support multipoint connections, so send an ADD PARTY REJECT
1764  *
1765  * Arguments:
1766  *      usp     pointer to protocol instance block
1767  *      uvp     pointer to the VCCB for the affected connection
1768  *      msg     pointer to a UNISIG message structure
1769  *
1770  * Returns:
1771  *      0       success
1772  *      errno   error encountered
1773  *
1774  */
1775 static int
1776 unisig_vc_act23(struct unisig *usp, struct unisig_vccb *uvp,
1777                 struct unisig_msg *msg)
1778 {
1779         int                     rc;
1780         struct unisig_msg       *apr_msg;
1781
1782         /*
1783          * Get memory for the ADD PARTY REJECT message
1784          */
1785         apr_msg = (struct unisig_msg *) atm_allocate(&unisig_msgpool);
1786         if (apr_msg == NULL)
1787                 return(ENOMEM);
1788
1789         /*
1790          * Fill out the message
1791          */
1792         if (msg->msg_call_ref & UNI_MSG_CALL_REF_RMT)
1793                 apr_msg->msg_call_ref = msg->msg_call_ref &
1794                                 UNI_MSG_CALL_REF_MASK;
1795         else
1796                 apr_msg->msg_call_ref = msg->msg_call_ref |
1797                                 UNI_MSG_CALL_REF_RMT;
1798         apr_msg->msg_type = UNI_MSG_ADPR;
1799         apr_msg->msg_type_flag = 0;
1800         apr_msg->msg_type_action = 0;
1801
1802         /*
1803          * Use the endpoint reference IE from the received message
1804          */
1805         apr_msg->msg_ie_eprf = msg->msg_ie_eprf;
1806
1807         /*
1808          * Send the ADD PARTY REJECT message
1809          */
1810         rc = unisig_send_msg(usp, apr_msg);
1811         apr_msg->msg_ie_eprf = NULL;
1812         unisig_free_msg(apr_msg);
1813
1814         return(rc);
1815 }
1816
1817
1818 /*
1819  * VC state machine action 24
1820  * User error
1821  *
1822  * Return EALREADY
1823  *
1824  * Arguments:
1825  *      usp     pointer to protocol instance block
1826  *      uvp     pointer to the VCCB for the affected connection
1827  *      msg     pointer to a UNISIG message structure
1828  *
1829  * Returns:
1830  *      0       success
1831  *      errno   error encountered
1832  *
1833  */
1834 static int
1835 unisig_vc_act24(struct unisig *usp, struct unisig_vccb *uvp,
1836                 struct unisig_msg *msg)
1837 {
1838         return(EALREADY);
1839 }
1840
1841
1842 /*
1843  * VC state machine action 25
1844  * User error
1845  *
1846  * Return EINVAL
1847  *
1848  * Arguments:
1849  *      usp     pointer to protocol instance block
1850  *      uvp     pointer to the VCCB for the affected connection
1851  *      msg     pointer to a UNISIG message structure
1852  *
1853  * Returns:
1854  *      0       success
1855  *      errno   error encountered
1856  *
1857  */
1858 static int
1859 unisig_vc_act25(struct unisig *usp, struct unisig_vccb *uvp,
1860                 struct unisig_msg *msg)
1861 {
1862         return(EINVAL);
1863 }
1864
1865
1866 /*
1867  * VC state machine action 26
1868  * PVC abort
1869  *
1870  * The abort handler was called to abort a PVC.  Clear the VCCB and
1871  * notify the user.
1872  *
1873  * Arguments:
1874  *      usp     pointer to protocol instance block
1875  *      uvp     pointer to the VCCB for the affected connection
1876  *      msg     pointer to a UNISIG message structure
1877  *
1878  * Returns:
1879  *      0       success
1880  *      errno   error encountered
1881  *
1882  */
1883 static int
1884 unisig_vc_act26(struct unisig *usp, struct unisig_vccb *uvp,
1885                 struct unisig_msg *msg)
1886 {
1887         int     rc;
1888
1889         /*
1890          * Clear any running timer
1891          */
1892         UNISIG_VC_CANCEL((struct vccb *) uvp);
1893
1894         /*
1895          * Close the VCCB
1896          */
1897         rc = unisig_close_vcc(usp, uvp);
1898         if (rc)
1899                 return(rc);
1900
1901         /*
1902          * Notify the user
1903          */
1904         if (uvp->uv_connvc->cvc_attr.cause.tag != T_ATM_PRESENT)
1905                 unisig_cause_attr_from_user(&uvp->uv_connvc->cvc_attr,
1906                         T_ATM_CAUSE_NORMAL_CALL_CLEARING);
1907
1908         atm_cm_cleared(uvp->uv_connvc);
1909
1910         return(0);
1911 }
1912
1913
1914 /*
1915  * VC state machine action 27
1916  * Signalling AAL failure
1917  *
1918  * Change PVC state to UNI_PVC_ACT_DOWN.
1919  *
1920  * Arguments:
1921  *      usp     pointer to protocol instance block
1922  *      uvp     pointer to the VCCB for the affected connection
1923  *      msg     pointer to a UNISIG message structure
1924  *
1925  * Returns:
1926  *      0       success
1927  *      errno   error encountered
1928  *
1929  */
1930 static int
1931 unisig_vc_act27(struct unisig *usp, struct unisig_vccb *uvp,
1932                 struct unisig_msg *msg)
1933 {
1934         /*
1935          * Set the state
1936          */
1937         uvp->uv_sstate = UNI_PVC_ACT_DOWN;
1938
1939         /*
1940          * Mark the time
1941          */
1942         uvp->uv_tstamp = time_second;
1943
1944         return(0);
1945 }
1946
1947
1948 /*
1949  * VC state machine action 28
1950  * Signalling AAL established
1951  *
1952  * Set PVC state to UNI_PVC_ACTIVE.
1953  *
1954  * Arguments:
1955  *      usp     pointer to protocol instance block
1956  *      uvp     pointer to the VCCB for the affected connection
1957  *      msg     pointer to a UNISIG message structure
1958  *
1959  * Returns:
1960  *      0       success
1961  *      errno   error encountered
1962  *
1963  */
1964 static int
1965 unisig_vc_act28(struct unisig *usp, struct unisig_vccb *uvp,
1966                 struct unisig_msg *msg)
1967 {
1968         /*
1969          * Set the state
1970          */
1971         uvp->uv_sstate = UNI_PVC_ACTIVE;
1972
1973         /*
1974          * Mark the time
1975          */
1976         uvp->uv_tstamp = time_second;
1977
1978         return(0);
1979 }
1980
1981
1982 /*
1983  * VC state machine action 29
1984  * Protocol error
1985  *
1986  * Send a RELEASE COMPLETE message with cause 81, "invalid call
1987  * reference value"
1988  *
1989  * Arguments:
1990  *      usp     pointer to protocol instance block
1991  *      uvp     pointer to the VCCB for the affected connection (may
1992  *              be NULL)
1993  *      msg     pointer to a UNISIG message structure
1994  *
1995  * Returns:
1996  *      0       success
1997  *      errno   error encountered
1998  *
1999  */
2000 static int
2001 unisig_vc_act29(struct unisig *usp, struct unisig_vccb *uvp,
2002                 struct unisig_msg *msg)
2003 {
2004         int                     rc;
2005
2006         /*
2007          * Send a RELEASE COMPLETE message
2008          */
2009         rc = unisig_send_release_complete(usp, uvp, msg,
2010                         UNI_IE_CAUS_CREF);
2011
2012         return(rc);
2013 }
2014
2015
2016 /*
2017  * VC state machine action 30
2018  * Release routine called while SSCF session down, or SSCF session
2019  * reset or lost while in UNI_CALL_PRESENT
2020  *
2021  * Go to UNI_FREE state
2022  *
2023  * Arguments:
2024  *      usp     pointer to protocol instance block
2025  *      uvp     pointer to the VCCB for the affected connection
2026  *      msg     pointer to a UNISIG message structure
2027  *
2028  * Returns:
2029  *      0       success
2030  *      errno   error encountered
2031  *
2032  */
2033 static int
2034 unisig_vc_act30(struct unisig *usp, struct unisig_vccb *uvp,
2035                 struct unisig_msg *msg)
2036 {
2037         /*
2038          * Clear any running timer
2039          */
2040         UNISIG_VC_CANCEL((struct vccb *) uvp);
2041
2042         /*
2043          * Clear the call state
2044          */
2045         uvp->uv_sstate = UNI_FREE;
2046         uvp->uv_ustate = VCCU_CLOSED;
2047
2048         /*
2049          * Mark the time
2050          */
2051         uvp->uv_tstamp = time_second;
2052
2053         return(0);
2054 }
2055
2056
2057 /*
2058  * VC state machine action 31
2059  * Accept handler called in UNI_FREE state.
2060  *
2061  * The call was in UNI_CALL_PRESENT state when it was closed because
2062  * of an SSCF failure.  Return an error indication.  The accept
2063  * handler will free the VCCB and return the proper code to the
2064  * caller.
2065  *
2066  * Arguments:
2067  *      usp     pointer to protocol instance block
2068  *      uvp     pointer to the VCCB for the affected connection
2069  *      msg     pointer to a UNISIG message structure
2070  *
2071  * Returns:
2072  *      0       success
2073  *      errno   error encountered
2074  *
2075  */
2076 static int
2077 unisig_vc_act31(struct unisig *usp, struct unisig_vccb *uvp,
2078                 struct unisig_msg *msg)
2079 {
2080         return(ENETDOWN);
2081 }
2082
2083
2084 /*
2085  * Initiate clearing a call by sending a RELEASE message.
2086  *
2087  * Arguments:
2088  *      usp     pointer to protocol instance block
2089  *      uvp     pointer to the VCCB for the affected connection
2090  *      msg     pointer to UNI signalling message that the RELEASE
2091  *              responds to (may be NULL)
2092  *      cause   the reason for clearing the call;  a value of
2093  *              T_ATM_ABSENT indicates that the cause code is
2094  *              in the VCC's ATM attributes block
2095  *
2096  * Returns:
2097  *      0       success
2098  *      errno   error encountered
2099  *
2100  */
2101 static int
2102 unisig_vc_clear_call(struct unisig *usp, struct unisig_vccb *uvp,
2103                      struct unisig_msg *msg, int cause)
2104 {
2105         int                     rc;
2106
2107         /*
2108          * Clear the retry count
2109          */
2110         uvp->uv_retry = 0;
2111
2112         /*
2113          * Make sure the ATM attributes block has a valid cause code,
2114          * if needed
2115          */
2116         if (cause == T_ATM_ABSENT &&
2117                         uvp->uv_connvc->cvc_attr.cause.tag !=
2118                         T_ATM_PRESENT) {
2119                 uvp->uv_connvc->cvc_attr.cause.tag = T_ATM_PRESENT;
2120                 uvp->uv_connvc->cvc_attr.cause.v.coding_standard =
2121                                 T_ATM_ITU_CODING;
2122                 uvp->uv_connvc->cvc_attr.cause.v.location =
2123                                 T_ATM_LOC_USER;
2124                 uvp->uv_connvc->cvc_attr.cause.v.cause_value =
2125                         usp->us_proto == ATM_SIG_UNI30 ? 
2126                                 T_ATM_CAUSE_UNSPECIFIED_NORMAL :
2127                                 T_ATM_CAUSE_NORMAL_CALL_CLEARING;
2128         }
2129
2130         /*
2131          * Send a RELEASE message
2132          */
2133         rc = unisig_send_release(usp, uvp, msg, cause);
2134         if (rc)
2135                 return(rc);
2136
2137         /*
2138          * Start timer T308
2139          */
2140         UNISIG_VC_TIMER((struct vccb *) uvp, UNI_T308);
2141
2142         /*
2143          * Set the VCCB state
2144          */
2145         uvp->uv_sstate = UNI_RELEASE_REQUEST;
2146         if (uvp->uv_ustate != VCCU_ABORT)
2147                 uvp->uv_ustate = VCCU_CLOSED;
2148
2149         /*
2150          * Mark the time
2151          */
2152         uvp->uv_tstamp = time_second;
2153
2154         return(0);
2155 }