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