📄 fsm.c
字号:
dprintf(4, (LOG_DAEMON, LOG_DEBUG, "%s: entered", func)); for (i = 0; events[i].ev_name != NULL; i++) { if (strcmp (events[i].ev_name, pevent) == 0) { return events[i].ev_value; } } return (-2);} /* end of enum_event () *//************************************************************************* * * Function: extra_stuff * * Purpose: Evaluate an extra value pair (or two) for this FSM entry. * * Returns: 0, if successful, * -1, if there were errors. * *************************************************************************/static intextra_stuff (buf, value, string)char *buf;int *value;char **string;{ int result; VALUE_PAIR *list; VALUE_PAIR *vp; static char *func = "extra_stuff"; dprintf(4, (LOG_DAEMON, LOG_DEBUG, "%s: entered", func)); result = 0; *value = 0; *string = '\0'; vp = (VALUE_PAIR *) NULL; list = (VALUE_PAIR *) NULL; if (pair_parse (buf, &list, (VALUE_PAIR **) NULL) != 0) { dprintf(4, (LOG_DAEMON, LOG_DEBUG, "%s: error parsing '%s'", func, (buf == (char *) NULL) ? "?" : buf )); result = -1; } else { vp = list; while (vp != (VALUE_PAIR *) NULL) { switch (vp->ap->type) { case PW_TYPE_INTEGER: *value = vp->lvalue; break; case PW_TYPE_STRING: if (strlen (vp->strvalue) < AUTH_ID_LEN) { *string = add_string (vp->strvalue, ASIS); } break; default: dprintf(4, (LOG_DAEMON, LOG_DEBUG, "%s: unsupported type %d", func, vp->ap->type)); result = -1; break; } vp = vp->next; } } list_free (list); return result;} /* end of extra_stuff () *//************************************************************************* * * Function: find_state * * Purpose: Find the numer of the given state in the list of states. * * Returns: pointer to the NAME_LIST node for this state, * (NAME_LIST *) NULL, if the name is not found in the list. * *************************************************************************/static NAME_LIST *find_state (list, name)STATELIST *list; /* list of states names already seen */char *name; /* the state name to search for */{ NAME_LIST *state; static char *func = "find_state"; dprintf(4, (LOG_DAEMON, LOG_DEBUG, "%s: entered", func)); for (state = list->states ; state != (NAME_LIST *) NULL ; state = state->next) { if (strcmp (state->name, name) == 0) { break; } } return state;} /* end of find_state () *//************************************************************************* * * Function: init_fsm * * Purpose: Does all the initialization for FSM. * * Returns: <number of states>, if the (new) FSM is initialized properly, * -1, if any errors are detected. * *************************************************************************/intinit_fsm (n, fsm_file, main_fsm, def_fsm)int n; /* INPUT: current number of FSM states */char *fsm_file; /* INPUT: pointer to FSM config file name */FSM_ENT ***main_fsm; /* OUTPUT: pointer to FSM table */FSM_ENT ***def_fsm; /* OUTPUT: pointer to default action table */{ int len; int nfsm; FILE *fp; char *fsmfile; struct stat statbuf; char buf[MAXPATHLEN]; static char *func = "init_fsm"; dprintf(2, (LOG_DAEMON, LOG_DEBUG, "%s: entered", func)); if (n > 0) { rad_fsmdelete (n); } sprintf (buf, "%s/%s", radius_dir, fsm_file); if ((fp = fopen (buf, "r")) == (FILE *) NULL) { dprintf(2, (LOG_DAEMON, LOG_DEBUG, "%s: using built-in standard FSM table", func)); fsmfile = standard_fsm; strcpy (buf, "built-in standard FSM table"); fsm_file = "Built-in"; } else { stat (buf, &statbuf); len = (long) statbuf.st_size; if ((fsmfile = (char *) malloc (len)) == (char *) NULL) { logit (LOG_DAEMON, LOG_ALERT, "%s: FATAL out of memory", func); abort (); } fread (fsmfile, len, 1, fp); fclose (fp); /* Cleanup... */ } nfsm = rad_fsminit (fsmfile, &fsm, fsm_file); if (fsmfile != standard_fsm) { free (fsmfile); } dprintf(1, (LOG_DAEMON, LOG_DEBUG, "%s: FSM defined with %d states from %s", func, nfsm, buf)); if (nfsm == -2) { return (-1); } /* ... and the default action table */ if (default_fsm == (FSM_ENT **) NULL) { len = rad_fsminit (default_actions, &default_fsm, "DEFAULT"); if (len == -2) { dprintf(1, (LOG_DAEMON, LOG_DEBUG, "%s: return code %d from rad_fsminit()", func, len)); return (-1); } } *main_fsm = fsm; *def_fsm = default_fsm; return nfsm;} /* end of init_fsm () *//************************************************************************* * * Function: rad_fsmdelete * * Purpose: Destroy the finite state machine (FSM) data structure. * *************************************************************************/static voidrad_fsmdelete (nfsm)int nfsm;{ FSM_ENT *pe; FSM_ENT *pen; static char *func = "rad_fsmdelete"; dprintf(2, (LOG_DAEMON, LOG_DEBUG, "%s: entered", func)); while (nfsm > 0) /* free the individual FSM state entries */ { nfsm--; for (pe = fsm[nfsm]; pe != (FSM_ENT *) NULL; pe = pen) { pen = pe->next; free (pe); } } free (fsm); /* free the FSM array itself */ return;} /* end of rad_fsmdelete () *//************************************************************************* * * Function: rad_fsminit * * Purpose: Initialize the FSM table in memory from the given file. * * Returns: number of states parsed, if successful, * -2, if errors occurred. * *************************************************************************/static intrad_fsminit (fsmfile, fsm, fsm_name)char *fsmfile;FSM_ENT ***fsm;char *fsm_name;{ int i; /* loop variable */ int more; /* while loop control variable */ int nfsm; /* state counter */ int line_cnt; /* config file line count */ int err_cnt; /* used in FSM verification */ int ref_cnt; /* used in FSM verification */ int cst; /* current state number */ int xvalue; FILE *debugout = stdout; char *ptr; /* pointer into given file */ char *newline; /* pointer into given file */ char *p; /* pointer into line buffer */ char *s; /* pointer into line buffer */ char *b; /* pointer into line buffer */ char *e; /* pointer into line buffer */ char *a; /* pointer into line buffer */ char *n; /* pointer into line buffer */ char *xtra; /* pointer into line buffer */ FSM_ENT *pe; /* pointer to an entry */ FSM_ENT *pn; /* temporary pointer */ FSM_ENT **pfsm; /* new FSM */ NAME_LIST *node; /* pointer to a state NAME_LIST node */ NAME_LIST *node_state; /* pointer to current FSM state */ NAME_LIST **prev; /* used to free "sts" states below */ STATELIST sts; /* state list data structure */ char *xstring; char buf[256]; /* line buffer for file reading */ static char *func = "rad_fsminit"; dprintf(2, (LOG_DAEMON, LOG_DEBUG, "%s: entered", func)); /* allocate new FSM */ sts.nst = 0; sts.maxst = NUMSTATES; sts.states = (NAME_LIST *) NULL; if ((pfsm = (FSM_ENT **) calloc (sts.maxst, sizeof (FSM_ENT *))) == (FSM_ENT **) NULL) { logit (LOG_DAEMON, LOG_ALERT, "%s: FATAL out of memory for FSM", func); abort (); } line_cnt = 0; /* line number for debugging */ nfsm = 0; /* have seen no state yet */ more = 1; ptr = fsmfile; node_state = (NAME_LIST *) NULL; /* Saftey */ while (more) { if ((newline = strchr (ptr, '\n')) == (char *) NULL) { more = 0; break; } else { i = newline - ptr; strncpy (buf, ptr, i); buf[i] = '\0'; ptr = ++newline; } line_cnt++; if (*buf == COMMENT || *buf == '\n' || *buf == '\0') { continue; } else { if (*buf == '%') { if ((p = strtok (buf, " \t")) != (char *) NULL) { /* Have found a keyword */ if (strcasecmp (p, "%FSMID") == 0) { /* Find end of line. */ if ((p = strtok (NULL, "\n\r")) != (char *) NULL) { int j; if (fsm_id != (char *) NULL) { free (fsm_id); } j = strlen (p); if (j > MAX_FSMID_LEN) { /* Truncate. */ p[MAX_FSMID_LEN] = '\0'; } fsm_id = rad_strdup (p); fsm_name = fsm_id; } } } /* Just treat FSMID as a comment. */ continue; } } while (i > 0) /* capitalize all tokens on line */ { i--; buf[i] = toupper (buf[i]); } xvalue = 0; xstring = (char *) NULL; if (isalpha(*buf)) /* states start in column one */ { if ((p = strtok (buf, ":")) != NULL) /* have state */ { if ((s = strtok (NULL, " \t\r\n")) != NULL) { if ((*s != '#') && (*s != '\0')) { logit (LOG_DAEMON, LOG_ERR, "%s: Warning, extra junk on end of state label", func); logit (LOG_DAEMON, LOG_ERR, "%s: at line %d, for state %s, '%s'", func, line_cnt, p, s); } } if (strcmp (p, "END") == 0) { dprintf(4, (LOG_DAEMON, LOG_DEBUG, "%s state detected", p)); more = 0; } else /* insert new state */ { dprintf(4, (LOG_DAEMON, LOG_DEBUG, "about to insert new state %s", p)); if ((node = find_state (&sts, p)) == (NAME_LIST *) NULL) { cst = nfsm; nfsm = add_state (&sts, p, (u_int) ST_DEFINED, cst); node_state = find_state (&sts, p); } else /* have seen this state already */ { node_state = node; if (node->flag == ST_SEEN) { cst = node->num; node->flag = ST_DEFINED; } else /* oops, was defined */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -