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.
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 __RCSID("@(#) $FreeBSD$");
69 * Copy CSAS records into a CA record
72 * dcsp pointer to DCS block for DCS
73 * cap pointer to CA record for CSASs
81 scsp_ca_csas_setup(dcsp, cap)
85 int csas_len, len, mtu;
86 Scsp_server *ssp = dcsp->sd_server;
87 Scsp_cse *csep, *next_csep;
91 * Loop through pending CSAS records
93 len = sizeof(struct scsp_nhdr) + sizeof(struct scsp_nmcp) +
95 dcsp->sd_dcsid.id_len;
96 csas_len = sizeof(struct scsp_ncsa) +
97 dcsp->sd_server->ss_id_len +
98 dcsp->sd_server->ss_ckey_len;
99 mtu = dcsp->sd_server->ss_mtu;
100 for (csep = dcsp->sd_ca_csas;
101 csep && (len < mtu - csas_len);
103 next_csep = csep->sc_next;
104 csap = scsp_cse2csas(csep);
105 LINK2TAIL(csap, Scsp_csa, cap->ca_csa_rec, next);
107 UNLINK(csep, Scsp_cse, dcsp->sd_ca_csas, sc_next);
109 cap->ca_mcp.rec_cnt++;
115 * Process CSA records from a CSU Request that may be in response to
116 * CSAS records sent in a CSUS
119 * dcsp pointer to DCS control block
120 * msg pointer to received message
127 scsp_csus_ack(dcsp, msg)
132 Scsp_csa *csap, *csasp, *next_csasp;
135 * If this isn't a CSU Request, or there's no outstanding CSUS,
136 * or the outstanding CSUS has already been satisfied, just
139 if (!msg || msg->sc_msg_type != SCSP_CSU_REQ_MSG ||
140 !dcsp->sd_csus_rexmt_msg ||
141 !dcsp->sd_csus_rexmt_msg->sc_csu_msg ||
142 !dcsp->sd_csus_rexmt_msg->sc_csu_msg->csu_csa_rec)
147 * Loop through the CSASs in the CSUS message, checking for
148 * each in the CSA records of the received CSU Request
150 csusp = dcsp->sd_csus_rexmt_msg->sc_csu_msg;
151 for (csasp = csusp->csu_csa_rec; csasp; csasp = next_csasp) {
152 next_csasp = csasp->next;
153 for (csap = msg->sc_csu_msg->csu_csa_rec;
154 csap; csap = csap->next) {
156 * If the records match, unlink and free the
159 if (scsp_cmp_key(&csap->key, &csasp->key) == 0 &&
160 scsp_cmp_key(&csap->key, &csasp->key) == 0 &&
161 scsp_cmp_id(&csap->oid, &csasp->oid) == 0 &&
162 csap->seq >= csasp->seq) {
163 UNLINK(csasp, Scsp_csa,
166 SCSP_FREE_CSA(csasp);
167 dcsp->sd_csus_rexmt_msg->sc_csu_msg->csu_mcp.rec_cnt--;
173 if (csusp->csu_csa_rec == (Scsp_csa *)0) {
175 * All CSASs in the CSUS message have been
176 * answered. Stop the timer and free the
179 HARP_CANCEL(&dcsp->sd_csus_rexmt_t);
180 scsp_free_msg(dcsp->sd_csus_rexmt_msg);
181 dcsp->sd_csus_rexmt_msg = (Scsp_msg *)0;
184 * If the CRL isn't empty, send another CSUS
187 (void)scsp_send_csus(dcsp);
197 * dcsp pointer to DCS block for DCS
201 * else errno indicating reason for failure
211 Scsp_server *ssp = dcsp->sd_server;
214 * Get memory for a CA message
216 ca_msg = calloc(1, sizeof(Scsp_msg));
218 scsp_mem_err("scsp_send_ca: sizeof(Scsp_msg)");
219 cap = calloc(1, sizeof(Scsp_ca));
221 scsp_mem_err("scsp_send_ca: sizeof(Scsp_ca)");
224 * Fill out constant fields
226 ca_msg->sc_msg_type = SCSP_CA_MSG;
228 cap->ca_seq = dcsp->sd_ca_seq;
229 cap->ca_mcp.pid = ssp->ss_pid;
230 cap->ca_mcp.sgid = ssp->ss_sgid;
231 cap->ca_mcp.sid = ssp->ss_lsid;
232 cap->ca_mcp.rid = dcsp->sd_dcsid;
235 * Fill out state-dependent fields
237 switch(dcsp->sd_ca_state) {
243 case SCSP_CAFSM_MASTER:
246 scsp_ca_csas_setup(dcsp, cap);
247 cap->ca_o = dcsp->sd_ca_csas != (Scsp_cse *)0;
249 case SCSP_CAFSM_SLAVE:
252 scsp_ca_csas_setup(dcsp, cap);
253 cap->ca_o = dcsp->sd_ca_csas != (Scsp_cse *)0;
256 scsp_log(LOG_ERR, "Invalid state in scsp_send_ca");
261 * Send the CA message and save a pointer to it in case
262 * it needs to be retransmitted
264 rc = scsp_send_msg(dcsp, ca_msg);
266 dcsp->sd_ca_rexmt_msg = ca_msg;
268 scsp_free_msg(ca_msg);
276 * Send a CSU Solicit message
279 * dcsp pointer to DCS block for DCS
283 * else errno indicating reason for failure
290 int csas_len, len, mtu, rc;
293 Scsp_csa *csasp, *next_csasp;
294 Scsp_server *ssp = dcsp->sd_server;
297 * If we have a mesage saved for retransmission, use it.
298 * If not, get memory for a new one.
300 if (dcsp->sd_csus_rexmt_msg) {
301 csus_msg = dcsp->sd_csus_rexmt_msg;
302 csusp = csus_msg->sc_csu_msg;
305 * Get memory for a CSUS message
307 csus_msg = calloc(1, sizeof(Scsp_msg));
308 if (csus_msg == NULL)
309 scsp_mem_err("scsp_send_csus: sizeof(Scsp_msg)");
310 csusp = calloc(1, sizeof(Scsp_csu_msg));
312 scsp_mem_err("scsp_send_csus: sizeof(Scsp_csu_msg)");
315 * Fill out constant fields
317 csus_msg->sc_msg_type = SCSP_CSUS_MSG;
318 csus_msg->sc_csu_msg = csusp;
319 csusp->csu_mcp.pid = ssp->ss_pid;
320 csusp->csu_mcp.sgid = ssp->ss_sgid;
321 csusp->csu_mcp.sid = ssp->ss_lsid;
322 csusp->csu_mcp.rid = dcsp->sd_dcsid;
326 * Move CSAS records from CRL into message
328 mtu = dcsp->sd_server->ss_mtu;
329 csas_len = sizeof(struct scsp_ncsa) + ssp->ss_id_len +
331 len = sizeof(struct scsp_nhdr) + sizeof(struct scsp_nmcp) +
333 csas_len * (csusp->csu_mcp.rec_cnt + 1);
334 for (csasp = dcsp->sd_crl;
335 csasp && ((len + csas_len) < mtu);
336 csasp = next_csasp, len += csas_len) {
337 next_csasp = csasp->next;
338 csusp->csu_mcp.rec_cnt++;
339 UNLINK(csasp, Scsp_csa, dcsp->sd_crl, next);
340 LINK2TAIL(csasp, Scsp_csa, csusp->csu_csa_rec, next);
345 * Send the CSUS message and save a pointer to it in case
346 * it needs to be retransmitted
348 rc = scsp_send_msg(dcsp, csus_msg);
351 * Success--Save a pointer to the message and
352 * start the CSUS retransmit timer
354 dcsp->sd_csus_rexmt_msg = csus_msg;
355 HARP_TIMER(&dcsp->sd_csus_rexmt_t,
356 dcsp->sd_csus_rexmt_int,
357 scsp_csus_retran_timeout);
360 * Error--free the CSUS message
362 scsp_free_msg(csus_msg);
370 * Send a CSU Request message
373 * dcsp pointer to DCS block for DCS
374 * csap pointer to CSAs to include
378 * else errno indicating reason for failure
382 scsp_send_csu_req(dcsp, csap)
387 Scsp_server *ssp = dcsp->sd_server;
394 * Return if CSA list is empty
400 * Get memory for a CSU Req message
402 csu_msg = calloc(1, sizeof(Scsp_msg));
404 scsp_mem_err("scsp_send_csu_req: sizeof(Scsp_msg)");
405 csup = calloc(1, sizeof(Scsp_csu_msg));
407 scsp_mem_err("scsp_send_csu_req: sizeof(Scsp_csu_msg)");
410 * Get memory for a CSU Req retransmission queue entry
412 rxp = calloc(1, sizeof(Scsp_csu_rexmt));
414 scsp_mem_err("scsp_send_csu_req: sizeof(Scsp_csu_rexmt)");
417 * Fill out constant fields
419 csu_msg->sc_msg_type = SCSP_CSU_REQ_MSG;
420 csu_msg->sc_csu_msg = csup;
421 csup->csu_mcp.pid = ssp->ss_pid;
422 csup->csu_mcp.sgid = ssp->ss_sgid;
423 csup->csu_mcp.sid = ssp->ss_lsid;
424 csup->csu_mcp.rid = dcsp->sd_dcsid;
427 * Put the CSA list into the message
429 csup->csu_csa_rec = csap;
430 for (cnt_csap = csap; cnt_csap; cnt_csap = cnt_csap->next) {
431 csup->csu_mcp.rec_cnt++;
435 * Send the CSU Request
437 rc = scsp_send_msg(dcsp, csu_msg);
439 scsp_free_msg(csu_msg);
446 * Save the CSA entries on the CSU Request retransmission
447 * queue and start the retransmission timer
451 HARP_TIMER(&rxp->sr_t, dcsp->sd_csu_rexmt_int,
452 scsp_csu_req_retran_timeout);
453 LINK2TAIL(rxp, Scsp_csu_rexmt, dcsp->sd_csu_rexmt, sr_next);
460 * Send a CSU Reply message
463 * dcsp pointer to DCS block for DCS
464 * csap pointer to CSAs to include
468 * errno reason for failure
472 scsp_send_csu_reply(dcsp, csap)
477 Scsp_server *ssp = dcsp->sd_server;
483 * Return if CSA list is empty
489 * Get memory for a CSU Reply message
491 csu_msg = calloc(1, sizeof(Scsp_msg));
493 scsp_mem_err("scsp_send_csu_reply: sizeof(Scsp_msg)");
494 csup = calloc(1, sizeof(Scsp_csu_msg));
496 scsp_mem_err("scsp_send_csu_reply: sizeof(Scsp_csu_msg)");
499 * Fill out constant fields
501 csu_msg->sc_msg_type = SCSP_CSU_REPLY_MSG;
502 csu_msg->sc_csu_msg = csup;
503 csup->csu_mcp.pid = ssp->ss_pid;
504 csup->csu_mcp.sgid = ssp->ss_sgid;
505 csup->csu_mcp.sid = ssp->ss_lsid;
506 csup->csu_mcp.rid = dcsp->sd_dcsid;
509 * Put the CSA list into the message. Convert the CSAs into
510 * CSASs by freeing the protocol-specific portion.
512 csup->csu_csa_rec = csap;
513 for (csap1 = csap; csap1; csap1 = csap1->next) {
514 switch(dcsp->sd_server->ss_pid) {
516 * We currently only support ATMARP
518 case SCSP_PROTO_ATMARP:
519 if (csap1->atmarp_data) {
520 free(csap1->atmarp_data);
522 (Scsp_atmarp_csa *)0;
526 csup->csu_mcp.rec_cnt++;
532 rc = scsp_send_msg(dcsp, csu_msg);
533 scsp_free_msg(csu_msg);
540 * Send a Hello message
543 * dcsp pointer to DCS control block
547 * errno error encountered
551 scsp_send_hello(dcsp)
559 * Get memory for a Hello message
561 hello = calloc(1, sizeof(Scsp_msg));
563 scsp_mem_err("scsp_send_hello: sizeof(Scsp_msg)");
564 hp = calloc(1, sizeof(Scsp_hello));
566 scsp_mem_err("scsp_send_hello: sizeof(Scsp_hello)");
569 * Set up the Hello message
571 hello->sc_msg_type = SCSP_HELLO_MSG;
572 hello->sc_hello = hp;
573 hp->hello_int = SCSP_HELLO_Interval;
574 hp->dead_factor = SCSP_HELLO_DF;
575 hp->family_id = dcsp->sd_server->ss_fid;
576 hp->hello_mcp.pid = dcsp->sd_server->ss_pid;
577 hp->hello_mcp.sgid = dcsp->sd_server->ss_sgid;
578 hp->hello_mcp.flags = 0;
579 hp->hello_mcp.rec_cnt = 0;
580 hp->hello_mcp.sid = dcsp->sd_server->ss_lsid;
581 hp->hello_mcp.rid = dcsp->sd_dcsid;
584 * Send and free the message
586 rc = scsp_send_msg(dcsp, hello);
587 scsp_free_msg(hello);