kernel: Sync ACPICA with Intel's version 20140424.
[dragonfly.git] / sys / netproto / atm / spans / spans_msg.c
1 /*
2  *
3  * ===================================
4  * HARP  |  Host ATM Research Platform
5  * ===================================
6  *
7  *
8  * This Host ATM Research Platform ("HARP") file (the "Software") is
9  * made available by Network Computing Services, Inc. ("NetworkCS")
10  * "AS IS".  NetworkCS does not provide maintenance, improvements or
11  * support of any kind.
12  *
13  * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14  * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15  * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16  * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17  * In no event shall NetworkCS be responsible for any damages, including
18  * but not limited to consequential damages, arising from or relating to
19  * any use of the Software or related support.
20  *
21  * Copyright 1994-1998 Network Computing Services, Inc.
22  *
23  * Copies of this Software may be made, however, the above copyright
24  * notice must be reproduced on all copies.
25  *
26  *      @(#) $FreeBSD: src/sys/netatm/spans/spans_msg.c,v 1.5 1999/08/28 00:48:50 peter Exp $
27  *      @(#) $DragonFly: src/sys/netproto/atm/spans/spans_msg.c,v 1.7 2006/12/22 23:57:54 swildner Exp $
28  */
29
30 /*
31  * SPANS Signalling Manager
32  * ---------------------------
33  *
34  * SPANS signalling message processing.
35  *
36  */
37
38 #include <netproto/atm/kern_include.h>
39
40 #include "spans_xdr.h"
41 #include "spans_var.h"
42
43 /*
44  * External functions
45  */
46 void            xdrmbuf_init (XDR *, KBuffer *, enum xdr_op);
47
48 /*
49  * Local functions
50  */
51 static void     spans_host_link (struct spans *, long);
52 static void     spans_status_ind (struct spans *, spans_msg *);
53 static void     spans_status_rsp (struct spans *, spans_msg *);
54 static void     spans_open_req (struct spans *, spans_msg *);
55 static void     spans_open_rsp (struct spans *, spans_msg *);
56 static void     spans_close_req (struct spans *, spans_msg *);
57 static void     spans_close_rsp (struct spans *, spans_msg *);
58 static void     spans_multi_req (struct spans *, spans_msg *);
59 static void     spans_add_req (struct spans *, spans_msg *);
60 static void     spans_join_req (struct spans *, spans_msg *);
61 static void     spans_leave_req (struct spans *, spans_msg *);
62 static void     spans_vcir_ind (struct spans *, spans_msg *);
63 static void     spans_query_req (struct spans *, spans_msg *);
64
65
66 /*
67  * Called to set status when a status message comes in from a host
68  * connected back-to-back with us.  Check the epoch and, if it has
69  * changed, set the appropriate state and save updated state
70  * information.
71  *
72  * Arguments:
73  *      spp             pointer to SPANS protocol instance block
74  *      host_epoch      epoch of host at far end of link
75  *
76  * Returns:
77  *      0       message sent OK
78  *      errno   error encountered
79  *
80  */
81 static void
82 spans_host_link(struct spans *spp, long host_epoch)
83 {
84         struct atm_pif  *pip = spp->sp_pif;
85
86         /*
87          * There's a host at the other end of the link.  If its
88          * epoch has changed, clean up our state and save the
89          * new information.
90          */
91         if (spp->sp_s_epoch != host_epoch) {
92                 spp->sp_s_epoch = host_epoch;
93                 spans_switch_reset(spp, SPANS_UNI_UP);
94                 spp->sp_addr.address_format = T_ATM_SPANS_ADDR;
95                 spp->sp_addr.address_length = sizeof(spans_addr);
96                 KM_COPY(&pip->pif_macaddr.ma_data[2],
97                                 &spp->sp_addr.address[4],
98                                 4);
99                 log(LOG_INFO,
100                 "spans: using SPANS address of %s on interface %s%d\n",
101                         spans_addr_print((spans_addr *)spp->sp_addr.address),
102                         pip->pif_name,
103                         pip->pif_unit);
104         }
105 }
106
107 /*
108  * Send a SPANS signalling message
109  *
110  * Called to send a SPANS message.  This routine gets a buffer, performs
111  * XDR processing, and hands the message to the AAL for transmission.
112  *
113  * Arguments:
114  *      spp     pointer to SPANS protocol instance block
115  *      msg     pointer to status message
116  *
117  * Returns:
118  *      0       message sent OK
119  *      errno   error encountered
120  *
121  */
122 int
123 spans_send_msg(struct spans *spp, spans_msg *msg)
124 {
125         int             err = 0;
126         KBuffer         *m;
127         XDR             xdrs;
128
129 #ifdef NOTDEF
130         ATM_DEBUG2("spans_send_msg: msg=%p, type=%d\n", msg,
131                         msg->sm_type);
132         if (msg->sm_type != SPANS_STAT_REQ &&
133                         msg->sm_type != SPANS_STAT_IND &&
134                         msg->sm_type != SPANS_STAT_RSP) {
135                 kprintf("spans_send_msg: sending ");
136                 spans_print_msg(msg);
137         }
138 #endif
139
140         /*
141          * If the signalling channel has been closed, don't do anything
142          */
143         if (!spp->sp_conn)
144                 return(ECONNABORTED);
145
146         /*
147          * Get a buffer
148          */
149         KB_ALLOCPKT(m, sizeof(spans_msg), KB_F_NOWAIT, KB_T_DATA);
150         if (m == NULL) {
151                 /* No buffer available */
152                 return(ENOBUFS);
153         }
154
155         /*
156          * Convert message to network order
157          */
158         KB_LEN(m) = KB_BFRLEN(m);
159         xdrmbuf_init(&xdrs, m, XDR_ENCODE);
160         if (!xdr_spans_msg(&xdrs, msg)) {
161                 log(LOG_ERR, "spans_send_msg: XDR encode failed\n");
162                 KB_LEN(m) = XDR_GETPOS(&xdrs);
163                 spans_dump_buffer(m);
164                 KB_FREEALL(m);
165                 return(EIO);
166         }
167         KB_LEN(m) = XDR_GETPOS(&xdrs);
168
169         /*
170          * Send the message
171          */
172         err = atm_cm_cpcs_data(spp->sp_conn, m);
173         if (err)
174                 KB_FREEALL(m);
175
176         return(err);
177 }
178
179
180 /*
181  * Send an open request
182  *
183  * Build and send an open request.
184  *
185  * Arguments:
186  *      spp     pointer to SPANS protocol instance block
187  *      svp     pointer to VCCB for which the request is being sent
188  *
189  * Returns:
190  *      none
191  *
192  */
193 int
194 spans_send_open_req(struct spans *spp, struct spans_vccb *svp)
195 {
196         spans_msg       *req;
197         int             err = 0;
198
199         ATM_DEBUG1("spans_send_open_req: svp=%p\n", svp);
200
201         /*
202          * Get memory for a request message
203          */
204         req = (spans_msg *)atm_allocate(&spans_msgpool);
205         if (req == NULL) {
206                 err = ENOBUFS;
207                 goto done;
208         }
209
210         /*
211          * Fill in the request
212          */
213         req->sm_vers = SPANS_VERS_1_0;
214         req->sm_type = SPANS_OPEN_REQ;
215         req->sm_open_req.opreq_conn = svp->sv_conn;
216         req->sm_open_req.opreq_aal = svp->sv_spans_aal;
217         req->sm_open_req.opreq_desrsrc = svp->sv_spans_qos;
218         req->sm_open_req.opreq_minrsrc.rsc_peak = 0;
219         req->sm_open_req.opreq_minrsrc.rsc_mean = 0;
220         req->sm_open_req.opreq_minrsrc.rsc_burst = 0;
221         req->sm_open_req.opreq_vpvc.vpf_valid = FALSE;
222
223         /*
224          * Send the request
225          */
226         err = spans_send_msg(spp, req);
227         atm_free(req);
228
229 done:
230         return(err);
231 }
232
233
234 /*
235  * Send an open response
236  *
237  * Build and send a response to an open request or open indication.
238  *
239  * Arguments:
240  *      spp     pointer to SPANS protocol instance block
241  *      svp     pointer to VCCB for which the response is being sent
242  *      result  result code to include in the response
243  *
244  * Returns:
245  *      none
246  *
247  */
248 int
249 spans_send_open_rsp(struct spans *spp, struct spans_vccb *svp,
250                     spans_result result)
251 {
252         spans_msg       *rsp;
253         int             rc;
254
255         ATM_DEBUG2("spans_send_open_rsp: svp=%p, result=%d\n", svp,
256                         result);
257
258         /*
259          * Get memory for a response message
260          */
261         rsp = (spans_msg *)atm_allocate(&spans_msgpool);
262         if (rsp == NULL)
263                 return(ENOBUFS);
264
265         /*
266          * Fill in the response
267          */
268         rsp->sm_vers = SPANS_VERS_1_0;
269         rsp->sm_type = SPANS_OPEN_RSP;
270         rsp->sm_open_rsp.oprsp_conn = svp->sv_conn;
271         rsp->sm_open_rsp.oprsp_result = result;
272         rsp->sm_open_rsp.oprsp_rsrc = svp->sv_spans_qos;
273         rsp->sm_open_rsp.oprsp_vpvc =
274                         SPANS_PACK_VPIVCI(svp->sv_vpi, svp->sv_vci);
275
276         /*
277          * Send the response
278          */
279         rc = spans_send_msg(spp, rsp);
280         atm_free(rsp);
281
282         return(rc);
283 }
284
285
286 /*
287  * Send a close request
288  *
289  * Called to send a close request.
290  *
291  * Arguments:
292  *      spp     pointer to SPANS protocol instance block
293  *      svp     pointer to VCCB for which the close is being sent
294  *
295  * Returns:
296  *      none
297  *
298  */
299 int
300 spans_send_close_req(struct spans *spp, struct spans_vccb *svp)
301 {
302         spans_msg       *req;
303         int             err = 0;
304
305         ATM_DEBUG1("spans_send_close_req: svp=%p\n", svp);
306
307         /*
308          * Get memory for a close request
309          */
310         req = (spans_msg *)atm_allocate(&spans_msgpool);
311         if (req == NULL) {
312                 err = ENOBUFS;
313                 goto done;
314         }
315
316         /*
317          * Fill in the request
318          */
319         req->sm_vers = SPANS_VERS_1_0;
320         if (svp->sv_type & VCC_OUT) {
321                 req->sm_type = SPANS_CLOSE_REQ;
322         } else if (svp->sv_type & VCC_IN) {
323                 req->sm_type = SPANS_RCLOSE_REQ;
324         } else {
325                 err = EINVAL;
326                 ATM_DEBUG1(
327                 "spans_send_close_req: invalid VCCB type 0x%x\n",
328                                 svp->sv_type);
329                 goto done;
330         }
331         req->sm_close_req.clreq_conn = svp->sv_conn;
332
333         /*
334          * Send the close request
335          */
336         err = spans_send_msg(spp, req);
337
338 done:
339         if (req)
340                 atm_free(req);
341
342         return(err);
343 }
344
345
346
347 /*
348  * Process a status indication or status request
349  *
350  * Called when a status indication or status request is received.
351  * Processing will be based on the current SPANS state.
352  *
353  * Arguments:
354  *      spp     pointer to SPANS protocol instance block
355  *      msg     pointer to the status message
356  *
357  * Returns:
358  *      none
359  *
360  */
361 static void
362 spans_status_ind(struct spans *spp, spans_msg *msg)
363 {
364         spans_msg       *rsp_msg;
365         struct atm_pif  *pip = spp->sp_pif;
366
367         /*
368          * Reset the probe count.
369          */
370         spp->sp_probe_ct = 0;
371
372         switch (spp->sp_state) {
373         case SPANS_PROBE:
374                 /*
375                  * Interface just came up, update signalling state
376                  */
377                 spp->sp_state = SPANS_ACTIVE;
378                 break;
379
380         case SPANS_ACTIVE:
381                 break;
382
383         default:
384                 log(LOG_ERR, "spans: received status msg in state %d\n",
385                                 spp->sp_state);
386         }
387
388         /*
389          * Process the message
390          */
391         switch (msg->sm_type) {
392
393         case SPANS_STAT_REQ:
394                 /*
395                  * Handle a request from a host at the other end of
396                  * the link.
397                  */
398                 spans_host_link(spp, msg->sm_stat_req.streq_es_epoch);
399                 break;
400
401         case SPANS_STAT_IND:
402
403                 /*
404                  * There's a switch at the other end of the link.  If
405                  * its epoch has changed, reset the SPANS state and save
406                  * the new information.
407                  */
408                 if (spp->sp_s_epoch !=
409                                 msg->sm_stat_ind.stind_sw_epoch) {
410                         spans_switch_reset(spp, SPANS_UNI_UP);
411                         spp->sp_s_epoch =
412                                 msg->sm_stat_ind.stind_sw_epoch;
413                         spp->sp_addr.address_format = T_ATM_SPANS_ADDR;
414                         spp->sp_addr.address_length =
415                                         sizeof(spans_addr);
416                         spans_addr_copy(&msg->sm_stat_ind.stind_es_addr,
417                                 spp->sp_addr.address);
418                         log(LOG_INFO,
419                 "spans: received SPANS address %s from switch for interface %s%d\n",
420                                         spans_addr_print((spans_addr *)spp->sp_addr.address),
421                                         pip->pif_name,
422                                         pip->pif_unit);
423                 }
424                 break;
425
426         default:
427                 ATM_DEBUG1("spans_status_ind: Invalid message type %d\n",
428                                 msg->sm_type);
429                 return;
430         }
431
432         /*
433          * Respond to the status request or indication with a
434          * status response
435          */
436         rsp_msg = (spans_msg *)atm_allocate(&spans_msgpool);
437         if (rsp_msg == NULL)
438                 return;
439         rsp_msg->sm_vers = SPANS_VERS_1_0;
440         rsp_msg->sm_type = SPANS_STAT_RSP;
441         rsp_msg->sm_stat_rsp.strsp_es_epoch = spp->sp_h_epoch;
442         spans_addr_copy(spp->sp_addr.address,
443                         &rsp_msg->sm_stat_rsp.strsp_es_addr);
444         spans_send_msg(spp, rsp_msg);
445         atm_free(rsp_msg);
446 }
447
448
449
450 /*
451  * Process a status response
452  *
453  * Called when a status response is received.
454  * Processing will be based on the current SPANS state.
455  *
456  * Arguments:
457  *      spp     pointer to SPANS protocol instance block
458  *      msg     pointer to the status response message
459  *
460  * Returns:
461  *      none
462  *
463  */
464 static void
465 spans_status_rsp(struct spans *spp, spans_msg *msg)
466 {
467
468         /*
469          * Reset the probe count.
470          */
471         spp->sp_probe_ct = 0;
472
473         switch (spp->sp_state) {
474         case SPANS_PROBE:
475                 /*
476                  * Interface just came up, update signalling state
477                  */
478                 spp->sp_state = SPANS_ACTIVE;
479                 break;
480
481         case SPANS_ACTIVE:
482                 break;
483
484         default:
485                 log(LOG_ERR, "spans: received status msg in state %d\n",
486                                 spp->sp_state);
487         }
488
489         /*
490          * Process the message
491          */
492         spans_host_link(spp, msg->sm_stat_req.streq_es_epoch);
493 }
494
495
496 /*
497  * Process an open indication or open request
498  *
499  * Called when an open indication or open request is received.
500  * Processing will be based on the state of the requested connection.
501  *
502  * Arguments:
503  *      spp     pointer to SPANS protocol instance block
504  *      msg     pointer to the open message
505  *
506  * Returns:
507  *      none
508  *
509  */
510 static void
511 spans_open_req(struct spans *spp, spans_msg *msg)
512 {
513         spans_result            result = SPANS_OK;
514         spans_msg               *rsp_msg;
515         struct spans_vccb       *svp = NULL;
516         struct atm_pif          *pip;
517         spans_vpvc              vpvc;
518         int                     err = 0, vpi, vci;
519         Aal_t                   aal;
520         Atm_attributes          call_attrs;
521
522         ATM_DEBUG2("spans_open_req: spp=%p, msg=%p\n", spp, msg);
523
524         /*
525          * See if the connection is new
526          */
527         if ((svp = spans_find_conn(spp, &msg->sm_open_req.opreq_conn)) != NULL) {
528                 /*
529                  * We already have a VCCB that matches the connection in
530                  * the request
531                  */
532                 vpi = SPANS_EXTRACT_VPI(msg->sm_open_req.opreq_vpvc.vpf_vpvc);
533                 vci = SPANS_EXTRACT_VCI(msg->sm_open_req.opreq_vpvc.vpf_vpvc);
534                 if (msg->sm_open_req.opreq_aal == svp->sv_spans_aal &&
535                                 (!msg->sm_open_req.opreq_vpvc.vpf_valid ||
536                                         (vpi == svp->sv_vpi &&
537                                         vci == svp->sv_vci))) {
538                         /*
539                          * VCCB already exists, process depending on
540                          * state
541                          */
542                         switch (svp->sv_sstate) {
543                         case SPANS_VC_R_POPEN:
544                                 /* I'm still thinking about it */
545                                 return;
546                         case SPANS_VC_OPEN:
547                                 /* Retransmit the open_rsp */
548                                 break;
549                         case SPANS_VC_POPEN:
550                         case SPANS_VC_CLOSE:
551                         case SPANS_VC_ABORT:
552                                 ATM_DEBUG0("spans_open_req: bad VCCB state\n");
553                                 result = SPANS_FAIL;
554                                 break;
555                         }
556                 } else {
557                         /*
558                          * VCCB is for same connection, but other
559                          * parameters don't match
560                          */
561                         ATM_DEBUG0("spans_open_req: VCCB confusion\n");
562                         result = SPANS_FAIL;
563                 }
564                 svp = NULL;
565                 goto response;
566         }
567
568         /*
569          * Verify that the request is for our ATM addres
570          */
571         if (spans_addr_cmp(spp->sp_addr.address,
572                         &msg->sm_open_req.opreq_conn.con_dst)) {
573                 ATM_DEBUG0("spans_open_req: bad destination\n");
574                 result = SPANS_BADDEST;
575                 goto response;
576         }
577
578         /*
579          * See if we recognize the specified AAL
580          */
581         if (!spans_get_local_aal(msg->sm_open_req.opreq_aal, &aal)) {
582                 ATM_DEBUG0("spans_open_req: bad AAL\n");
583                 result = SPANS_FAIL;
584                 goto response;
585         }
586
587         /*
588          * Should verify that we can handle requested connection QOS
589          */
590
591         /*
592          * Select a VPI/VCI for the new connection
593          */
594         if (msg->sm_open_req.opreq_vpvc.vpf_valid) {
595                 /*
596                  * Requestor asked for a certain VPI/VCI.  Make sure we
597                  * aren't already using the pair that was asked for.
598                  */
599                 vpi = SPANS_EXTRACT_VPI(msg->sm_open_req.opreq_vpvc.vpf_vpvc);
600                 vci = SPANS_EXTRACT_VCI(msg->sm_open_req.opreq_vpvc.vpf_vpvc);
601                 if (spans_find_vpvc(spp, vci, vpi, VCC_IN)) {
602                         ATM_DEBUG0("spans_open_req: VPI, VCI busy\n");
603                         result = SPANS_NOVPVC;
604                         goto response;
605                 }
606                 vpvc = msg->sm_open_req.opreq_vpvc.vpf_vpvc;
607         } else {
608                 /*
609                  * Allocate a VPI/VCI for this end of the VCC
610                  */
611                 vpvc = spans_alloc_vpvc(spp);
612                 if (vpvc == 0) {
613                         ATM_DEBUG0("spans_open_req: no VPI, VCI available\n");
614                         result = SPANS_NOVPVC;
615                         goto response;
616                 }
617         }
618
619         /*
620          * Get a new VCCB for the connection
621          */
622         svp = (struct spans_vccb *)atm_allocate(&spans_vcpool);
623         if (svp == NULL) {
624                 ATM_DEBUG0("spans_open_req: VCCB pool empty\n");
625                 result = SPANS_NORSC;
626                 goto response;
627         }
628
629         /*
630          * Find the physical interface structure
631          */
632         pip = spp->sp_pif;
633
634         /*
635          * Fill in the VCCB fields that we can at this point
636          */
637         svp->sv_type = VCC_SVC | VCC_IN;
638         svp->sv_proto = ATM_SIG_SPANS;
639         svp->sv_sstate = SPANS_VC_R_POPEN;
640         svp->sv_ustate = VCCU_POPEN;
641         svp->sv_pif = pip;
642         svp->sv_nif = pip->pif_nif;
643         svp->sv_conn = msg->sm_open_req.opreq_conn;
644         svp->sv_spans_qos = msg->sm_open_req.opreq_desrsrc;
645         svp->sv_spans_aal = msg->sm_open_req.opreq_aal;
646         svp->sv_tstamp = time_second;
647
648         svp->sv_vpi = SPANS_EXTRACT_VPI(vpvc);
649         svp->sv_vci = SPANS_EXTRACT_VCI(vpvc);
650
651         /*
652          * Put the VCCB on the SPANS queue
653          */
654         ENQUEUE(svp, struct spans_vccb, sv_sigelem, spp->sp_vccq);
655
656         /*
657          * Set up the ATM attributes block
658          */
659         KM_ZERO(&call_attrs, sizeof(call_attrs));
660         call_attrs.nif = svp->sv_nif;
661         call_attrs.api = CMAPI_CPCS;
662
663         call_attrs.aal.tag = T_ATM_PRESENT;
664         call_attrs.aal.type = aal;
665         switch(aal) {
666         case ATM_AAL3_4:
667                 call_attrs.aal.v.aal4.forward_max_SDU_size =
668                                 ATM_NIF_MTU;
669                 call_attrs.aal.v.aal4.backward_max_SDU_size =
670                                 ATM_NIF_MTU;
671                 call_attrs.aal.v.aal4.SSCS_type =
672                                 T_ATM_NULL;
673                 call_attrs.aal.v.aal4.mid_low = 0;
674                 call_attrs.aal.v.aal4.mid_high = 1023;
675                 break;
676         case ATM_AAL5:
677                 call_attrs.aal.v.aal5.forward_max_SDU_size =
678                                 ATM_NIF_MTU;
679                 call_attrs.aal.v.aal5.backward_max_SDU_size =
680                                 ATM_NIF_MTU;
681                 call_attrs.aal.v.aal5.SSCS_type =
682                                 T_ATM_NULL;
683                 break;
684         }
685
686         call_attrs.traffic.tag = T_ATM_PRESENT;
687         call_attrs.traffic.v.forward.PCR_high_priority = T_ATM_ABSENT;
688         call_attrs.traffic.v.forward.PCR_all_traffic = 
689                         msg->sm_open_req.opreq_desrsrc.rsc_peak *
690                         1000 / 53;
691         call_attrs.traffic.v.forward.SCR_high_priority = T_ATM_ABSENT;
692         call_attrs.traffic.v.forward.SCR_all_traffic = T_ATM_ABSENT;
693         call_attrs.traffic.v.forward.MBS_high_priority = T_ATM_ABSENT;
694         call_attrs.traffic.v.forward.MBS_all_traffic = T_ATM_ABSENT;
695         call_attrs.traffic.v.forward.tagging = T_NO;
696         call_attrs.traffic.v.backward.PCR_high_priority = T_ATM_ABSENT;
697         call_attrs.traffic.v.backward.PCR_all_traffic = 
698                         call_attrs.traffic.v.forward.PCR_all_traffic;
699         call_attrs.traffic.v.backward.SCR_high_priority = T_ATM_ABSENT;
700         call_attrs.traffic.v.backward.SCR_all_traffic = T_ATM_ABSENT;
701         call_attrs.traffic.v.backward.MBS_high_priority = T_ATM_ABSENT;
702         call_attrs.traffic.v.backward.MBS_all_traffic = T_ATM_ABSENT;
703         call_attrs.traffic.v.backward.tagging = T_NO;
704         call_attrs.traffic.v.best_effort = T_YES;
705
706         call_attrs.bearer.tag = T_ATM_PRESENT;
707         call_attrs.bearer.v.bearer_class = T_ATM_CLASS_X;
708         call_attrs.bearer.v.traffic_type = T_ATM_NULL;
709         call_attrs.bearer.v.timing_requirements = T_ATM_NULL;
710         call_attrs.bearer.v.clipping_susceptibility = T_NO;
711         call_attrs.bearer.v.connection_configuration = T_ATM_1_TO_1;
712
713
714         call_attrs.bhli.tag = T_ATM_ABSENT;
715         call_attrs.blli.tag_l2 = T_ATM_ABSENT;
716         call_attrs.blli.tag_l3 = T_ATM_ABSENT;
717         call_attrs.llc.tag = T_ATM_ABSENT;
718
719         call_attrs.called.tag = T_ATM_PRESENT;
720         spans_addr_copy(&msg->sm_open_req.opreq_conn.con_dst,
721                 call_attrs.called.addr.address);
722         call_attrs.called.addr.address_format = T_ATM_SPANS_ADDR;
723         call_attrs.called.addr.address_length = sizeof(spans_addr);
724         call_attrs.called.subaddr.address_format = T_ATM_ABSENT;
725         call_attrs.called.subaddr.address_length = 0;
726
727         call_attrs.calling.tag = T_ATM_PRESENT;
728         spans_addr_copy(&msg->sm_open_req.opreq_conn.con_src,
729                 call_attrs.calling.addr.address);
730         call_attrs.calling.addr.address_format = T_ATM_SPANS_ADDR;
731         call_attrs.calling.addr.address_length = sizeof(spans_addr);
732         call_attrs.calling.subaddr.address_format = T_ATM_ABSENT;
733         call_attrs.calling.subaddr.address_length = 0;
734
735         call_attrs.qos.tag = T_ATM_PRESENT;
736         call_attrs.qos.v.coding_standard = T_ATM_NETWORK_CODING;
737         call_attrs.qos.v.forward.qos_class = T_ATM_QOS_CLASS_0;
738         call_attrs.qos.v.backward.qos_class = T_ATM_QOS_CLASS_0;
739
740         call_attrs.transit.tag = T_ATM_ABSENT;
741         call_attrs.cause.tag = T_ATM_ABSENT;
742
743         /*
744          * Notify the connection manager that it has a new channel
745          */
746         err = atm_cm_incoming((struct vccb *)svp, &call_attrs);
747         if (err) {
748                 ATM_DEBUG0("spans_open_req: atm_cm_incoming returned error\n");
749                 result = SPANS_FAIL;
750                 goto response;
751         }
752
753         /*
754          * Wait for the connection recipient to issue an accept
755          */
756         return;
757
758 response:
759         /*
760          * Clean up the VCCB and the atm_conn block if we got them
761          */
762         if (svp) {
763                 DEQUEUE(svp, struct spans_vccb, sv_sigelem,
764                                 spp->sp_vccq);
765                 atm_free(svp);
766         }
767
768         /*
769          * Some problem was detected with the request.  Send a SPANS
770          * message rejecting the connection.
771          */
772         rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
773         if (rsp_msg == NULL)
774                 return;
775
776         /*
777          * Fill out the response
778          */
779         rsp_msg->sm_vers = SPANS_VERS_1_0;
780         rsp_msg->sm_type = SPANS_OPEN_RSP;
781         rsp_msg->sm_open_rsp.oprsp_conn = msg->sm_open_req.opreq_conn;
782         rsp_msg->sm_open_rsp.oprsp_result = result;
783         rsp_msg->sm_open_rsp.oprsp_vpvc = 0;
784
785         /*
786          * Send the Open Response
787          */
788         spans_send_msg(spp, rsp_msg);
789         atm_free(rsp_msg);
790 }
791
792
793 /*
794  * Process an open response or open confirmation
795  *
796  * Called when an open response or open confirmation is received.
797  * Processing will be based on the state of the requested connection and
798  * the status returned.
799  *
800  * Arguments:
801  *      spp     pointer to SPANS protocol instance block
802  *      msg     pointer to the open response or confirmation message
803  *
804  * Returns:
805  *      none
806  *
807  */
808 static void
809 spans_open_rsp(struct spans *spp, spans_msg *msg)
810 {
811         struct spans_vccb       *svp;
812
813         ATM_DEBUG2("spans_open_rsp: spp=%p, msg=%p\n", spp, msg);
814
815         /*
816          * Locate the VCCB for the connection
817          */
818         svp = spans_find_conn(spp, &msg->sm_open_rsp.oprsp_conn);
819         if (svp == NULL)
820                 return;
821
822         /*
823          * Check the connection state
824          */
825         if ((svp->sv_sstate != SPANS_VC_POPEN &&
826                         svp->sv_sstate != SPANS_VC_R_POPEN) ||
827                         svp->sv_ustate != VCCU_POPEN) {
828                 ATM_DEBUG2(
829         "spans_open_rsp: invalid VCCB state, sstate=%d, ustate=%d\n",
830                                 svp->sv_sstate, svp->sv_ustate);
831                 return;
832         }
833
834         /*
835          * Cancel the retransmission timer
836          */
837         SPANS_VC_CANCEL((struct vccb *) svp);
838
839         /*
840          * Check the result
841          */
842         switch (msg->sm_open_rsp.oprsp_result) {
843
844         case SPANS_OK:
845                 /*
846                  * Save the assigned VPI and VCI
847                  */
848                 svp->sv_vpi = SPANS_EXTRACT_VPI(msg->sm_open_rsp.oprsp_vpvc);
849                 svp->sv_vci = SPANS_EXTRACT_VCI(msg->sm_open_rsp.oprsp_vpvc);
850
851                 /*
852                  * Update the VCC state and notify the VCC owner
853                  */
854                 svp->sv_sstate = SPANS_VC_OPEN;
855                 svp->sv_ustate = VCCU_OPEN;
856                 svp->sv_tstamp = time_second;
857                 atm_cm_connected(svp->sv_connvc);
858                 break;
859
860         case SPANS_FAIL:
861         case SPANS_NOVPVC:
862         case SPANS_NORSC:
863         case SPANS_BADDEST:
864                 /*
865                  * Close out the VCCB and notify the user
866                  */
867                 svp->sv_sstate = SPANS_VC_FREE;
868                 svp->sv_ustate = VCCU_CLOSED;
869                 svp->sv_connvc->cvc_attr.cause.tag = T_ATM_PRESENT;
870                 svp->sv_connvc->cvc_attr.cause.v.coding_standard =
871                                 T_ATM_ITU_CODING;
872                 svp->sv_connvc->cvc_attr.cause.v.location =
873                                 T_ATM_LOC_USER;
874                 svp->sv_connvc->cvc_attr.cause.v.cause_value =
875                                 T_ATM_CAUSE_CALL_REJECTED;
876                 KM_ZERO(svp->sv_connvc->cvc_attr.cause.v.diagnostics,
877                                 sizeof(svp->sv_connvc->cvc_attr.cause.v.diagnostics));
878                 atm_cm_cleared(svp->sv_connvc);
879                 break;
880
881         default:
882                 log(LOG_ERR, "spans: unknown result %d in open rsp\n",
883                                 msg->sm_open_rsp.oprsp_result);
884                 break;
885         }
886 }
887
888
889 /*
890  * Process a close request from the network
891  *
892  * Called when a close request, close indication, rclose request, or
893  * rclose indication is received.  Processing will be based on the
894  * state of the connection.
895  *
896  * Arguments:
897  *      spp     pointer to SPANS protocol instance block
898  *      msg     pointer to the close request message
899  *
900  * Returns:
901  *      none
902  *
903  */
904 static void
905 spans_close_req(struct spans *spp, spans_msg *msg)
906 {
907         struct spans_vccb       *svp;
908         spans_result            result;
909         spans_msg               *rsp_msg;
910         u_char                  outstate;
911         Atm_connvc              *cvp;
912
913         ATM_DEBUG2("spans_close_req: spp=%p, msg=%p\n", spp, msg);
914
915         /*
916          * Locate the VCCB for the connection
917          */
918         svp = spans_find_conn(spp, &msg->sm_close_req.clreq_conn);
919         if (svp == NULL) {
920                 result = SPANS_BADDEST;
921                 goto response;
922         }
923
924         /*
925          * Check the connection type
926          */
927         if (!(svp->sv_type & VCC_SVC)) {
928                 result = SPANS_FAIL;
929                 goto response;
930         }
931
932         /*
933          * Check the connection state
934          */
935         switch (svp->sv_sstate) {
936         case SPANS_VC_OPEN:
937         case SPANS_VC_R_POPEN:
938         case SPANS_VC_POPEN:
939                 /*
940                  * VCC is open or opening--continue
941                  */
942                 break;
943         case SPANS_VC_CLOSE:
944         case SPANS_VC_FREE:
945         case SPANS_VC_ABORT:
946                 /*
947                  * We're already closing--give a response, since this
948                  * is probably a retransmission
949                  */
950                 result = SPANS_OK;
951                 goto response;
952         case SPANS_VC_NULL:
953                 result = SPANS_FAIL;
954                 goto response;
955         }
956
957         /*
958          * Cancel the retransmission timer
959          */
960         SPANS_VC_CANCEL((struct vccb *) svp);
961
962         /*
963          * Close out the VCCB and notify the user
964          */
965         outstate = svp->sv_sstate;
966         svp->sv_ustate = VCCU_CLOSED;
967         svp->sv_sstate = SPANS_VC_FREE;
968         cvp = svp->sv_connvc;
969         switch (outstate) {
970         case SPANS_VC_R_POPEN:
971                 spans_free((struct vccb *)svp);
972                 /* FALLTHRU */
973
974         case SPANS_VC_POPEN:
975         case SPANS_VC_OPEN:
976                 cvp->cvc_attr.cause.tag = T_ATM_PRESENT;
977                 cvp->cvc_attr.cause.v.coding_standard =
978                                 T_ATM_ITU_CODING;
979                 cvp->cvc_attr.cause.v.location = T_ATM_LOC_USER;
980                 cvp->cvc_attr.cause.v.cause_value =
981                                 T_ATM_CAUSE_NORMAL_CALL_CLEARING;
982                 KM_ZERO(cvp->cvc_attr.cause.v.diagnostics,
983                                 sizeof(cvp->cvc_attr.cause.v.diagnostics));
984                 atm_cm_cleared(svp->sv_connvc);
985                 break;
986         }
987
988         result = SPANS_OK;
989
990 response:
991         /*
992          * Respond to the SPANS_CLOSE_IND with a SPANS_CLOSE_RSP
993          */
994         rsp_msg = (spans_msg *)atm_allocate(&spans_msgpool);
995         if (rsp_msg == NULL)
996                 return;
997         rsp_msg->sm_vers = SPANS_VERS_1_0;
998         if (msg->sm_type == SPANS_RCLOSE_REQ ||
999                         msg->sm_type == SPANS_RCLOSE_IND) {
1000                 rsp_msg->sm_type = SPANS_RCLOSE_RSP;
1001         } else {
1002                 rsp_msg->sm_type = SPANS_CLOSE_RSP;
1003         }
1004         rsp_msg->sm_close_rsp.clrsp_conn = msg->sm_close_req.clreq_conn;
1005         rsp_msg->sm_close_rsp.clrsp_result = result;
1006         spans_send_msg(spp, rsp_msg);
1007         atm_free(rsp_msg);
1008 }
1009
1010
1011 /*
1012  * Process a close response or close confirmation
1013  *
1014  * Called when an close response or close confirmation is received.
1015  * Processing will be based on the state of the requested connection and
1016  * the returned status.
1017  *
1018  * Arguments:
1019  *      spp     pointer to SPANS protocol instance block
1020  *      msg     pointer to the close response or confirmation message
1021  *
1022  * Returns:
1023  *      none
1024  *
1025  */
1026 static void
1027 spans_close_rsp(struct spans *spp, spans_msg *msg)
1028 {
1029         struct spans_vccb       *svp;
1030
1031         ATM_DEBUG2("spans_close_rsp: spp=%p, msg=%p\n", spp, msg);
1032
1033         /*
1034          * Locate the VCCB for the connection
1035          */
1036         svp = spans_find_conn(spp, &msg->sm_close_rsp.clrsp_conn);
1037         if (svp == NULL) {
1038                 return;
1039         }
1040
1041         /*
1042          * Check the VCCB state
1043          */
1044         if (svp->sv_sstate != SPANS_VC_CLOSE) {
1045                 return;
1046         }
1047
1048         /*
1049          * Cancel the retransmission timer
1050          */
1051         SPANS_VC_CANCEL((struct vccb *) svp);
1052
1053         /*
1054          * Check the response from the remote end
1055          */
1056         switch (msg->sm_close_rsp.clrsp_result) {
1057
1058         case SPANS_OK:
1059                 /*
1060                  * Mark the VCCB as closed and notify the owner
1061                  */
1062                 svp->sv_sstate = SPANS_VC_FREE;
1063                 svp->sv_connvc->cvc_attr.cause.tag = T_ATM_PRESENT;
1064                 svp->sv_connvc->cvc_attr.cause.v.coding_standard =
1065                                 T_ATM_ITU_CODING;
1066                 svp->sv_connvc->cvc_attr.cause.v.location =
1067                                 T_ATM_LOC_USER;
1068                 svp->sv_connvc->cvc_attr.cause.v.cause_value =
1069                                 T_ATM_CAUSE_NORMAL_CALL_CLEARING;
1070                 KM_ZERO(svp->sv_connvc->cvc_attr.cause.v.diagnostics,
1071                                 sizeof(svp->sv_connvc->cvc_attr.cause.v.diagnostics));
1072                 atm_cm_cleared(svp->sv_connvc);
1073                 break;
1074
1075         case SPANS_NOVPVC:
1076         case SPANS_BADDEST:
1077         case SPANS_FAIL:
1078         case SPANS_NORSC:
1079                 /*
1080                  * Mark the VCCB as closed and notify the owner
1081                  */
1082                 svp->sv_sstate = SPANS_VC_FREE;
1083                 svp->sv_connvc->cvc_attr.cause.tag = T_ATM_PRESENT;
1084                 svp->sv_connvc->cvc_attr.cause.v.coding_standard =
1085                                 T_ATM_ITU_CODING;
1086                 svp->sv_connvc->cvc_attr.cause.v.location =
1087                                 T_ATM_LOC_USER;
1088                 svp->sv_connvc->cvc_attr.cause.v.cause_value =
1089                                 T_ATM_CAUSE_UNSPECIFIED_NORMAL;
1090                 KM_ZERO(svp->sv_connvc->cvc_attr.cause.v.diagnostics,
1091                                 sizeof(svp->sv_connvc->cvc_attr.cause.v.diagnostics));
1092                 atm_cm_cleared(svp->sv_connvc);
1093                 break;
1094
1095         default:
1096                 log(LOG_ERR, "spans: unknown result %d in close rsp\n",
1097                                 msg->sm_close_rsp.clrsp_result);
1098                 break;
1099         }
1100 }
1101
1102
1103 /*
1104  * Process a multi request or multi indication
1105  *
1106  * Called when a multi response or multi confirmation is received.  We
1107  * don't support multicast channels, so we just reject the request.
1108  *
1109  * Arguments:
1110  *      spp     pointer to SPANS protocol instance block
1111  *      msg     pointer to the multi request or indication message
1112  *
1113  * Returns:
1114  *      none
1115  *
1116  */
1117 static void
1118 spans_multi_req(struct spans *spp, spans_msg *msg)
1119 {
1120         spans_msg       *rsp_msg;
1121
1122         /*
1123          * Get memory for a SPANS_MULTI_RSP message.
1124          */
1125         rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1126         if (rsp_msg == NULL)
1127                 return;
1128
1129         /*
1130          * Fill out the response.
1131          */
1132         rsp_msg->sm_vers = SPANS_VERS_1_0;
1133         rsp_msg->sm_type = SPANS_MULTI_RSP;
1134         rsp_msg->sm_multi_rsp.mursp_conn = msg->sm_multi_req.mureq_conn;
1135         rsp_msg->sm_multi_rsp.mursp_result = SPANS_FAIL;
1136         rsp_msg->sm_multi_rsp.mursp_rsrc = msg->sm_multi_req.mureq_desrsrc;
1137         rsp_msg->sm_multi_rsp.mursp_vpvc = 0;
1138
1139         /*
1140          * Send the response and free the message.
1141          */
1142         spans_send_msg(spp, rsp_msg);
1143         atm_free(rsp_msg);
1144 }
1145
1146
1147 /*
1148  * Process an add request or add indication
1149  *
1150  * Called when an add response or add confirmation is received.  We
1151  * don't support multicast channels, so we just reject the request.
1152  *
1153  * Arguments:
1154  *      spp     pointer to SPANS protocol instance block
1155  *      msg     pointer to the add request or indication message
1156  *
1157  * Returns:
1158  *      none
1159  *
1160  */
1161 static void
1162 spans_add_req(struct spans *spp, spans_msg *msg)
1163 {
1164         spans_msg       *rsp_msg;
1165
1166         /*
1167          * Get memory for a SPANS_ADD_RSP message.
1168          */
1169         rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1170         if (rsp_msg == NULL)
1171                 return;
1172
1173         /*
1174          * Fill out the response.
1175          */
1176         rsp_msg->sm_vers = SPANS_VERS_1_0;
1177         rsp_msg->sm_type = SPANS_ADD_RSP;
1178         rsp_msg->sm_add_rsp.adrsp_conn = msg->sm_add_req.adreq_desconn;
1179         rsp_msg->sm_add_rsp.adrsp_result = SPANS_FAIL;
1180         rsp_msg->sm_add_rsp.adrsp_rsrc.rsc_peak = 0;
1181         rsp_msg->sm_add_rsp.adrsp_rsrc.rsc_mean = 0;
1182         rsp_msg->sm_add_rsp.adrsp_rsrc.rsc_burst = 0;
1183
1184         /*
1185          * Send the response and free the message.
1186          */
1187         spans_send_msg(spp, rsp_msg);
1188         atm_free(rsp_msg);
1189 }
1190
1191
1192 /*
1193  * Process a join request
1194  *
1195  * Called when an join request is received.  We don't support group
1196  * addresses, so we just reject the request.
1197  *
1198  * Arguments:
1199  *      spp     pointer to SPANS protocol instance block
1200  *      msg     pointer to the join request message
1201  *
1202  * Returns:
1203  *      none
1204  *
1205  */
1206 static void
1207 spans_join_req(struct spans *spp, spans_msg *msg)
1208 {
1209         spans_msg       *rsp_msg;
1210
1211         /*
1212          * Get memory for a SPANS_JOIN_CNF message.
1213          */
1214         rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1215         if (rsp_msg == NULL)
1216                 return;
1217
1218         /*
1219          * Fill out the response.
1220          */
1221         rsp_msg->sm_vers = SPANS_VERS_1_0;
1222         rsp_msg->sm_type = SPANS_JOIN_CNF;
1223         spans_addr_copy(&msg->sm_join_req.jnreq_addr,
1224                         &rsp_msg->sm_join_cnf.jncnf_addr);
1225         rsp_msg->sm_join_cnf.jncnf_result = SPANS_FAIL;
1226
1227         /*
1228          * Send the response and free the message.
1229          */
1230         spans_send_msg(spp, rsp_msg);
1231         atm_free(rsp_msg);
1232 }
1233
1234
1235 /*
1236  * Process a leave request
1237  *
1238  * Called when an leave request is received.  We don't support group
1239  * addresses, so we just reject the request.
1240  *
1241  * Arguments:
1242  *      spp     pointer to SPANS protocol instance block
1243  *      msg     pointer to the leave request message
1244  *
1245  * Returns:
1246  *      none
1247  *
1248  */
1249 static void
1250 spans_leave_req(struct spans *spp, spans_msg *msg)
1251 {
1252         spans_msg       *rsp_msg;
1253
1254         /*
1255          * Get memory for a SPANS_LEAVE_CNF message.
1256          */
1257         rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1258         if (rsp_msg == NULL)
1259                 return;
1260
1261         /*
1262          * Fill out the response.
1263          */
1264         rsp_msg->sm_vers = SPANS_VERS_1_0;
1265         rsp_msg->sm_type = SPANS_LEAVE_CNF;
1266         spans_addr_copy(&msg->sm_leave_req.lvreq_addr,
1267                         &rsp_msg->sm_leave_cnf.lvcnf_addr);
1268         rsp_msg->sm_leave_cnf.lvcnf_result = SPANS_FAIL;
1269
1270         /*
1271          * Send the response and free the message.
1272          */
1273         spans_send_msg(spp, rsp_msg);
1274         atm_free(rsp_msg);
1275 }
1276
1277
1278 /*
1279  * Process a VCI range indication
1280  *
1281  * Called when a VCI range indication is received.  Adjust the VCI
1282  * bounds if they have changed.
1283  *
1284  * Arguments:
1285  *      spp     pointer to SPANS protocol instance block
1286  *      msg     pointer to the VCI range indication message
1287  *
1288  * Returns:
1289  *      none
1290  *
1291  */
1292 static void
1293 spans_vcir_ind(struct spans *spp, spans_msg *msg)
1294 {
1295         /*
1296          * Adjust the limits if they have changed
1297          */
1298         if (msg->sm_vcir_ind.vrind_min != spp->sp_min_vci) {
1299                 spp->sp_min_vci =
1300                                 (msg->sm_vcir_ind.vrind_min <
1301                                 SPANS_MIN_VCI ?
1302                                 SPANS_MIN_VCI :
1303                                 msg->sm_vcir_ind.vrind_min);
1304         }
1305         if (msg->sm_vcir_ind.vrind_max != spp->sp_max_vci) {
1306                 spp->sp_max_vci =
1307                                 (msg->sm_vcir_ind.vrind_max >
1308                                 SPANS_MAX_VCI ?
1309                                 SPANS_MAX_VCI :
1310                                 msg->sm_vcir_ind.vrind_max);
1311         }
1312 }
1313
1314
1315 /*
1316  * Process a query request
1317  *
1318  * Called when a query request is received.  Respond with the
1319  * appropriate query response.
1320  *
1321  * Arguments:
1322  *      spp     pointer to SPANS protocol instance block
1323  *      msg     pointer to the VCI range indication message
1324  *
1325  * Returns:
1326  *      none
1327  *
1328  */
1329 static void
1330 spans_query_req(struct spans *spp, spans_msg *msg)
1331 {
1332         struct spans_vccb       *svp = NULL;
1333         spans_msg               *rsp_msg;
1334
1335         ATM_DEBUG1("spans_query_req: msg=%p\n", msg);
1336
1337         /*
1338          * Ignore an end-to-end query
1339          */
1340         if (msg->sm_query_req.qyreq_type == SPANS_QUERY_END_TO_END) {
1341                 return;
1342         }
1343
1344         /*
1345          * Get memory for a SPANS_QUERY_RSP message.
1346          */
1347         rsp_msg = (spans_msg *) atm_allocate(&spans_msgpool);
1348         if (rsp_msg == NULL)
1349                 return;
1350
1351         /*
1352          * Fill out the response.
1353          */
1354         rsp_msg->sm_vers = SPANS_VERS_1_0;
1355         rsp_msg->sm_type = SPANS_QUERY_RSP;
1356         rsp_msg->sm_query_rsp.qyrsp_conn = msg->sm_query_req.qyreq_conn;
1357         rsp_msg->sm_query_rsp.qyrsp_type = msg->sm_query_req.qyreq_type;
1358         rsp_msg->sm_query_rsp.qyrsp_data = 0;
1359
1360         /*
1361          * Get the state of the requested connection
1362          */
1363         svp = spans_find_conn(spp, &msg->sm_query_req.qyreq_conn);
1364         if (svp) {
1365                 switch(svp->sv_sstate) {
1366                 case SPANS_VC_NULL:
1367                 case SPANS_VC_FREE:
1368                         rsp_msg->sm_query_rsp.qyrsp_state =
1369                                 SPANS_CONN_CLOSED;
1370                         break;
1371                 case SPANS_VC_OPEN:
1372                         rsp_msg->sm_query_rsp.qyrsp_state =
1373                                 SPANS_CONN_OPEN;
1374                         break;
1375                 case SPANS_VC_POPEN:
1376                 case SPANS_VC_R_POPEN:
1377                         rsp_msg->sm_query_rsp.qyrsp_state =
1378                                 SPANS_CONN_OPEN_PEND;
1379                         break;
1380                 case SPANS_VC_CLOSE:
1381                 case SPANS_VC_ABORT:
1382                         rsp_msg->sm_query_rsp.qyrsp_state =
1383                                 SPANS_CONN_CLOSE_PEND;
1384                         break;
1385                 case SPANS_VC_ACTIVE:
1386                 case SPANS_VC_ACT_DOWN:
1387                         /*
1388                          * VCCB is for a PVC (shouldn't happen)
1389                          */
1390                         atm_free(rsp_msg);
1391                         return;
1392                 }
1393         } else {
1394                 /*
1395                  * No VCCB found--connection doesn't exist
1396                  */
1397                 rsp_msg->sm_query_rsp.qyrsp_state = SPANS_CONN_CLOSED;
1398         }
1399
1400         /*
1401          * Send the response and free the message.
1402          */
1403         spans_send_msg(spp, rsp_msg);
1404         atm_free(rsp_msg);
1405 }
1406
1407
1408 /*
1409  * Process a SPANS signalling message
1410  *
1411  * Called when a SPANS message is received.  The message is converted
1412  * into internal format with XDR and decoded by calling the appropriate
1413  * mesage handling routine.  Unrecognized and unexpected messages are
1414  * logged.
1415  *
1416  * Arguments:
1417  *      spp     pointer to SPANS protocol instance block
1418  *      m       pointer to a buffer chain containing the SPANS message
1419  *
1420  * Returns:
1421  *      none
1422  *
1423  */
1424 void
1425 spans_rcv_msg(struct spans *spp, KBuffer *m)
1426 {
1427         XDR             xdrs;
1428         spans_msg       *msg;
1429
1430         /*
1431          * Get storage for the message
1432          */
1433         msg = (spans_msg *)atm_allocate(&spans_msgpool);
1434         if (msg == NULL) {
1435                 return;
1436         }
1437
1438         /*
1439          * Convert the message from network order to internal format
1440          */
1441         xdrmbuf_init(&xdrs, m, XDR_DECODE);
1442         if (!xdr_spans_msg(&xdrs, msg)) {
1443                 log(LOG_ERR, "spans_rcv_msg: XDR decode failed\n");
1444                 spans_dump_buffer(m);
1445                 goto done;
1446         }
1447
1448 #ifdef NOTDEF
1449         /*
1450          * Debug--print some information about the message
1451          */
1452         if (msg->sm_type != SPANS_STAT_REQ &&
1453                         msg->sm_type != SPANS_STAT_IND &&
1454                         msg->sm_type != SPANS_STAT_RSP) {
1455                 kprintf("spans_rcv_msg: got ");
1456                 spans_print_msg(msg);
1457         }
1458 #endif
1459
1460         /*
1461          * Verify the message sm_vers
1462          */
1463         if (msg->sm_vers != SPANS_VERS_1_0) {
1464                 log(LOG_ERR, "spans: invalid message version 0x%x\n",
1465                                 msg->sm_vers);
1466         }
1467
1468         /*
1469          * Ignore the message if SPANS isn't up yet
1470          */
1471         if (spp->sp_state != SPANS_ACTIVE &&
1472                         (spp->sp_state != SPANS_PROBE ||
1473                         (msg->sm_type != SPANS_STAT_REQ &&
1474                         msg->sm_type != SPANS_STAT_RSP &&
1475                         msg->sm_type != SPANS_STAT_IND))) {
1476                 goto done;
1477         }
1478
1479         /*
1480          * Process the message based on its type
1481          */
1482         switch(msg->sm_type) {
1483         case SPANS_STAT_REQ:
1484                 spans_status_ind(spp, msg);
1485                 break;
1486         case SPANS_STAT_IND:
1487                 spans_status_ind(spp, msg);
1488                 break;
1489         case SPANS_STAT_RSP:
1490                 spans_status_rsp(spp, msg);
1491                 break;
1492         case SPANS_OPEN_REQ:
1493                 spans_open_req(spp, msg);
1494                 break;
1495         case SPANS_OPEN_IND:
1496                 spans_open_req(spp, msg);
1497                 break;
1498         case SPANS_OPEN_RSP:
1499                 spans_open_rsp(spp, msg);
1500                 break;
1501         case SPANS_OPEN_CNF:
1502                 spans_open_rsp(spp, msg);
1503                 break;
1504         case SPANS_CLOSE_REQ:
1505                 spans_close_req(spp, msg);
1506                 break;
1507         case SPANS_CLOSE_IND:
1508                 spans_close_req(spp, msg);
1509                 break;
1510         case SPANS_CLOSE_RSP:
1511                 spans_close_rsp(spp, msg);
1512                 break;
1513         case SPANS_CLOSE_CNF:
1514                 spans_close_rsp(spp, msg);
1515                 break;
1516         case SPANS_RCLOSE_REQ:
1517                 spans_close_req(spp, msg);
1518                 break;
1519         case SPANS_RCLOSE_IND:
1520                 spans_close_req(spp, msg);
1521                 break;
1522         case SPANS_RCLOSE_RSP:
1523                 spans_close_rsp(spp, msg);
1524                 break;
1525         case SPANS_RCLOSE_CNF:
1526                 spans_close_rsp(spp, msg);
1527                 break;
1528         case SPANS_MULTI_REQ:
1529                 spans_multi_req(spp, msg);
1530                 break;
1531         case SPANS_MULTI_IND:
1532                 spans_multi_req(spp, msg);
1533                 break;
1534         case SPANS_MULTI_RSP:
1535                 log(LOG_ERR,
1536                         "spans: unexpected message (multi_rsp)\n");
1537                 break;
1538         case SPANS_MULTI_CNF:
1539                 log(LOG_ERR,
1540                         "spans: unexpected message (multi_conf)\n");
1541                 break;
1542         case SPANS_ADD_REQ:
1543                 spans_add_req(spp, msg);
1544                 break;
1545         case SPANS_ADD_IND:
1546                 spans_add_req(spp, msg);
1547                 break;
1548         case SPANS_ADD_RSP:
1549                 log(LOG_ERR,
1550                         "spans: unexpected message (add_rsp)\n");
1551                 break;
1552         case SPANS_ADD_CNF:
1553                 log(LOG_ERR, "spans: unexpected message (add_conf)\n");
1554                 break;
1555         case SPANS_JOIN_REQ:
1556                 spans_join_req(spp, msg);
1557                 break;
1558         case SPANS_JOIN_CNF:
1559                 log(LOG_ERR, "spans: unexpected message (join_conf)\n");
1560                 break;
1561         case SPANS_LEAVE_REQ:
1562                 spans_leave_req(spp, msg);
1563                 break;
1564         case SPANS_LEAVE_CNF:
1565                 log(LOG_ERR,
1566                         "spans: unexpected message (leave_conf)\n");
1567                 break;
1568         case SPANS_VCIR_IND:
1569                 spans_vcir_ind(spp, msg);
1570                 break;
1571         case SPANS_QUERY_REQ:
1572                 spans_query_req(spp, msg);
1573                 break;
1574         case SPANS_QUERY_RSP:
1575                 log(LOG_ERR,
1576                         "spans: unexpected message (query_rsp)\n");
1577                 break;
1578         default:
1579                 log(LOG_ERR, "spans: unknown SPANS message type %d\n",
1580                                 msg->sm_type);
1581         }
1582
1583 done:
1584         /*
1585          * Free the incoming message (both buffer and internal format) if
1586          * necessary.
1587          */
1588         if (msg)
1589                 atm_free(msg);
1590         if (m)
1591                 KB_FREEALL(m);
1592 }