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