Initial import from FreeBSD RELENG_4:
[games.git] / usr.sbin / atm / scspd / scsp_if.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_if.c,v 1.3 1999/08/28 01:15:33 peter Exp $
27  *
28  */
29
30
31 /*
32  * Server Cache Synchronization Protocol (SCSP) Support
33  * ----------------------------------------------------
34  *
35  * Interface to client server protocol
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 #include <unistd.h>
59
60 #include "scsp_msg.h"
61 #include "scsp_if.h"
62 #include "scsp_var.h"
63
64 #ifndef lint
65 __RCSID("@(#) $FreeBSD: src/usr.sbin/atm/scspd/scsp_if.c,v 1.3 1999/08/28 01:15:33 peter Exp $");
66 #endif
67
68
69 /*
70  * SCSP client server interface FSM actions
71  */
72 #define SCSP_CIFSM_ACTION_CNT   11
73 int     scsp_client_act_00
74                         __P((Scsp_dcs *, Scsp_msg *, Scsp_if_msg *));
75 int     scsp_client_act_01
76                         __P((Scsp_dcs *, Scsp_msg *, Scsp_if_msg *));
77 int     scsp_client_act_02
78                         __P((Scsp_dcs *, Scsp_msg *, Scsp_if_msg *));
79 int     scsp_client_act_03
80                         __P((Scsp_dcs *, Scsp_msg *, Scsp_if_msg *));
81 int     scsp_client_act_04
82                         __P((Scsp_dcs *, Scsp_msg *, Scsp_if_msg *));
83 int     scsp_client_act_05
84                         __P((Scsp_dcs *, Scsp_msg *, Scsp_if_msg *));
85 int     scsp_client_act_06
86                         __P((Scsp_dcs *, Scsp_msg *, Scsp_if_msg *));
87 int     scsp_client_act_07
88                         __P((Scsp_dcs *, Scsp_msg *, Scsp_if_msg *));
89 int     scsp_client_act_08
90                         __P((Scsp_dcs *, Scsp_msg *, Scsp_if_msg *));
91 int     scsp_client_act_09
92                         __P((Scsp_dcs *, Scsp_msg *, Scsp_if_msg *));
93 int     scsp_client_act_10
94                         __P((Scsp_dcs *, Scsp_msg *, Scsp_if_msg *));
95
96 static int (*scsp_action_vector[SCSP_CIFSM_ACTION_CNT])() = {
97         scsp_client_act_00,
98         scsp_client_act_01,
99         scsp_client_act_02,
100         scsp_client_act_03,
101         scsp_client_act_04,
102         scsp_client_act_05,
103         scsp_client_act_06,
104         scsp_client_act_07,
105         scsp_client_act_08,
106         scsp_client_act_09,
107         scsp_client_act_10
108 };
109
110
111 /*
112  * Client server interface FSM state table
113  */
114 static int client_state_table[SCSP_CIFSM_EVENT_CNT][SCSP_CIFSM_STATE_CNT] = {
115         /* 0   1   2   3  */
116         {  1,  3,  3,  3 },     /*  0 */
117         {  2,  5,  5,  5 },     /*  1 */
118         {  0,  4,  0,  0 },     /*  2 */
119         {  0,  6,  6,  1 },     /*  3 */
120         {  1,  0,  7,  7 },     /*  4 */
121         {  7,  7,  7,  7 },     /*  5 */
122         {  1,  1,  8,  8 },     /*  6 */
123         {  0,  0, 10, 10 },     /*  7 */
124         {  0,  0,  1,  1 },     /*  8 */
125         {  0,  0,  9,  9 }      /*  9 */
126 };
127
128
129 /*
130  * SCSP client server interface finite state machine
131  *
132  * Arguments:
133  *      ssp     pointer to server control block
134  *      event   the event which has occurred
135  *      msg     pointer to message from DCS, if there is one
136  *      cmsg    pointer to message from server, if there is one
137  *
138  * Returns:
139  *      0       success
140  *      errno   error encountered
141  *
142  */
143 int
144 scsp_cfsm(dcsp, event, msg, cmsg)
145         Scsp_dcs        *dcsp;
146         int             event;
147         Scsp_msg        *msg;
148         Scsp_if_msg     *cmsg;
149 {
150         int     action, rc, state;
151
152         /*
153          * Select an action from the state table
154          */
155         state = dcsp->sd_client_state;
156         action = client_state_table[event][state];
157         if (scsp_trace_mode & SCSP_TRACE_CFSM) {
158                 scsp_trace("Server I/F FSM: state=%d, event=%d, action=%d\n",
159                                 state, event, action);
160         }
161         if (action >= SCSP_CIFSM_ACTION_CNT || action <= 0) {
162                 scsp_log(LOG_ERR, "Server I/F FSM--invalid action %d; state=%d, event=%d",
163                                 action, dcsp->sd_client_state, event);
164                 exit(1);
165         }
166
167         /*
168          * Perform the selected action
169          */
170         rc = scsp_action_vector[action](dcsp, msg, cmsg);
171
172         return(rc);
173 }
174
175
176 /*
177  * SCSP client server interface finite state machine action 0
178  * Unexpected action -- log an error message
179  *
180  * Arguments:
181  *      dcsp    pointer to DCS control block
182  *      msg     pointer to message from DCS (ignored)
183  *      cmsg    pointer to message from server (ignored)
184  *
185  * Returns:
186  *      EOPNOTSUPP      always returns EOPNOTSUPP
187  *
188  */
189 int
190 scsp_client_act_00(dcsp, msg, cmsg)
191         Scsp_dcs        *dcsp;
192         Scsp_msg        *msg;
193         Scsp_if_msg     *cmsg;
194 {
195         scsp_log(LOG_ERR, "Server I/F FSM error--unexpected action, state=%d",
196                         dcsp->sd_client_state);
197         return(EOPNOTSUPP);
198 }
199
200
201 /*
202  * SCSP client server interface finite state machine action 1
203  *
204  * Ignore an event
205  *
206  * Arguments:
207  *      dcsp    pointer to DCS control block
208  *      msg     pointer to message from DCS
209  *      cmsg    pointer to message from server
210  *
211  * Returns:
212  *      0       always returns 0
213  *
214  */
215 int
216 scsp_client_act_01(dcsp, msg, cmsg)
217         Scsp_dcs        *dcsp;
218         Scsp_msg        *msg;
219         Scsp_if_msg     *cmsg;
220 {
221         return(0);
222 }
223
224
225 /*
226  * SCSP client server interface finite state machine action 2
227  *
228  * CA FSM went to Cache Summarize state--go to Summarize
229  *
230  * Arguments:
231  *      dcsp    pointer to DCS control block
232  *      msg     pointer to message from DCS
233  *      cmsg    pointer to message from server
234  *
235  * Returns:
236  *      0       success
237  *      else    errno describing error
238  *
239  */
240 int
241 scsp_client_act_02(dcsp, msg, cmsg)
242         Scsp_dcs        *dcsp;
243         Scsp_msg        *msg;
244         Scsp_if_msg     *cmsg;
245 {
246         /*
247          * Set the new state
248          */
249         dcsp->sd_client_state = SCSP_CIFSM_SUM;
250
251         return(0);
252 }
253
254
255 /*
256  * SCSP client server interface finite state machine action 3
257  *
258  * CA FSM went down--clean up and go to Null
259  *
260  * Arguments:
261  *      dcsp    pointer to DCS control block
262  *      msg     pointer to message from DCS
263  *      cmsg    pointer to message from server
264  *
265  * Returns:
266  *      0       success
267  *      else    errno describing error
268  *
269  */
270 int
271 scsp_client_act_03(dcsp, msg, cmsg)
272         Scsp_dcs        *dcsp;
273         Scsp_msg        *msg;
274         Scsp_if_msg     *cmsg;
275 {
276         /*
277          * Set the new state
278          */
279         dcsp->sd_client_state = SCSP_CIFSM_NULL;
280
281         return(0);
282 }
283
284
285 /*
286  * SCSP client server interface finite state machine action 4
287  *
288  * CA FSM went to Update Cache state--go to Update state
289  *
290  * Arguments:
291  *      dcsp    pointer to DCS control block
292  *      msg     pointer to message from DCS
293  *      cmsg    pointer to message from server
294  *
295  * Returns:
296  *      0       success
297  *      else    errno describing error
298  *
299  */
300 int
301 scsp_client_act_04(dcsp, msg, cmsg)
302         Scsp_dcs        *dcsp;
303         Scsp_msg        *msg;
304         Scsp_if_msg     *cmsg;
305 {
306         /*
307          * Set the new state
308          */
309         dcsp->sd_client_state = SCSP_CIFSM_UPD;
310
311         return(0);
312 }
313
314
315 /*
316  * SCSP client server interface finite state machine action 5
317  *
318  * The CA FSM went to Cache Summarize state from Summarize,
319  * Update, or Aligned, implying that the CA FSM went down and came
320  * back up--copy the server's cache to the DCSs CSAS list and go to
321  * Summarize state
322  *
323  * Arguments:
324  *      dcsp    pointer to DCS control block
325  *      msg     pointer to message from DCS
326  *      cmsg    pointer to message from server
327  *
328  * Returns:
329  *      0       success
330  *      else    errno describing error
331  *
332  */
333 int
334 scsp_client_act_05(dcsp, msg, cmsg)
335         Scsp_dcs        *dcsp;
336         Scsp_msg        *msg;
337         Scsp_if_msg     *cmsg;
338 {
339         int             i;
340         Scsp_cse        *csep, *ncsep;
341
342         /*
343          * Copy the cache summmary to the CSAS list
344          */
345         for (i = 0; i < SCSP_HASHSZ; i++) {
346                 for (csep = dcsp->sd_server->ss_cache[i]; csep;
347                                 csep = csep->sc_next) {
348                         ncsep = scsp_dup_cse(csep);
349                         LINK2TAIL(ncsep, Scsp_cse, dcsp->sd_ca_csas,
350                                         sc_next);
351                 }
352         }
353
354         /*
355          * Set the new state
356          */
357         dcsp->sd_client_state = SCSP_CIFSM_SUM;
358
359         return(0);
360 }
361
362
363 /*
364  * SCSP client server interface finite state machine action 6
365  *
366  * CA FSM went to Aligned state--go to Aligned
367  *
368  * Arguments:
369  *      dcsp    pointer to DCS control block
370  *      msg     pointer to message from DCS
371  *      cmsg    pointer to message from server
372  *
373  * Returns:
374  *      0       success
375  *      else    errno describing error
376  *
377  */
378 int
379 scsp_client_act_06(dcsp, msg, cmsg)
380         Scsp_dcs        *dcsp;
381         Scsp_msg        *msg;
382         Scsp_if_msg     *cmsg;
383 {
384         /*
385          * Set the new state
386          */
387         dcsp->sd_client_state = SCSP_CIFSM_ALIGN;
388
389         return(0);
390 }
391
392
393 /*
394  * SCSP client server interface finite state machine action 7
395  *
396  * We received a Solicit Rsp or Update Req from the server--pass it
397  * to the CA FSM
398  *
399  * Arguments:
400  *      dcsp    pointer to DCS control block
401  *      msg     pointer to message from DCS
402  *      cmsg    pointer to message from server
403  *
404  * Returns:
405  *      0       success
406  *      else    errno describing error
407  *
408  */
409 int
410 scsp_client_act_07(dcsp, msg, cmsg)
411         Scsp_dcs        *dcsp;
412         Scsp_msg        *msg;
413         Scsp_if_msg     *cmsg;
414 {
415         int             rc;
416         Scsp_csa        *csap;
417         Scsp_atmarp_csa *acp;
418
419         /*
420          * Allocate memory for a CSA record
421          */
422         csap = (Scsp_csa *)UM_ALLOC(sizeof(Scsp_csa));
423         if (!csap) {
424                 scsp_mem_err("scsp_client_act_07: sizeof(Scsp_csa)");
425         }
426         acp = (Scsp_atmarp_csa *)UM_ALLOC(sizeof(Scsp_atmarp_csa));
427         if (!acp) {
428                 scsp_mem_err("scsp_client_act_07: sizeof(Scsp_atmarp_csa)");
429         }
430         UM_ZERO(csap, sizeof(Scsp_csa));
431         UM_ZERO(acp, sizeof(Scsp_atmarp_csa));
432
433         /*
434          * Build a CSA record from the server's message
435          */
436         csap->hops = dcsp->sd_hops;
437         csap->null = (cmsg->si_atmarp.sa_state == SCSP_ASTATE_DEL) ||
438                         (cmsg->si_type == SCSP_SOLICIT_RSP &&
439                         cmsg->si_rc != SCSP_RSP_OK);
440         csap->seq = cmsg->si_atmarp.sa_seq;
441         csap->key = cmsg->si_atmarp.sa_key;
442         csap->oid = cmsg->si_atmarp.sa_oid;
443         csap->atmarp_data = acp;
444         acp->sa_state = cmsg->si_atmarp.sa_state;
445         acp->sa_sha = cmsg->si_atmarp.sa_cha;
446         acp->sa_ssa = cmsg->si_atmarp.sa_csa;
447         acp->sa_spa = cmsg->si_atmarp.sa_cpa;
448         acp->sa_tpa = cmsg->si_atmarp.sa_cpa;
449
450         /*
451          * Call the CA FSM
452          */
453         rc = scsp_cafsm(dcsp, SCSP_CAFSM_CACHE_UPD, (void *)csap);
454
455         return(rc);
456 }
457
458
459 /*
460  * SCSP client server interface finite state machine action 8
461  *
462  * Update Rsp from server--pass the update to the CA FSM.
463  *
464  * Arguments:
465  *      dcsp    pointer to DCS control block
466  *      msg     pointer to message from DCS
467  *      cmsg    pointer to message from server
468  *
469  * Returns:
470  *      0       success
471  *      else    errno describing error
472  *
473  */
474 int
475 scsp_client_act_08(dcsp, msg, cmsg)
476         Scsp_dcs        *dcsp;
477         Scsp_msg        *msg;
478         Scsp_if_msg     *cmsg;
479 {
480         int             rc;
481
482         /* 
483          * Pass the response to the CA FSM
484          */
485         switch (dcsp->sd_server->ss_pid) {
486         case SCSP_PROTO_ATMARP:
487                 rc = scsp_cafsm(dcsp, SCSP_CAFSM_CACHE_RSP, cmsg);
488                 break;
489         default:
490                 rc = EPROTONOSUPPORT;
491         }
492
493         return(rc);
494 }
495
496
497 /*
498  * SCSP client server interface finite state machine action 9
499  *
500  * CSU Solicit from DCS--pass Solicit Ind to server
501  *
502  * Arguments:
503  *      dcsp    pointer to DCS control block
504  *      msg     pointer to message from DCS
505  *      cmsg    pointer to message from server
506  *
507  * Returns:
508  *      0       success
509  *      else    errno describing error
510  *
511  */
512 int
513 scsp_client_act_09(dcsp, msg, cmsg)
514         Scsp_dcs        *dcsp;
515         Scsp_msg        *msg;
516         Scsp_if_msg     *cmsg;
517 {
518         int             rc, rrc = 0;
519         Scsp_csa        *csap;
520         Scsp_if_msg     *csip;
521
522         /*
523          * Get memory for a Solicit Ind
524          */
525         csip = (Scsp_if_msg *)UM_ALLOC(sizeof(Scsp_if_msg));
526         if (!csip) {
527                 scsp_mem_err("scsp_client_act_09: sizeof(Scsp_if_msg)");
528         }
529
530         /*
531          * Loop through list of CSAs
532          */
533         for (csap = msg->sc_csu_msg->csu_csa_rec; csap;
534                         csap = csap->next) {
535                 /*
536                  * Fill out the Solicit Indication
537                  */
538                 UM_ZERO(csip, sizeof(Scsp_if_msg));
539                 csip->si_type = SCSP_SOLICIT_IND;
540                 csip->si_proto = dcsp->sd_server->ss_pid;
541                 csip->si_tok = (u_long)dcsp;
542                 csip->si_len = sizeof(Scsp_if_msg_hdr) +
543                                 sizeof(Scsp_sum_msg);
544                 csip->si_sum.ss_hops = csap->hops;
545                 csip->si_sum.ss_null = csap->null;
546                 csip->si_sum.ss_seq = csap->seq;
547                 csip->si_sum.ss_key = csap->key;
548                 csip->si_sum.ss_oid = csap->oid;
549
550                 /*
551                  * Send the Solicit Ind to the server
552                  */
553                 rc = scsp_if_sock_write(dcsp->sd_server->ss_sock, csip);
554                 if (rc) {
555                         rrc = rc;
556                 }
557         }
558
559         UM_FREE(csip);
560         return(rrc);
561 }
562
563
564 /*
565  * SCSP client server interface finite state machine action 10
566  *
567  * CSU Request from DCS--pass it to the server as a Cache Update
568  * Indication
569  *
570  * Arguments:
571  *      dcsp    pointer to DCS control block
572  *      msg     pointer to message from DCS
573  *      cmsg    pointer to message from server
574  *
575  * Returns:
576  *      0       success
577  *      else    errno describing error
578  *
579  */
580 int
581 scsp_client_act_10(dcsp, msg, cmsg)
582         Scsp_dcs        *dcsp;
583         Scsp_msg        *msg;
584         Scsp_if_msg     *cmsg;
585 {
586         int             rc, rrc = 0;
587         Scsp_csa        *csap;
588         Scsp_atmarp_csa *acp;
589         Scsp_if_msg     *cuip;
590
591         /*
592          * Get memory for a Cache Update Ind
593          */
594         cuip = (Scsp_if_msg *)UM_ALLOC(sizeof(Scsp_if_msg));
595         if (!cuip) {
596                 scsp_mem_err("scsp_client_act_10: sizeof(Scsp_if_msg)");
597         }
598
599         /*
600          * Loop through CSAs in message
601          */
602         for (csap = msg->sc_csu_msg->csu_csa_rec; csap;
603                         csap = csap->next) {
604                 acp = csap->atmarp_data;
605                 if (!acp)
606                         continue;
607
608                 /*
609                  * Fill out the Cache Update Ind
610                  */
611                 UM_ZERO(cuip, sizeof(Scsp_if_msg));
612                 cuip->si_type = SCSP_UPDATE_IND;
613                 cuip->si_proto = dcsp->sd_server->ss_pid;
614                 cuip->si_tok = (u_long)dcsp;
615                 switch(dcsp->sd_server->ss_pid) {
616                 case SCSP_PROTO_ATMARP:
617                         cuip->si_len = sizeof(Scsp_if_msg_hdr) +
618                                         sizeof(Scsp_atmarp_msg);
619                         cuip->si_atmarp.sa_state = acp->sa_state;
620                         cuip->si_atmarp.sa_cpa = acp->sa_spa;
621                         cuip->si_atmarp.sa_cha = acp->sa_sha;
622                         cuip->si_atmarp.sa_csa = acp->sa_ssa;
623                         cuip->si_atmarp.sa_key = csap->key;
624                         cuip->si_atmarp.sa_oid = csap->oid;
625                         cuip->si_atmarp.sa_seq = csap->seq;
626                         break;
627                 case SCSP_PROTO_NHRP:
628                         /*
629                          * Not implemented yet
630                          */
631                         break;
632                 }
633
634                 /*
635                  * Send the Cache Update Ind to the server
636                  */
637                 rc = scsp_if_sock_write(dcsp->sd_server->ss_sock, cuip);
638                 if (rc) {
639                         rrc = rc;
640                 }
641         }
642
643         UM_FREE(cuip);
644         return(rrc);
645 }