3 * ===================================
4 * HARP | Host ATM Research Platform
5 * ===================================
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.
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.
21 * Copyright 1994-1998 Network Computing Services, Inc.
23 * Copies of this Software may be made, however, the above copyright
24 * notice must be reproduced on all copies.
26 * @(#) $FreeBSD: src/usr.sbin/atm/scspd/scsp_msg.c,v 1.3 1999/08/28 01:15:33 peter Exp $
27 * @(#) $DragonFly: src/usr.sbin/atm/scspd/scsp_msg.c,v 1.4 2004/12/18 22:48:02 swildner Exp $
32 * Server Cache Synchronization Protocol (SCSP) Support
33 * ----------------------------------------------------
35 * SCSP message-handling routines
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <sys/socket.h>
43 #include <netinet/in.h>
44 #include <netatm/port.h>
45 #include <netatm/queue.h>
46 #include <netatm/atm.h>
47 #include <netatm/atm_if.h>
48 #include <netatm/atm_sap.h>
49 #include <netatm/atm_sys.h>
50 #include <netatm/atm_ioctl.h>
64 * Copy CSAS records into a CA record
67 * dcsp pointer to DCS block for DCS
68 * cap pointer to CA record for CSASs
76 scsp_ca_csas_setup(Scsp_dcs
*dcsp
, Scsp_ca
*cap
)
78 int csas_len
, len
, mtu
;
79 Scsp_server
*ssp
= dcsp
->sd_server
;
80 Scsp_cse
*csep
, *next_csep
;
84 * Loop through pending CSAS records
86 len
= sizeof(struct scsp_nhdr
) + sizeof(struct scsp_nmcp
) +
88 dcsp
->sd_dcsid
.id_len
;
89 csas_len
= sizeof(struct scsp_ncsa
) +
90 dcsp
->sd_server
->ss_id_len
+
91 dcsp
->sd_server
->ss_ckey_len
;
92 mtu
= dcsp
->sd_server
->ss_mtu
;
93 for (csep
= dcsp
->sd_ca_csas
;
94 csep
&& (len
< mtu
- csas_len
);
96 next_csep
= csep
->sc_next
;
97 csap
= scsp_cse2csas(csep
);
98 LINK2TAIL(csap
, Scsp_csa
, cap
->ca_csa_rec
, next
);
100 UNLINK(csep
, Scsp_cse
, dcsp
->sd_ca_csas
, sc_next
);
102 cap
->ca_mcp
.rec_cnt
++;
108 * Process CSA records from a CSU Request that may be in response to
109 * CSAS records sent in a CSUS
112 * dcsp pointer to DCS control block
113 * msg pointer to received message
120 scsp_csus_ack(Scsp_dcs
*dcsp
, Scsp_msg
*msg
)
123 Scsp_csa
*csap
, *csasp
, *next_csasp
;
126 * If this isn't a CSU Request, or there's no outstanding CSUS,
127 * or the outstanding CSUS has already been satisfied, just
130 if (!msg
|| msg
->sc_msg_type
!= SCSP_CSU_REQ_MSG
||
131 !dcsp
->sd_csus_rexmt_msg
||
132 !dcsp
->sd_csus_rexmt_msg
->sc_csu_msg
||
133 !dcsp
->sd_csus_rexmt_msg
->sc_csu_msg
->csu_csa_rec
)
138 * Loop through the CSASs in the CSUS message, checking for
139 * each in the CSA records of the received CSU Request
141 csusp
= dcsp
->sd_csus_rexmt_msg
->sc_csu_msg
;
142 for (csasp
= csusp
->csu_csa_rec
; csasp
; csasp
= next_csasp
) {
143 next_csasp
= csasp
->next
;
144 for (csap
= msg
->sc_csu_msg
->csu_csa_rec
;
145 csap
; csap
= csap
->next
) {
147 * If the records match, unlink and free the
150 if (scsp_cmp_key(&csap
->key
, &csasp
->key
) == 0 &&
151 scsp_cmp_key(&csap
->key
, &csasp
->key
) == 0 &&
152 scsp_cmp_id(&csap
->oid
, &csasp
->oid
) == 0 &&
153 csap
->seq
>= csasp
->seq
) {
154 UNLINK(csasp
, Scsp_csa
,
157 SCSP_FREE_CSA(csasp
);
158 dcsp
->sd_csus_rexmt_msg
->sc_csu_msg
->csu_mcp
.rec_cnt
--;
164 if (csusp
->csu_csa_rec
== (Scsp_csa
*)0) {
166 * All CSASs in the CSUS message have been
167 * answered. Stop the timer and free the
170 HARP_CANCEL(&dcsp
->sd_csus_rexmt_t
);
171 scsp_free_msg(dcsp
->sd_csus_rexmt_msg
);
172 dcsp
->sd_csus_rexmt_msg
= (Scsp_msg
*)0;
175 * If the CRL isn't empty, send another CSUS
178 scsp_send_csus(dcsp
);
188 * dcsp pointer to DCS block for DCS
192 * else errno indicating reason for failure
196 scsp_send_ca(Scsp_dcs
*dcsp
)
201 Scsp_server
*ssp
= dcsp
->sd_server
;
204 * Get memory for a CA message
206 ca_msg
= (Scsp_msg
*)UM_ALLOC(sizeof(Scsp_msg
));
208 scsp_mem_err("scsp_send_ca: sizeof(Scsp_msg)");
210 cap
= (Scsp_ca
*)UM_ALLOC(sizeof(Scsp_ca
));
212 scsp_mem_err("scsp_send_ca: sizeof(Scsp_ca)");
214 UM_ZERO(ca_msg
, sizeof(Scsp_msg
));
215 UM_ZERO(cap
, sizeof(Scsp_ca
));
218 * Fill out constant fields
220 ca_msg
->sc_msg_type
= SCSP_CA_MSG
;
222 cap
->ca_seq
= dcsp
->sd_ca_seq
;
223 cap
->ca_mcp
.pid
= ssp
->ss_pid
;
224 cap
->ca_mcp
.sgid
= ssp
->ss_sgid
;
225 cap
->ca_mcp
.sid
= ssp
->ss_lsid
;
226 cap
->ca_mcp
.rid
= dcsp
->sd_dcsid
;
229 * Fill out state-dependent fields
231 switch(dcsp
->sd_ca_state
) {
237 case SCSP_CAFSM_MASTER
:
240 scsp_ca_csas_setup(dcsp
, cap
);
241 cap
->ca_o
= dcsp
->sd_ca_csas
!= (Scsp_cse
*)0;
243 case SCSP_CAFSM_SLAVE
:
246 scsp_ca_csas_setup(dcsp
, cap
);
247 cap
->ca_o
= dcsp
->sd_ca_csas
!= (Scsp_cse
*)0;
250 scsp_log(LOG_ERR
, "Invalid state in scsp_send_ca");
255 * Send the CA message and save a pointer to it in case
256 * it needs to be retransmitted
258 rc
= scsp_send_msg(dcsp
, ca_msg
);
260 dcsp
->sd_ca_rexmt_msg
= ca_msg
;
262 scsp_free_msg(ca_msg
);
270 * Send a CSU Solicit message
273 * dcsp pointer to DCS block for DCS
277 * else errno indicating reason for failure
281 scsp_send_csus(Scsp_dcs
*dcsp
)
283 int csas_len
, len
, mtu
, rc
;
286 Scsp_csa
*csasp
, *next_csasp
;
287 Scsp_server
*ssp
= dcsp
->sd_server
;
290 * If we have a mesage saved for retransmission, use it.
291 * If not, get memory for a new one.
293 if (dcsp
->sd_csus_rexmt_msg
) {
294 csus_msg
= dcsp
->sd_csus_rexmt_msg
;
295 csusp
= csus_msg
->sc_csu_msg
;
298 * Get memory for a CSUS message
300 csus_msg
= (Scsp_msg
*)UM_ALLOC(sizeof(Scsp_msg
));
302 scsp_mem_err("scsp_send_csus: sizeof(Scsp_msg)");
304 csusp
= (Scsp_csu_msg
*)UM_ALLOC(sizeof(Scsp_csu_msg
));
306 scsp_mem_err("scsp_send_csus: sizeof(Scsp_csu_msg)");
308 UM_ZERO(csus_msg
, sizeof(Scsp_msg
));
309 UM_ZERO(csusp
, sizeof(Scsp_csu_msg
));
312 * Fill out constant fields
314 csus_msg
->sc_msg_type
= SCSP_CSUS_MSG
;
315 csus_msg
->sc_csu_msg
= csusp
;
316 csusp
->csu_mcp
.pid
= ssp
->ss_pid
;
317 csusp
->csu_mcp
.sgid
= ssp
->ss_sgid
;
318 csusp
->csu_mcp
.sid
= ssp
->ss_lsid
;
319 csusp
->csu_mcp
.rid
= dcsp
->sd_dcsid
;
323 * Move CSAS records from CRL into message
325 mtu
= dcsp
->sd_server
->ss_mtu
;
326 csas_len
= sizeof(struct scsp_ncsa
) + ssp
->ss_id_len
+
328 len
= sizeof(struct scsp_nhdr
) + sizeof(struct scsp_nmcp
) +
330 csas_len
* (csusp
->csu_mcp
.rec_cnt
+ 1);
331 for (csasp
= dcsp
->sd_crl
;
332 csasp
&& ((len
+ csas_len
) < mtu
);
333 csasp
= next_csasp
, len
+= csas_len
) {
334 next_csasp
= csasp
->next
;
335 csusp
->csu_mcp
.rec_cnt
++;
336 UNLINK(csasp
, Scsp_csa
, dcsp
->sd_crl
, next
);
337 LINK2TAIL(csasp
, Scsp_csa
, csusp
->csu_csa_rec
, next
);
342 * Send the CSUS message and save a pointer to it in case
343 * it needs to be retransmitted
345 rc
= scsp_send_msg(dcsp
, csus_msg
);
348 * Success--Save a pointer to the message and
349 * start the CSUS retransmit timer
351 dcsp
->sd_csus_rexmt_msg
= csus_msg
;
352 HARP_TIMER(&dcsp
->sd_csus_rexmt_t
,
353 dcsp
->sd_csus_rexmt_int
,
354 scsp_csus_retran_timeout
);
357 * Error--free the CSUS message
359 scsp_free_msg(csus_msg
);
367 * Send a CSU Request message
370 * dcsp pointer to DCS block for DCS
371 * csap pointer to CSAs to include
375 * else errno indicating reason for failure
379 scsp_send_csu_req(Scsp_dcs
*dcsp
, Scsp_csa
*csap
)
382 Scsp_server
*ssp
= dcsp
->sd_server
;
389 * Return if CSA list is empty
395 * Get memory for a CSU Req message
397 csu_msg
= (Scsp_msg
*)UM_ALLOC(sizeof(Scsp_msg
));
399 scsp_mem_err("scsp_send_csu_req: sizeof(Scsp_msg)");
401 csup
= (Scsp_csu_msg
*)UM_ALLOC(sizeof(Scsp_csu_msg
));
403 scsp_mem_err("scsp_send_csu_req: sizeof(Scsp_csu_msg)");
405 UM_ZERO(csu_msg
, sizeof(Scsp_msg
));
406 UM_ZERO(csup
, sizeof(Scsp_csu_msg
));
409 * Get memory for a CSU Req retransmission queue entry
411 rxp
= (Scsp_csu_rexmt
*)UM_ALLOC(sizeof(Scsp_csu_rexmt
));
413 scsp_mem_err("scsp_send_csu_req: sizeof(Scsp_csu_rexmt)");
415 UM_ZERO(rxp
, sizeof(Scsp_csu_rexmt
));
418 * Fill out constant fields
420 csu_msg
->sc_msg_type
= SCSP_CSU_REQ_MSG
;
421 csu_msg
->sc_csu_msg
= csup
;
422 csup
->csu_mcp
.pid
= ssp
->ss_pid
;
423 csup
->csu_mcp
.sgid
= ssp
->ss_sgid
;
424 csup
->csu_mcp
.sid
= ssp
->ss_lsid
;
425 csup
->csu_mcp
.rid
= dcsp
->sd_dcsid
;
428 * Put the CSA list into the message
430 csup
->csu_csa_rec
= csap
;
431 for (cnt_csap
= csap
; cnt_csap
; cnt_csap
= cnt_csap
->next
) {
432 csup
->csu_mcp
.rec_cnt
++;
436 * Send the CSU Request
438 rc
= scsp_send_msg(dcsp
, csu_msg
);
440 scsp_free_msg(csu_msg
);
447 * Save the CSA entries on the CSU Request retransmission
448 * queue and start the retransmission timer
452 HARP_TIMER(&rxp
->sr_t
, dcsp
->sd_csu_rexmt_int
,
453 scsp_csu_req_retran_timeout
);
454 LINK2TAIL(rxp
, Scsp_csu_rexmt
, dcsp
->sd_csu_rexmt
, sr_next
);
461 * Send a CSU Reply message
464 * dcsp pointer to DCS block for DCS
465 * csap pointer to CSAs to include
469 * errno reason for failure
473 scsp_send_csu_reply(Scsp_dcs
*dcsp
, Scsp_csa
*csap
)
476 Scsp_server
*ssp
= dcsp
->sd_server
;
482 * Return if CSA list is empty
488 * Get memory for a CSU Reply message
490 csu_msg
= (Scsp_msg
*)UM_ALLOC(sizeof(Scsp_msg
));
492 scsp_mem_err("scsp_send_csu_reply: sizeof(Scsp_msg)");
494 csup
= (Scsp_csu_msg
*)UM_ALLOC(sizeof(Scsp_csu_msg
));
496 scsp_mem_err("scsp_send_csu_reply: sizeof(Scsp_csu_msg)");
498 UM_ZERO(csu_msg
, sizeof(Scsp_msg
));
499 UM_ZERO(csup
, sizeof(Scsp_csu_msg
));
502 * Fill out constant fields
504 csu_msg
->sc_msg_type
= SCSP_CSU_REPLY_MSG
;
505 csu_msg
->sc_csu_msg
= csup
;
506 csup
->csu_mcp
.pid
= ssp
->ss_pid
;
507 csup
->csu_mcp
.sgid
= ssp
->ss_sgid
;
508 csup
->csu_mcp
.sid
= ssp
->ss_lsid
;
509 csup
->csu_mcp
.rid
= dcsp
->sd_dcsid
;
512 * Put the CSA list into the message. Convert the CSAs into
513 * CSASs by freeing the protocol-specific portion.
515 csup
->csu_csa_rec
= csap
;
516 for (csap1
= csap
; csap1
; csap1
= csap1
->next
) {
517 switch(dcsp
->sd_server
->ss_pid
) {
519 * We currently only support ATMARP
521 case SCSP_PROTO_ATMARP
:
522 if (csap1
->atmarp_data
) {
523 UM_FREE(csap1
->atmarp_data
);
525 (Scsp_atmarp_csa
*)0;
529 csup
->csu_mcp
.rec_cnt
++;
535 rc
= scsp_send_msg(dcsp
, csu_msg
);
536 scsp_free_msg(csu_msg
);
543 * Send a Hello message
546 * dcsp pointer to DCS control block
550 * errno error encountered
554 scsp_send_hello(Scsp_dcs
*dcsp
)
561 * Get memory for a Hello message
563 hello
= (Scsp_msg
*)UM_ALLOC(sizeof(Scsp_msg
));
565 scsp_mem_err("scsp_send_hello: sizeof(Scsp_msg)");
567 UM_ZERO(hello
, sizeof(Scsp_msg
));
568 hp
= (Scsp_hello
*)UM_ALLOC(sizeof(Scsp_hello
));
570 scsp_mem_err("scsp_send_hello: sizeof(Scsp_hello)");
572 UM_ZERO(hp
, sizeof(Scsp_hello
));
575 * Set up the Hello message
577 hello
->sc_msg_type
= SCSP_HELLO_MSG
;
578 hello
->sc_hello
= hp
;
579 hp
->hello_int
= SCSP_HELLO_Interval
;
580 hp
->dead_factor
= SCSP_HELLO_DF
;
581 hp
->family_id
= dcsp
->sd_server
->ss_fid
;
582 hp
->hello_mcp
.pid
= dcsp
->sd_server
->ss_pid
;
583 hp
->hello_mcp
.sgid
= dcsp
->sd_server
->ss_sgid
;
584 hp
->hello_mcp
.flags
= 0;
585 hp
->hello_mcp
.rec_cnt
= 0;
586 hp
->hello_mcp
.sid
= dcsp
->sd_server
->ss_lsid
;
587 hp
->hello_mcp
.rid
= dcsp
->sd_dcsid
;
590 * Send and free the message
592 rc
= scsp_send_msg(dcsp
, hello
);
593 scsp_free_msg(hello
);