Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.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: 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.2 2003/06/17 04:29:52 dillon Exp $
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 /*
64  * Copy CSAS records into a CA record
65  *
66  * Arguments:
67  *      dcsp    pointer to DCS block for DCS
68  *      cap     pointer to CA record for CSASs
69  *
70  *
71  * Returns:
72  *      none
73  *
74  */
75 static void
76 scsp_ca_csas_setup(dcsp, cap)
77         Scsp_dcs        *dcsp;
78         Scsp_ca         *cap;
79 {
80         int             csas_len, len, mtu;
81         Scsp_server     *ssp = dcsp->sd_server;
82         Scsp_cse        *csep, *next_csep;
83         Scsp_csa        *csap;
84
85         /*
86          * Loop through pending CSAS records
87          */
88         len = sizeof(struct scsp_nhdr) + sizeof(struct scsp_nmcp) +
89                         ssp->ss_lsid.id_len +
90                         dcsp->sd_dcsid.id_len;
91         csas_len = sizeof(struct scsp_ncsa) +
92                         dcsp->sd_server->ss_id_len +
93                         dcsp->sd_server->ss_ckey_len;
94         mtu = dcsp->sd_server->ss_mtu;
95         for (csep = dcsp->sd_ca_csas;
96                         csep && (len < mtu - csas_len);
97                         csep = next_csep) {
98                 next_csep = csep->sc_next;
99                 csap = scsp_cse2csas(csep);
100                 LINK2TAIL(csap, Scsp_csa, cap->ca_csa_rec, next);
101                 len += csas_len;
102                 UNLINK(csep, Scsp_cse, dcsp->sd_ca_csas, sc_next);
103                 UM_FREE(csep);
104                 cap->ca_mcp.rec_cnt++;
105         }
106 }
107
108
109 /*
110  * Process CSA records from a CSU Request that may be in response to
111  * CSAS records sent in a CSUS
112  *
113  * Arguments:
114  *      dcsp    pointer to DCS control block
115  *      msg     pointer to received message
116  *
117  * Returns:
118  *      none
119  *
120  */
121 void
122 scsp_csus_ack(dcsp, msg)
123         Scsp_dcs        *dcsp;
124         Scsp_msg        *msg;
125 {
126         Scsp_csu_msg    *csusp;
127         Scsp_csa        *csap, *csasp, *next_csasp;
128
129         /*
130          * If this isn't a CSU Request, or there's no outstanding CSUS,
131          * or the outstanding CSUS has already been satisfied, just
132          * return
133          */
134         if (!msg || msg->sc_msg_type != SCSP_CSU_REQ_MSG ||
135                         !dcsp->sd_csus_rexmt_msg ||
136                         !dcsp->sd_csus_rexmt_msg->sc_csu_msg ||
137                         !dcsp->sd_csus_rexmt_msg->sc_csu_msg->csu_csa_rec)
138                 return;
139
140
141         /*
142          * Loop through the CSASs in the CSUS message, checking for
143          * each in the CSA records of the received CSU Request
144          */
145         csusp = dcsp->sd_csus_rexmt_msg->sc_csu_msg;
146         for (csasp = csusp->csu_csa_rec; csasp; csasp = next_csasp) {
147                 next_csasp = csasp->next;
148                 for (csap = msg->sc_csu_msg->csu_csa_rec;
149                                 csap; csap = csap->next) {
150                         /*
151                          * If the records match, unlink and free the
152                          * CSAS from the CSUS
153                          */
154                         if (scsp_cmp_key(&csap->key, &csasp->key) == 0 &&
155                                         scsp_cmp_key(&csap->key, &csasp->key) == 0 &&
156                                         scsp_cmp_id(&csap->oid, &csasp->oid) == 0 &&
157                                         csap->seq >= csasp->seq) {
158                                 UNLINK(csasp, Scsp_csa,
159                                                 csusp->csu_csa_rec,
160                                                 next);
161                                 SCSP_FREE_CSA(csasp);
162                                 dcsp->sd_csus_rexmt_msg->sc_csu_msg->csu_mcp.rec_cnt--;
163                                 break;
164                         }
165                 }
166         }
167
168         if (csusp->csu_csa_rec == (Scsp_csa *)0) {
169                 /*
170                  * All CSASs in the CSUS message have been
171                  * answered.  Stop the timer and free the
172                  * saved message.
173                  */
174                 HARP_CANCEL(&dcsp->sd_csus_rexmt_t);
175                 scsp_free_msg(dcsp->sd_csus_rexmt_msg);
176                 dcsp->sd_csus_rexmt_msg = (Scsp_msg *)0;
177
178                 /*
179                  * If the CRL isn't empty, send another CSUS
180                  */
181                 if (dcsp->sd_crl) {
182                         (void)scsp_send_csus(dcsp);
183                 }
184         }
185 }
186
187
188 /*
189  * Send a CA message
190  *
191  * Arguments:
192  *      dcsp    pointer to DCS block for DCS
193  *
194  * Returns:
195  *      0       message sent OK
196  *      else    errno indicating reason for failure
197  *
198  */
199 int
200 scsp_send_ca(dcsp)
201         Scsp_dcs        *dcsp;
202 {
203         int             rc;
204         Scsp_msg        *ca_msg;
205         Scsp_ca         *cap;
206         Scsp_server     *ssp = dcsp->sd_server;
207
208         /*
209          * Get memory for a CA message
210          */
211         ca_msg = (Scsp_msg *)UM_ALLOC(sizeof(Scsp_msg));
212         if (!ca_msg) {
213                 scsp_mem_err("scsp_send_ca: sizeof(Scsp_msg)");
214         }
215         cap = (Scsp_ca *)UM_ALLOC(sizeof(Scsp_ca));
216         if (!cap) {
217                 scsp_mem_err("scsp_send_ca: sizeof(Scsp_ca)");
218         }
219         UM_ZERO(ca_msg, sizeof(Scsp_msg));
220         UM_ZERO(cap, sizeof(Scsp_ca));
221
222         /*
223          * Fill out constant fields
224          */
225         ca_msg->sc_msg_type = SCSP_CA_MSG;
226         ca_msg->sc_ca = cap;
227         cap->ca_seq = dcsp->sd_ca_seq;
228         cap->ca_mcp.pid = ssp->ss_pid;
229         cap->ca_mcp.sgid = ssp->ss_sgid;
230         cap->ca_mcp.sid = ssp->ss_lsid;
231         cap->ca_mcp.rid = dcsp->sd_dcsid;
232
233         /*
234          * Fill out state-dependent fields
235          */
236         switch(dcsp->sd_ca_state) {
237         case SCSP_CAFSM_NEG:
238                 cap->ca_m = 1;
239                 cap->ca_i = 1;
240                 cap->ca_o = 1;
241                 break;
242         case SCSP_CAFSM_MASTER:
243                 cap->ca_m = 1;
244                 cap->ca_i = 0;
245                 scsp_ca_csas_setup(dcsp, cap);
246                 cap->ca_o = dcsp->sd_ca_csas != (Scsp_cse *)0;
247                 break;
248         case SCSP_CAFSM_SLAVE:
249                 cap->ca_m = 0;
250                 cap->ca_i = 0;
251                 scsp_ca_csas_setup(dcsp, cap);
252                 cap->ca_o = dcsp->sd_ca_csas != (Scsp_cse *)0;
253                 break;
254         default:
255                 scsp_log(LOG_ERR, "Invalid state in scsp_send_ca");
256                 abort();
257         }
258
259         /*
260          * Send the CA message and save a pointer to it in case
261          * it needs to be retransmitted
262          */
263         rc = scsp_send_msg(dcsp, ca_msg);
264         if (rc == 0) {
265                 dcsp->sd_ca_rexmt_msg = ca_msg;
266         } else {
267                 scsp_free_msg(ca_msg);
268         }
269
270         return(rc);
271 }
272
273
274 /*
275  * Send a CSU Solicit message
276  *
277  * Arguments:
278  *      dcsp    pointer to DCS block for DCS
279  *
280  * Returns:
281  *      0       message sent OK
282  *      else    errno indicating reason for failure
283  *
284  */
285 int
286 scsp_send_csus(dcsp)
287         Scsp_dcs        *dcsp;
288 {
289         int             csas_len, len, mtu, rc;
290         Scsp_msg        *csus_msg;
291         Scsp_csu_msg    *csusp;
292         Scsp_csa        *csasp, *next_csasp;
293         Scsp_server     *ssp = dcsp->sd_server;
294
295         /*
296          * If we have a mesage saved for retransmission, use it.
297          * If not, get memory for a new one.
298          */
299         if (dcsp->sd_csus_rexmt_msg) {
300                 csus_msg = dcsp->sd_csus_rexmt_msg;
301                 csusp = csus_msg->sc_csu_msg;
302         } else {
303                 /*
304                  * Get memory for a CSUS message
305                  */
306                 csus_msg = (Scsp_msg *)UM_ALLOC(sizeof(Scsp_msg));
307                 if (!csus_msg) {
308                         scsp_mem_err("scsp_send_csus: sizeof(Scsp_msg)");
309                 }
310                 csusp = (Scsp_csu_msg *)UM_ALLOC(sizeof(Scsp_csu_msg));
311                 if (!csusp) {
312                         scsp_mem_err("scsp_send_csus: sizeof(Scsp_csu_msg)");
313                 }
314                 UM_ZERO(csus_msg, sizeof(Scsp_msg));
315                 UM_ZERO(csusp, sizeof(Scsp_csu_msg));
316
317                 /*
318                  * Fill out constant fields
319                  */
320                 csus_msg->sc_msg_type = SCSP_CSUS_MSG;
321                 csus_msg->sc_csu_msg = csusp;
322                 csusp->csu_mcp.pid = ssp->ss_pid;
323                 csusp->csu_mcp.sgid = ssp->ss_sgid;
324                 csusp->csu_mcp.sid = ssp->ss_lsid;
325                 csusp->csu_mcp.rid = dcsp->sd_dcsid;
326         }
327
328         /*
329          * Move CSAS records from CRL into message
330          */
331         mtu = dcsp->sd_server->ss_mtu;
332         csas_len = sizeof(struct scsp_ncsa) + ssp->ss_id_len +
333                         ssp->ss_ckey_len;
334         len = sizeof(struct scsp_nhdr) + sizeof(struct scsp_nmcp) +
335                         2 * ssp->ss_id_len +
336                         csas_len * (csusp->csu_mcp.rec_cnt + 1);
337         for (csasp = dcsp->sd_crl;
338                         csasp && ((len + csas_len) < mtu);
339                         csasp = next_csasp, len += csas_len) {
340                 next_csasp = csasp->next;
341                 csusp->csu_mcp.rec_cnt++;
342                 UNLINK(csasp, Scsp_csa, dcsp->sd_crl, next);
343                 LINK2TAIL(csasp, Scsp_csa, csusp->csu_csa_rec, next);
344                 csasp->hops = 1;
345         }
346
347         /*
348          * Send the CSUS message and save a pointer to it in case
349          * it needs to be retransmitted
350          */
351         rc = scsp_send_msg(dcsp, csus_msg);
352         if (rc == 0) {
353                 /*
354                  * Success--Save a pointer to the message and
355                  * start the CSUS retransmit timer
356                  */
357                 dcsp->sd_csus_rexmt_msg = csus_msg;
358                 HARP_TIMER(&dcsp->sd_csus_rexmt_t,
359                                 dcsp->sd_csus_rexmt_int,
360                                 scsp_csus_retran_timeout);
361         } else {
362                 /*
363                  * Error--free the CSUS message
364                  */
365                 scsp_free_msg(csus_msg);
366         }
367
368         return(rc);
369 }
370
371
372 /*
373  * Send a CSU Request message
374  *
375  * Arguments:
376  *      dcsp    pointer to DCS block for DCS
377  *      csap    pointer to CSAs to include
378  *
379  * Returns:
380  *      0       message sent OK
381  *      else    errno indicating reason for failure
382  *
383  */
384 int
385 scsp_send_csu_req(dcsp, csap)
386         Scsp_dcs        *dcsp;
387         Scsp_csa        *csap;
388 {
389         int             rc;
390         Scsp_server     *ssp = dcsp->sd_server;
391         Scsp_csa        *cnt_csap;
392         Scsp_msg        *csu_msg;
393         Scsp_csu_msg    *csup;
394         Scsp_csu_rexmt  *rxp;
395
396         /*
397          * Return if CSA list is empty
398          */
399         if (!csap)
400                 return(0);
401
402         /*
403          * Get memory for a CSU Req message
404          */
405         csu_msg = (Scsp_msg *)UM_ALLOC(sizeof(Scsp_msg));
406         if (!csu_msg) {
407                 scsp_mem_err("scsp_send_csu_req: sizeof(Scsp_msg)");
408         }
409         csup = (Scsp_csu_msg *)UM_ALLOC(sizeof(Scsp_csu_msg));
410         if (!csup) {
411                 scsp_mem_err("scsp_send_csu_req: sizeof(Scsp_csu_msg)");
412         }
413         UM_ZERO(csu_msg, sizeof(Scsp_msg));
414         UM_ZERO(csup, sizeof(Scsp_csu_msg));
415
416         /*
417          * Get memory for a CSU Req retransmission queue entry
418          */
419         rxp = (Scsp_csu_rexmt *)UM_ALLOC(sizeof(Scsp_csu_rexmt));
420         if (!rxp) {
421                 scsp_mem_err("scsp_send_csu_req: sizeof(Scsp_csu_rexmt)");
422         }
423         UM_ZERO(rxp, sizeof(Scsp_csu_rexmt));
424
425         /*
426          * Fill out constant fields
427          */
428         csu_msg->sc_msg_type = SCSP_CSU_REQ_MSG;
429         csu_msg->sc_csu_msg = csup;
430         csup->csu_mcp.pid = ssp->ss_pid;
431         csup->csu_mcp.sgid = ssp->ss_sgid;
432         csup->csu_mcp.sid = ssp->ss_lsid;
433         csup->csu_mcp.rid = dcsp->sd_dcsid;
434
435         /*
436          * Put the CSA list into the message
437          */
438         csup->csu_csa_rec = csap;
439         for (cnt_csap = csap; cnt_csap; cnt_csap = cnt_csap->next) {
440                 csup->csu_mcp.rec_cnt++;
441         }
442
443         /*
444          * Send the CSU Request
445          */
446         rc = scsp_send_msg(dcsp, csu_msg);
447         if (rc) {
448                 scsp_free_msg(csu_msg);
449                 return(rc);
450         }
451         UM_FREE(csu_msg);
452         UM_FREE(csup);
453
454         /*
455          * Save the CSA entries on the CSU Request retransmission
456          * queue and start the retransmission timer
457          */
458         rxp->sr_dcs = dcsp;
459         rxp->sr_csa = csap;
460         HARP_TIMER(&rxp->sr_t, dcsp->sd_csu_rexmt_int,
461                         scsp_csu_req_retran_timeout);
462         LINK2TAIL(rxp, Scsp_csu_rexmt, dcsp->sd_csu_rexmt, sr_next);
463
464         return(0);
465 }
466
467
468 /*
469  * Send a CSU Reply message
470  *
471  * Arguments:
472  *      dcsp    pointer to DCS block for DCS
473  *      csap    pointer to CSAs to include
474  *
475  * Returns:
476  *      0       message sent OK
477  *      errno   reason for failure
478  *
479  */
480 int
481 scsp_send_csu_reply(dcsp, csap)
482         Scsp_dcs        *dcsp;
483         Scsp_csa        *csap;
484 {
485         int             rc;
486         Scsp_server     *ssp = dcsp->sd_server;
487         Scsp_csa        *csap1;
488         Scsp_msg        *csu_msg;
489         Scsp_csu_msg    *csup;
490
491         /*
492          * Return if CSA list is empty
493          */
494         if (!csap)
495                 return(0);
496
497         /*
498          * Get memory for a CSU Reply message
499          */
500         csu_msg = (Scsp_msg *)UM_ALLOC(sizeof(Scsp_msg));
501         if (!csu_msg) {
502                 scsp_mem_err("scsp_send_csu_reply: sizeof(Scsp_msg)");
503         }
504         csup = (Scsp_csu_msg *)UM_ALLOC(sizeof(Scsp_csu_msg));
505         if (!csup) {
506                 scsp_mem_err("scsp_send_csu_reply: sizeof(Scsp_csu_msg)");
507         }
508         UM_ZERO(csu_msg, sizeof(Scsp_msg));
509         UM_ZERO(csup, sizeof(Scsp_csu_msg));
510
511         /*
512          * Fill out constant fields
513          */
514         csu_msg->sc_msg_type = SCSP_CSU_REPLY_MSG;
515         csu_msg->sc_csu_msg = csup;
516         csup->csu_mcp.pid = ssp->ss_pid;
517         csup->csu_mcp.sgid = ssp->ss_sgid;
518         csup->csu_mcp.sid = ssp->ss_lsid;
519         csup->csu_mcp.rid = dcsp->sd_dcsid;
520
521         /*
522          * Put the CSA list into the message.  Convert the CSAs into
523          * CSASs by freeing the protocol-specific portion.
524          */
525         csup->csu_csa_rec = csap;
526         for (csap1 = csap; csap1; csap1 = csap1->next) {
527                 switch(dcsp->sd_server->ss_pid) {
528                 /*
529                  * We currently only support ATMARP
530                  */
531                 case SCSP_PROTO_ATMARP:
532                         if (csap1->atmarp_data) {
533                                 UM_FREE(csap1->atmarp_data);
534                                 csap1->atmarp_data =
535                                                 (Scsp_atmarp_csa *)0;
536                         }
537                         break;
538                 }
539                 csup->csu_mcp.rec_cnt++;
540         }
541
542         /*
543          * Send the CSU Reply
544          */
545         rc = scsp_send_msg(dcsp, csu_msg);
546         scsp_free_msg(csu_msg);
547
548         return(rc);
549 }
550
551
552 /*
553  * Send a Hello message
554  *
555  * Arguments:
556  *      dcsp    pointer to DCS control block
557  *
558  * Returns:
559  *      0       success
560  *      errno   error encountered
561  *
562  */
563 int
564 scsp_send_hello(dcsp)
565         Scsp_dcs        *dcsp;
566 {
567         int             rc;
568         Scsp_msg        *hello;
569         Scsp_hello      *hp;
570
571         /*
572          * Get memory for a Hello message
573          */
574         hello = (Scsp_msg *)UM_ALLOC(sizeof(Scsp_msg));
575         if (!hello) {
576                 scsp_mem_err("scsp_send_hello: sizeof(Scsp_msg)");
577         }
578         UM_ZERO(hello, sizeof(Scsp_msg));
579         hp = (Scsp_hello *)UM_ALLOC(sizeof(Scsp_hello));
580         if (!hp) {
581                 scsp_mem_err("scsp_send_hello: sizeof(Scsp_hello)");
582         }
583         UM_ZERO(hp, sizeof(Scsp_hello));
584
585         /*
586          * Set up the Hello message
587          */
588         hello->sc_msg_type = SCSP_HELLO_MSG;
589         hello->sc_hello = hp;
590         hp->hello_int = SCSP_HELLO_Interval;
591         hp->dead_factor = SCSP_HELLO_DF;
592         hp->family_id = dcsp->sd_server->ss_fid;
593         hp->hello_mcp.pid = dcsp->sd_server->ss_pid;
594         hp->hello_mcp.sgid = dcsp->sd_server->ss_sgid;
595         hp->hello_mcp.flags = 0;
596         hp->hello_mcp.rec_cnt = 0;
597         hp->hello_mcp.sid = dcsp->sd_server->ss_lsid;
598         hp->hello_mcp.rid = dcsp->sd_dcsid;
599
600         /*
601          * Send and free the message
602          */
603         rc = scsp_send_msg(dcsp, hello);
604         scsp_free_msg(hello);
605
606         return(rc);
607 }