]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/atm/scspd/scsp_msg.c
This commit was generated by cvs2svn to compensate for changes in r161655,
[FreeBSD/FreeBSD.git] / usr.sbin / atm / scspd / scsp_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$
27  *
28  */
29
30
31 /*
32  * Server Cache Synchronization Protocol (SCSP) Support
33  * ----------------------------------------------------
34  *
35  * SCSP message-handling routines
36  *
37  */
38
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <sys/socket.h>
42 #include <net/if.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>
51   
52 #include <errno.h>
53 #include <libatm.h>
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #include <syslog.h>
58
59 #include "scsp_msg.h"
60 #include "scsp_if.h"
61 #include "scsp_var.h"
62
63 #ifndef lint
64 __RCSID("@(#) $FreeBSD$");
65 #endif
66
67
68 /*
69  * Copy CSAS records into a CA record
70  *
71  * Arguments:
72  *      dcsp    pointer to DCS block for DCS
73  *      cap     pointer to CA record for CSASs
74  *
75  *
76  * Returns:
77  *      none
78  *
79  */
80 static void
81 scsp_ca_csas_setup(dcsp, cap)
82         Scsp_dcs        *dcsp;
83         Scsp_ca         *cap;
84 {
85         int             csas_len, len, mtu;
86         Scsp_server     *ssp = dcsp->sd_server;
87         Scsp_cse        *csep, *next_csep;
88         Scsp_csa        *csap;
89
90         /*
91          * Loop through pending CSAS records
92          */
93         len = sizeof(struct scsp_nhdr) + sizeof(struct scsp_nmcp) +
94                         ssp->ss_lsid.id_len +
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);
102                         csep = next_csep) {
103                 next_csep = csep->sc_next;
104                 csap = scsp_cse2csas(csep);
105                 LINK2TAIL(csap, Scsp_csa, cap->ca_csa_rec, next);
106                 len += csas_len;
107                 UNLINK(csep, Scsp_cse, dcsp->sd_ca_csas, sc_next);
108                 free(csep);
109                 cap->ca_mcp.rec_cnt++;
110         }
111 }
112
113
114 /*
115  * Process CSA records from a CSU Request that may be in response to
116  * CSAS records sent in a CSUS
117  *
118  * Arguments:
119  *      dcsp    pointer to DCS control block
120  *      msg     pointer to received message
121  *
122  * Returns:
123  *      none
124  *
125  */
126 void
127 scsp_csus_ack(dcsp, msg)
128         Scsp_dcs        *dcsp;
129         Scsp_msg        *msg;
130 {
131         Scsp_csu_msg    *csusp;
132         Scsp_csa        *csap, *csasp, *next_csasp;
133
134         /*
135          * If this isn't a CSU Request, or there's no outstanding CSUS,
136          * or the outstanding CSUS has already been satisfied, just
137          * return
138          */
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)
143                 return;
144
145
146         /*
147          * Loop through the CSASs in the CSUS message, checking for
148          * each in the CSA records of the received CSU Request
149          */
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) {
155                         /*
156                          * If the records match, unlink and free the
157                          * CSAS from the CSUS
158                          */
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,
164                                                 csusp->csu_csa_rec,
165                                                 next);
166                                 SCSP_FREE_CSA(csasp);
167                                 dcsp->sd_csus_rexmt_msg->sc_csu_msg->csu_mcp.rec_cnt--;
168                                 break;
169                         }
170                 }
171         }
172
173         if (csusp->csu_csa_rec == (Scsp_csa *)0) {
174                 /*
175                  * All CSASs in the CSUS message have been
176                  * answered.  Stop the timer and free the
177                  * saved message.
178                  */
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;
182
183                 /*
184                  * If the CRL isn't empty, send another CSUS
185                  */
186                 if (dcsp->sd_crl) {
187                         (void)scsp_send_csus(dcsp);
188                 }
189         }
190 }
191
192
193 /*
194  * Send a CA message
195  *
196  * Arguments:
197  *      dcsp    pointer to DCS block for DCS
198  *
199  * Returns:
200  *      0       message sent OK
201  *      else    errno indicating reason for failure
202  *
203  */
204 int
205 scsp_send_ca(dcsp)
206         Scsp_dcs        *dcsp;
207 {
208         int             rc;
209         Scsp_msg        *ca_msg;
210         Scsp_ca         *cap;
211         Scsp_server     *ssp = dcsp->sd_server;
212
213         /*
214          * Get memory for a CA message
215          */
216         ca_msg = calloc(1, sizeof(Scsp_msg));
217         if (ca_msg == NULL)
218                 scsp_mem_err("scsp_send_ca: sizeof(Scsp_msg)");
219         cap = calloc(1, sizeof(Scsp_ca));
220         if (cap == NULL)
221                 scsp_mem_err("scsp_send_ca: sizeof(Scsp_ca)");
222
223         /*
224          * Fill out constant fields
225          */
226         ca_msg->sc_msg_type = SCSP_CA_MSG;
227         ca_msg->sc_ca = cap;
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;
233
234         /*
235          * Fill out state-dependent fields
236          */
237         switch(dcsp->sd_ca_state) {
238         case SCSP_CAFSM_NEG:
239                 cap->ca_m = 1;
240                 cap->ca_i = 1;
241                 cap->ca_o = 1;
242                 break;
243         case SCSP_CAFSM_MASTER:
244                 cap->ca_m = 1;
245                 cap->ca_i = 0;
246                 scsp_ca_csas_setup(dcsp, cap);
247                 cap->ca_o = dcsp->sd_ca_csas != (Scsp_cse *)0;
248                 break;
249         case SCSP_CAFSM_SLAVE:
250                 cap->ca_m = 0;
251                 cap->ca_i = 0;
252                 scsp_ca_csas_setup(dcsp, cap);
253                 cap->ca_o = dcsp->sd_ca_csas != (Scsp_cse *)0;
254                 break;
255         default:
256                 scsp_log(LOG_ERR, "Invalid state in scsp_send_ca");
257                 abort();
258         }
259
260         /*
261          * Send the CA message and save a pointer to it in case
262          * it needs to be retransmitted
263          */
264         rc = scsp_send_msg(dcsp, ca_msg);
265         if (rc == 0) {
266                 dcsp->sd_ca_rexmt_msg = ca_msg;
267         } else {
268                 scsp_free_msg(ca_msg);
269         }
270
271         return(rc);
272 }
273
274
275 /*
276  * Send a CSU Solicit message
277  *
278  * Arguments:
279  *      dcsp    pointer to DCS block for DCS
280  *
281  * Returns:
282  *      0       message sent OK
283  *      else    errno indicating reason for failure
284  *
285  */
286 int
287 scsp_send_csus(dcsp)
288         Scsp_dcs        *dcsp;
289 {
290         int             csas_len, len, mtu, rc;
291         Scsp_msg        *csus_msg;
292         Scsp_csu_msg    *csusp;
293         Scsp_csa        *csasp, *next_csasp;
294         Scsp_server     *ssp = dcsp->sd_server;
295
296         /*
297          * If we have a mesage saved for retransmission, use it.
298          * If not, get memory for a new one.
299          */
300         if (dcsp->sd_csus_rexmt_msg) {
301                 csus_msg = dcsp->sd_csus_rexmt_msg;
302                 csusp = csus_msg->sc_csu_msg;
303         } else {
304                 /*
305                  * Get memory for a CSUS message
306                  */
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));
311                 if (csusp == NULL)
312                         scsp_mem_err("scsp_send_csus: sizeof(Scsp_csu_msg)");
313
314                 /*
315                  * Fill out constant fields
316                  */
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;
323         }
324
325         /*
326          * Move CSAS records from CRL into message
327          */
328         mtu = dcsp->sd_server->ss_mtu;
329         csas_len = sizeof(struct scsp_ncsa) + ssp->ss_id_len +
330                         ssp->ss_ckey_len;
331         len = sizeof(struct scsp_nhdr) + sizeof(struct scsp_nmcp) +
332                         2 * ssp->ss_id_len +
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);
341                 csasp->hops = 1;
342         }
343
344         /*
345          * Send the CSUS message and save a pointer to it in case
346          * it needs to be retransmitted
347          */
348         rc = scsp_send_msg(dcsp, csus_msg);
349         if (rc == 0) {
350                 /*
351                  * Success--Save a pointer to the message and
352                  * start the CSUS retransmit timer
353                  */
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);
358         } else {
359                 /*
360                  * Error--free the CSUS message
361                  */
362                 scsp_free_msg(csus_msg);
363         }
364
365         return(rc);
366 }
367
368
369 /*
370  * Send a CSU Request message
371  *
372  * Arguments:
373  *      dcsp    pointer to DCS block for DCS
374  *      csap    pointer to CSAs to include
375  *
376  * Returns:
377  *      0       message sent OK
378  *      else    errno indicating reason for failure
379  *
380  */
381 int
382 scsp_send_csu_req(dcsp, csap)
383         Scsp_dcs        *dcsp;
384         Scsp_csa        *csap;
385 {
386         int             rc;
387         Scsp_server     *ssp = dcsp->sd_server;
388         Scsp_csa        *cnt_csap;
389         Scsp_msg        *csu_msg;
390         Scsp_csu_msg    *csup;
391         Scsp_csu_rexmt  *rxp;
392
393         /*
394          * Return if CSA list is empty
395          */
396         if (!csap)
397                 return(0);
398
399         /*
400          * Get memory for a CSU Req message
401          */
402         csu_msg = calloc(1, sizeof(Scsp_msg));
403         if (csu_msg == NULL)
404                 scsp_mem_err("scsp_send_csu_req: sizeof(Scsp_msg)");
405         csup = calloc(1, sizeof(Scsp_csu_msg));
406         if (csup == NULL)
407                 scsp_mem_err("scsp_send_csu_req: sizeof(Scsp_csu_msg)");
408
409         /*
410          * Get memory for a CSU Req retransmission queue entry
411          */
412         rxp = calloc(1, sizeof(Scsp_csu_rexmt));
413         if (rxp == NULL)
414                 scsp_mem_err("scsp_send_csu_req: sizeof(Scsp_csu_rexmt)");
415
416         /*
417          * Fill out constant fields
418          */
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;
425
426         /*
427          * Put the CSA list into the message
428          */
429         csup->csu_csa_rec = csap;
430         for (cnt_csap = csap; cnt_csap; cnt_csap = cnt_csap->next) {
431                 csup->csu_mcp.rec_cnt++;
432         }
433
434         /*
435          * Send the CSU Request
436          */
437         rc = scsp_send_msg(dcsp, csu_msg);
438         if (rc) {
439                 scsp_free_msg(csu_msg);
440                 return(rc);
441         }
442         free(csu_msg);
443         free(csup);
444
445         /*
446          * Save the CSA entries on the CSU Request retransmission
447          * queue and start the retransmission timer
448          */
449         rxp->sr_dcs = dcsp;
450         rxp->sr_csa = csap;
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);
454
455         return(0);
456 }
457
458
459 /*
460  * Send a CSU Reply message
461  *
462  * Arguments:
463  *      dcsp    pointer to DCS block for DCS
464  *      csap    pointer to CSAs to include
465  *
466  * Returns:
467  *      0       message sent OK
468  *      errno   reason for failure
469  *
470  */
471 int
472 scsp_send_csu_reply(dcsp, csap)
473         Scsp_dcs        *dcsp;
474         Scsp_csa        *csap;
475 {
476         int             rc;
477         Scsp_server     *ssp = dcsp->sd_server;
478         Scsp_csa        *csap1;
479         Scsp_msg        *csu_msg;
480         Scsp_csu_msg    *csup;
481
482         /*
483          * Return if CSA list is empty
484          */
485         if (!csap)
486                 return(0);
487
488         /*
489          * Get memory for a CSU Reply message
490          */
491         csu_msg = calloc(1, sizeof(Scsp_msg));
492         if (csu_msg == NULL)
493                 scsp_mem_err("scsp_send_csu_reply: sizeof(Scsp_msg)");
494         csup = calloc(1, sizeof(Scsp_csu_msg));
495         if (csup == NULL)
496                 scsp_mem_err("scsp_send_csu_reply: sizeof(Scsp_csu_msg)");
497
498         /*
499          * Fill out constant fields
500          */
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;
507
508         /*
509          * Put the CSA list into the message.  Convert the CSAs into
510          * CSASs by freeing the protocol-specific portion.
511          */
512         csup->csu_csa_rec = csap;
513         for (csap1 = csap; csap1; csap1 = csap1->next) {
514                 switch(dcsp->sd_server->ss_pid) {
515                 /*
516                  * We currently only support ATMARP
517                  */
518                 case SCSP_PROTO_ATMARP:
519                         if (csap1->atmarp_data) {
520                                 free(csap1->atmarp_data);
521                                 csap1->atmarp_data =
522                                                 (Scsp_atmarp_csa *)0;
523                         }
524                         break;
525                 }
526                 csup->csu_mcp.rec_cnt++;
527         }
528
529         /*
530          * Send the CSU Reply
531          */
532         rc = scsp_send_msg(dcsp, csu_msg);
533         scsp_free_msg(csu_msg);
534
535         return(rc);
536 }
537
538
539 /*
540  * Send a Hello message
541  *
542  * Arguments:
543  *      dcsp    pointer to DCS control block
544  *
545  * Returns:
546  *      0       success
547  *      errno   error encountered
548  *
549  */
550 int
551 scsp_send_hello(dcsp)
552         Scsp_dcs        *dcsp;
553 {
554         int             rc;
555         Scsp_msg        *hello;
556         Scsp_hello      *hp;
557
558         /*
559          * Get memory for a Hello message
560          */
561         hello = calloc(1, sizeof(Scsp_msg));
562         if (hello == NULL)
563                 scsp_mem_err("scsp_send_hello: sizeof(Scsp_msg)");
564         hp = calloc(1, sizeof(Scsp_hello));
565         if (hp == NULL)
566                 scsp_mem_err("scsp_send_hello: sizeof(Scsp_hello)");
567
568         /*
569          * Set up the Hello message
570          */
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;
582
583         /*
584          * Send and free the message
585          */
586         rc = scsp_send_msg(dcsp, hello);
587         scsp_free_msg(hello);
588
589         return(rc);
590 }