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