(*fp->fn->DecodeConfig)(fp, ptr, count, MODE_NOP, NULL); if (count < sizeof(struct fsmconfig))
(*fp->fn->DecodeConfig)(fp, ptr, ptr + count, MODE_NOP, NULL); if (count < sizeof(struct fsm_opt_hdr))
              FsmRecvTimeRemain, FsmRecvResetReq, FsmRecvResetAck;static const struct fsmcodedesc {  recvfn *recv;  unsigned check_reqid : 1;  unsigned inc_reqid : 1;  const char *name;} FsmCodes[] = {  { FsmRecvConfigReq, 0, 0, "ConfigReq"    },  { FsmRecvConfigAck, 1, 1, "ConfigAck"    },  { FsmRecvConfigNak, 1, 1, "ConfigNak"    },  { FsmRecvConfigRej, 1, 1, "ConfigRej"    },  { FsmRecvTermReq,   0, 0, "TerminateReq" },  { FsmRecvTermAck,   1, 1, "TerminateAck" },  { FsmRecvCodeRej,   0, 0, "CodeRej"      },  { FsmRecvProtoRej,  0, 0, "ProtocolRej"  },  { FsmRecvEchoReq,   0, 0, "EchoRequest"  },  { FsmRecvEchoRep,   0, 0, "EchoReply"    },  { FsmRecvDiscReq,   0, 0, "DiscardReq"   },  { FsmRecvIdent,     0, 1, "Ident"        },  { FsmRecvTimeRemain,0, 0, "TimeRemain"   },  { FsmRecvResetReq,  0, 0, "ResetReq"     },  { FsmRecvResetAck,  0, 1, "ResetAck"     }};static const char *Code2Nam(u_int code){  if (code == 0 || code > sizeof FsmCodes / sizeof FsmCodes[0])    return "Unknown";  return FsmCodes[code-1].name;}const char *State2Nam(u_int state){  static const char * const StateNames[] = {    "Initial", "Starting", "Closed", "Stopped", "Closing", "Stopping",    "Req-Sent", "Ack-Rcvd", "Ack-Sent", "Opened",  };  if (state >= sizeof StateNames / sizeof StateNames[0])    return "unknown";  return StateNames[state];}static voidStoppedTimeout(void *v){  struct fsm *fp = (struct fsm *)v;  log_Printf(fp->LogLevel, "%s: Stopped timer expired\n", fp->link->name);  if (fp->OpenTimer.state == TIMER_RUNNING) {    log_Printf(LogWARN, "%s: %s: aborting open delay due to stopped timer\n",              fp->link->name, fp->name);    timer_Stop(&fp->OpenTimer);  }  if (fp->state == ST_STOPPED)    fsm2initial(fp);}voidfsm_Init(struct fsm *fp, const char *name, u_short proto, int mincode,         int maxcode, int LogLevel, struct bundle *bundle,         struct link *l, const struct fsm_parent *parent,         struct fsm_callbacks *fn, const char * const timer_names[3]){  fp->name = name;  fp->proto = proto;  fp->min_code = mincode;  fp->max_code = maxcode;  fp->state = fp->min_code > CODE_TERMACK ? ST_OPENED : ST_INITIAL;  fp->reqid = 1;  fp->restart = 1;  fp->more.reqs = fp->more.naks = fp->more.rejs = 3;  memset(&fp->FsmTimer, '\0', sizeof fp->FsmTimer);  memset(&fp->OpenTimer, '\0', sizeof fp->OpenTimer);  memset(&fp->StoppedTimer, '\0', sizeof fp->StoppedTimer);  fp->LogLevel = LogLevel;  fp->link = l;  fp->bundle = bundle;  fp->parent = parent;  fp->fn = fn;  fp->FsmTimer.name = timer_names[0];  fp->OpenTimer.name = timer_names[1];  fp->StoppedTimer.name = timer_names[2];}static voidNewState(struct fsm *fp, int new){  log_Printf(fp->LogLevel, "%s: State change %s --> %s\n",	    fp->link->name, State2Nam(fp->state), State2Nam(new));  if (fp->state == ST_STOPPED && fp->StoppedTimer.state == TIMER_RUNNING)    timer_Stop(&fp->StoppedTimer);  fp->state = new;  if ((new >= ST_INITIAL && new <= ST_STOPPED) || (new == ST_OPENED)) {    timer_Stop(&fp->FsmTimer);    if (new == ST_STOPPED && fp->StoppedTimer.load) {      timer_Stop(&fp->StoppedTimer);      fp->StoppedTimer.func = StoppedTimeout;      fp->StoppedTimer.arg = (void *) fp;      timer_Start(&fp->StoppedTimer);    }  }}voidfsm_Output(struct fsm *fp, u_int code, u_int id, u_char *ptr, int count,           int mtype){  int plen;  struct fsmheader lh;  struct mbuf *bp;  if (log_IsKept(fp->LogLevel)) {    log_Printf(fp->LogLevel, "%s: Send%s(%d) state = %s\n",              fp->link->name, Code2Nam(code), id, State2Nam(fp->state));    switch (code) {      case CODE_CONFIGREQ:      case CODE_CONFIGACK:      case CODE_CONFIGREJ:      case CODE_CONFIGNAK:        (*fp->fn->DecodeConfig)(fp, ptr, count, MODE_NOP, NULL);        if (count < sizeof(struct fsmconfig))          log_Printf(fp->LogLevel, "  [EMPTY]\n");        break;    }  }  plen = sizeof(struct fsmheader) + count;  lh.code = code;  lh.id = id;  lh.length = htons(plen);  bp = m_get(plen, mtype);  memcpy(MBUF_CTOP(bp), &lh, sizeof(struct fsmheader));  if (count)    memcpy(MBUF_CTOP(bp) + sizeof(struct fsmheader), ptr, count);  log_DumpBp(LogDEBUG, "fsm_Output", bp);  link_PushPacket(fp->link, bp, fp->bundle, LINK_QUEUES(fp->link) - 1,                  fp->proto);  if (code == CODE_CONFIGREJ)    lcp_SendIdentification(&fp->link->lcp);}static voidFsmOpenNow(void *v){  struct fsm *fp = (struct fsm *)v;  timer_Stop(&fp->OpenTimer);  if (fp->state <= ST_STOPPED) {    if (fp->state != ST_STARTING) {      /*       * In practice, we're only here in ST_STOPPED (when delaying the       * first config request) or ST_CLOSED (when openmode == 0).       *       * The ST_STOPPED bit is breaking the RFC already :-(       *       * According to the RFC (1661) state transition table, a TLS isn't       * required for an Open event when state == Closed, but the RFC       * must be wrong as TLS hasn't yet been called (since the last TLF)       * ie, Initial gets an `Up' event, Closing gets a RTA etc.       */      (*fp->fn->LayerStart)(fp);      (*fp->parent->LayerStart)(fp->parent->object, fp);    }    FsmInitRestartCounter(fp, FSM_REQ_TIMER);    FsmSendConfigReq(fp);    NewState(fp, ST_REQSENT);  }}voidfsm_Open(struct fsm *fp){  switch (fp->state) {  case ST_INITIAL:    NewState(fp, ST_STARTING);    (*fp->fn->LayerStart)(fp);    (*fp->parent->LayerStart)(fp->parent->object, fp);    break;  case ST_CLOSED:    if (fp->open_mode == OPEN_PASSIVE) {      NewState(fp, ST_STOPPED);		/* XXX: This is a hack ! */    } else if (fp->open_mode > 0) {      if (fp->open_mode > 1)        log_Printf(LogPHASE, "%s: Entering STOPPED state for %d seconds\n",                  fp->link->name, fp->open_mode);      NewState(fp, ST_STOPPED);		/* XXX: This is a not-so-bad hack ! */      timer_Stop(&fp->OpenTimer);      fp->OpenTimer.load = fp->open_mode * SECTICKS;      fp->OpenTimer.func = FsmOpenNow;      fp->OpenTimer.arg = (void *)fp;      timer_Start(&fp->OpenTimer);    } else      FsmOpenNow(fp);    break;  case ST_STOPPED:		/* XXX: restart option */  case ST_REQSENT:  case ST_ACKRCVD:  case ST_ACKSENT:  case ST_OPENED:		/* XXX: restart option */    break;  case ST_CLOSING:		/* XXX: restart option */  case ST_STOPPING:		/* XXX: restart option */    NewState(fp, ST_STOPPING);    break;  }}voidfsm_Up(struct fsm *fp){  switch (fp->state) {  case ST_INITIAL:    log_Printf(fp->LogLevel, "FSM: Using \"%s\" as a transport\n",              fp->link->name);    NewState(fp, ST_CLOSED);    break;  case ST_STARTING:    FsmInitRestartCounter(fp, FSM_REQ_TIMER);    FsmSendConfigReq(fp);    NewState(fp, ST_REQSENT);    break;  default:    log_Printf(fp->LogLevel, "%s: Oops, Up at %s\n",              fp->link->name, State2Nam(fp->state));    break;  }}voidfsm_Down(struct fsm *fp){  switch (fp->state) {  case ST_CLOSED:    NewState(fp, ST_INITIAL);    break;  case ST_CLOSING:    /* This TLF contradicts the RFC (1661), which ``misses it out'' ! */    (*fp->fn->LayerFinish)(fp);    NewState(fp, ST_INITIAL);    (*fp->parent->LayerFinish)(fp->parent->object, fp);    break;  case ST_STOPPED:    NewState(fp, ST_STARTING);    (*fp->fn->LayerStart)(fp);    (*fp->parent->LayerStart)(fp->parent->object, fp);    break;  case ST_STOPPING:  case ST_REQSENT:  case ST_ACKRCVD:  case ST_ACKSENT:    NewState(fp, ST_STARTING);    break;  case ST_OPENED:    (*fp->fn->LayerDown)(fp);    NewState(fp, ST_STARTING);    (*fp->parent->LayerDown)(fp->parent->object, fp);    break;  }}voidfsm_Close(struct fsm *fp){  switch (fp->state) {  case ST_STARTING:    (*fp->fn->LayerFinish)(fp);    NewState(fp, ST_INITIAL);    (*fp->parent->LayerFinish)(fp->parent->object, fp);    break;  case ST_STOPPED:    NewState(fp, ST_CLOSED);    break;  case ST_STOPPING:    NewState(fp, ST_CLOSING);    break;  case ST_OPENED:    (*fp->fn->LayerDown)(fp);    if (fp->state == ST_OPENED) {      FsmInitRestartCounter(fp, FSM_TRM_TIMER);      FsmSendTerminateReq(fp);      NewState(fp, ST_CLOSING);      (*fp->parent->LayerDown)(fp->parent->object, fp);    }    break;  case ST_REQSENT:  case ST_ACKRCVD:  case ST_ACKSENT:    FsmInitRestartCounter(fp, FSM_TRM_TIMER);    FsmSendTerminateReq(fp);    NewState(fp, ST_CLOSING);    break;  }}/* *	Send functions */static voidFsmSendConfigReq(struct fsm *fp){  if (fp->more.reqs-- > 0 && fp->restart-- > 0) {    (*fp->fn->SendConfigReq)(fp);    timer_Start(&fp->FsmTimer);		/* Start restart timer */  } else {    if (fp->more.reqs < 0)      log_Printf(LogPHASE, "%s: Too many %s REQs sent - abandoning "                 "negotiation\n", fp->link->name, fp->name);    lcp_SendIdentification(&fp->link->lcp);    fsm_Close(fp);  }}static voidFsmSendTerminateReq(struct fsm *fp){  fsm_Output(fp, CODE_TERMREQ, fp->reqid, NULL, 0, MB_UNKNOWN);  (*fp->fn->SentTerminateReq)(fp);  timer_Start(&fp->FsmTimer);	/* Start restart timer */  fp->restart--;		/* Decrement restart counter */}/* *	Timeout actions */static voidFsmTimeout(void *v){  struct fsm *fp = (struct fsm *)v;  if (fp->restart) {    switch (fp->state) {    case ST_CLOSING:    case ST_STOPPING:      FsmSendTerminateReq(fp);      break;    case ST_REQSENT:    case ST_ACKSENT:      FsmSendConfigReq(fp);      break;    case ST_ACKRCVD:      FsmSendConfigReq(fp);      NewState(fp, ST_REQSENT);      break;    }    timer_Start(&fp->FsmTimer);  } else {    switch (fp->state) {    case ST_CLOSING:      (*fp->fn->LayerFinish)(fp);      NewState(fp, ST_CLOSED);      (*fp->parent->LayerFinish)(fp->parent->object, fp);      break;    case ST_STOPPING:      (*fp->fn->LayerFinish)(fp);      NewState(fp, ST_STOPPED);      (*fp->parent->LayerFinish)(fp->parent->object, fp);      break;    case ST_REQSENT:		/* XXX: 3p */    case ST_ACKSENT:    case ST_ACKRCVD:      (*fp->fn->LayerFinish)(fp);      NewState(fp, ST_STOPPED);      (*fp->parent->LayerFinish)(fp->parent->object, fp);      break;    }  }}static voidFsmInitRestartCounter(struct fsm *fp, int what){  timer_Stop(&fp->FsmTimer);  fp->FsmTimer.func = FsmTimeout;  fp->FsmTimer.arg = (void *)fp;  (*fp->fn->InitRestartCounter)(fp, what);}/* * Actions when receive packets */static voidFsmRecvConfigReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)/* RCR */{  struct fsm_decode dec;  int plen, flen;  int ackaction = 0;  plen = m_length(bp);  flen = ntohs(lhp->length) - sizeof *lhp;  if (plen < flen) {    log_Printf(LogWARN, "%s: FsmRecvConfigReq: plen (%d) < flen (%d)\n",	      fp->link->name, plen, flen);    m_freem(bp);    return;  }  /* Check and process easy case */  switch (fp->state) {  case ST_INITIAL:    if (fp->proto == PROTO_CCP && fp->link->lcp.fsm.state == ST_OPENED) {      /*       * ccp_SetOpenMode() leaves us in initial if we're disabling       * & denying everything.       */      bp = m_prepend(bp, lhp, sizeof *lhp, 2);      bp = proto_Prepend(bp, fp->proto, 0, 0);      bp = m_pullup(bp);      lcp_SendProtoRej(&fp->link->lcp, MBUF_CTOP(bp), bp->m_len);      m_freem(bp);      return;    }    /* Drop through */  case ST_STARTING:    log_Printf(fp->LogLevel, "%s: Oops, RCR in %s.\n",              fp->link->name, State2Nam(fp->state));    m_freem(bp);    return;  case ST_CLOSED:    (*fp->fn->SendTerminateAck)(fp, lhp->id);    m_freem(bp);    return;  case ST_CLOSING:    log_Printf(fp->LogLevel, "%s: Error: Got ConfigReq while state = %s\n",              fp->link->name, State2Nam(fp->state));  case ST_STOPPING:    m_freem(bp);    return;  case ST_OPENED:    (*fp->fn->LayerDown)(fp);    break;  }  bp = m_pullup(bp);  dec.ackend = dec.ack;  dec.nakend = dec.nak;  dec.rejend = dec.rej;  (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REQ, &dec);  if (flen < sizeof(struct fsmconfig))    log_Printf(fp->LogLevel, "  [EMPTY]\n");  if (dec.nakend == dec.nak && dec.rejend == dec.rej)    ackaction = 1;  switch (fp->state) {  case ST_STOPPED:    FsmInitRestartCounter(fp, FSM_REQ_TIMER);    /* Fall through */  case ST_OPENED:    FsmSendConfigReq(fp);    break;  }  if (dec.rejend != dec.rej)    fsm_Output(fp, CODE_CONFIGREJ, lhp->id, dec.rej, dec.rejend - dec.rej,               MB_UNKNOWN);  if (dec.nakend != dec.nak)    fsm_Output(fp, CODE_CONFIGNAK, lhp->id, dec.nak, dec.nakend - dec.nak,               MB_UNKNOWN);  if (ackaction)    fsm_Output(fp, CODE_CONFIGACK, lhp->id, dec.ack, dec.ackend - dec.ack,               MB_UNKNOWN);  switch (fp->state) {  case ST_STOPPED:      /*       * According to the RFC (1661) state transition table, a TLS isn't       * required for a RCR when state == ST_STOPPED, but the RFC       * must be wrong as TLS hasn't yet been called (since the last TLF)       */    (*fp->fn->LayerStart)(fp);    (*fp->parent->LayerStart)(fp->parent->object, fp);    /* Fall through */  case ST_OPENED:    if (ackaction)      NewState(fp, ST_ACKSENT);    else      NewState(fp, ST_REQSENT);    (*fp->parent->LayerDown)(fp->parent->object, fp);    break;  case ST_REQSENT:    if (ackaction)      NewState(fp, ST_ACKSENT);    break;  case ST_ACKRCVD:    if (ackaction) {      NewState(fp, ST_OPENED);      if ((*fp->fn->LayerUp)(fp))        (*fp->parent->LayerUp)(fp->parent->object, fp);      else {        (*fp->fn->LayerDown)(fp);        FsmInitRestartCounter(fp, FSM_TRM_TIMER);        FsmSendTerminateReq(fp);        NewState(fp, ST_CLOSING);        lcp_SendIdentification(&fp->link->lcp);      }    }    break;  case ST_ACKSENT:    if (!ackaction)      NewState(fp, ST_REQSENT);    break;  }  m_freem(bp);  if (dec.rejend != dec.rej && --fp->more.rejs <= 0) {    log_Printf(LogPHASE, "%s: Too many %s REJs sent - abandoning negotiation\n",               fp->link->name, fp->name);    lcp_SendIdentification(&fp->link->lcp);    fsm_Close(fp);  }  if (dec.nakend != dec.nak && --fp->more.naks <= 0) {    log_Printf(LogPHASE, "%s: Too many %s NAKs sent - abandoning negotiation\n",               fp->link->name, fp->name);    lcp_SendIdentification(&fp->link->lcp);    fsm_Close(fp);  }}static voidFsmRecvConfigAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)/* RCA */{  switch (fp->state) {    case ST_CLOSED:    case ST_STOPPED:    (*fp->fn->SendTerminateAck)(fp, lhp->id);    break;  case ST_CLOSING:  case ST_STOPPING:    break;  case ST_REQSENT:    FsmInitRestartCounter(fp, FSM_REQ_TIMER);    NewState(fp, ST_ACKRCVD);    break;  case ST_ACKRCVD:    FsmSendConfigReq(fp);    NewState(fp, ST_REQSENT);    break;  case ST_ACKSENT:    FsmInitRestartCounter(fp, FSM_REQ_TIMER);    NewState(fp, ST_OPENED);    if ((*fp->fn->LayerUp)(fp))      (*fp->parent->LayerUp)(fp->parent->object, fp);    else {      (*fp->fn->LayerDown)(fp);      FsmInitRestartCounter(fp, FSM_TRM_TIMER);      FsmSendTerminateReq(fp);      NewState(fp, ST_CLOSING);      lcp_SendIdentification(&fp->link->lcp);    }    break;  case ST_OPENED:    (*fp->fn->LayerDown)(fp);    FsmSendConfigReq(fp);    NewState(fp, ST_REQSENT);    (*fp->parent->LayerDown)(fp->parent->object, fp);    break;  }  m_freem(bp);}static voidFsmRecvConfigNak(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)/* RCN */{  struct fsm_decode dec;  int plen, flen;  plen = m_length(bp);  flen = ntohs(lhp->length) - sizeof *lhp;  if (plen < flen) {    m_freem(bp);    return;  }  /*   * Check and process easy case   */  switch (fp->state) {  case ST_INITIAL:  case ST_STARTING:    log_Printf(fp->LogLevel, "%s: Oops, RCN in %s.\n",              fp->link->name, State2Nam(fp->state));    m_freem(bp);    return;  case ST_CLOSED:  case ST_STOPPED:    (*fp->fn->SendTerminateAck)(fp, lhp->id);    m_freem(bp);    return;  case ST_CLOSING:  case ST_STOPPING:    m_freem(bp);    return;  }  bp = m_pullup(bp);  dec.ackend = dec.ack;  dec.nakend = dec.nak;  dec.rejend = dec.rej;  (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_NAK, &dec);  if (flen < sizeof(struct fsmconfig))    log_Printf(fp->LogLevel, "  [EMPTY]\n");  switch (fp->state) {  case ST_REQSENT:  case ST_ACKSENT:    FsmInitRestartCounter(fp, FSM_REQ_TIMER);    FsmSendConfigReq(fp);    break;  case ST_OPENED:    (*fp->fn->LayerDown)(fp);    FsmSendConfigReq(fp);    NewState(fp, ST_REQSENT);    (*fp->parent->LayerDown)(fp->parent->object, fp);    break;  case ST_ACKRCVD:    FsmSendConfigReq(fp);    NewState(fp, ST_REQSENT);    break;  }  m_freem(bp);}static voidFsmRecvTermReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)/* RTR */{  switch (fp->state) {  case ST_INITIAL:  case ST_STARTING:    log_Printf(fp->LogLevel, "%s: Oops, RTR in %s\n",              fp->link->name, State2Nam(fp->state));    break;  case ST_CLOSED:  case ST_STOPPED:  case ST_CLOSING:  case ST_STOPPING:  case ST_REQSENT:    (*fp->fn->SendTerminateAck)(fp, lhp->id);    break;  case ST_ACKRCVD:  case ST_ACKSENT:    (*fp->fn->SendTerminateAck)(fp, lhp->id);    NewState(fp, ST_REQSENT);    break;  case ST_OPENED:    (*fp->fn->LayerDown)(fp);    (*fp->fn->SendTerminateAck)(fp, lhp->id);    FsmInitRestartCounter(fp, FSM_TRM_TIMER);    timer_Start(&fp->FsmTimer);			/* Start restart timer */    fp->restart = 0;    NewState(fp, ST_STOPPING);    (*fp->parent->LayerDown)(fp->parent->object, fp);    /* A delayed ST_STOPPED is now scheduled */    break;  }  m_freem(bp);}static voidFsmRecvTermAck(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)/* RTA */{  switch (fp->state) {  case ST_CLOSING:    (*fp->fn->LayerFinish)(fp);    NewState(fp, ST_CLOSED);    (*fp->parent->LayerFinish)(fp->parent->object, fp);    break;  case ST_STOPPING:    (*fp->fn->LayerFinish)(fp);    NewState(fp, ST_STOPPED);    (*fp->parent->LayerFinish)(fp->parent->object, fp);    break;  case ST_ACKRCVD:    NewState(fp, ST_REQSENT);    break;  case ST_OPENED:    (*fp->fn->LayerDown)(fp);    FsmSendConfigReq(fp);    NewState(fp, ST_REQSENT);    (*fp->parent->LayerDown)(fp->parent->object, fp);    break;  }  m_freem(bp);}static voidFsmRecvConfigRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp)/* RCJ */{  struct fsm_decode dec;  int plen, flen;  plen = m_length(bp);  flen = ntohs(lhp->length) - sizeof *lhp;  if (plen < flen) {    m_freem(bp);    return;  }  lcp_SendIdentification(&fp->link->lcp);  /*   * Check and process easy case   */  switch (fp->state) {  case ST_INITIAL:  case ST_STARTING:    log_Printf(fp->LogLevel, "%s: Oops, RCJ in %s.\n",              fp->link->name, State2Nam(fp->state));    m_freem(bp);    return;  case ST_CLOSED:  case ST_STOPPED:    (*fp->fn->SendTerminateAck)(fp, lhp->id);    m_freem(bp);    return;  case ST_CLOSING:  case ST_STOPPING:    m_freem(bp);    return;  }  bp = m_pullup(bp);  dec.ackend = dec.ack;  dec.nakend = dec.nak;  dec.rejend = dec.rej;  (*fp->fn->DecodeConfig)(fp, MBUF_CTOP(bp), flen, MODE_REJ, &dec);  if (flen < sizeof(struct fsmconfig))    log_Printf(fp->LogLevel, "  [EMPTY]\n");  switch (fp->state) {  case ST_REQSENT:  case ST_ACKSENT:    FsmInitRestartCounter(fp, FSM_REQ_TIMER);    FsmSendConfigReq(fp);    break;  case ST_OPENED:    (*fp->fn->LayerDown)(fp);    FsmSendConfigReq(fp);    NewState(fp, ST_REQSENT);    (*fp->parent->LayerDown)(fp->parent->object, fp);    break;  case ST_ACKRCVD:    FsmSendConfigReq(fp);    NewState(fp, ST_REQSENT);    break;  }  m_freem(bp);}static voidFsmRecvCodeRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp){  m_freem(bp);}static voidFsmRecvProtoRej(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp){  struct physical *p = link2physical(fp->link);  u_short proto;  if (m_length(bp) < 2) {    m_freem(bp);    return;  }  bp = mbuf_Read(bp, &proto, 2);  proto = ntohs(proto);  log_Printf(fp->LogLevel, "%s: -- Protocol 0x%04x (%s) was rejected!\n",            fp->link->name, proto, hdlc_Protocol2Nam(proto));  switch (proto) {  case PROTO_LQR:    if (p)      lqr_Stop(p, LQM_LQR);    else      log_Printf(LogERROR, "%s: FsmRecvProtoRej: Not a physical link !\n",                fp->link->name);    break;  case PROTO_CCP:    if (fp->proto == PROTO_LCP) {      fp = &fp->link->ccp.fsm;      /* Despite the RFC (1661), don't do an out-of-place TLF */      /* (*fp->fn->LayerFinish)(fp); */      switch (fp->state) {      case ST_CLOSED:      case ST_CLOSING:        NewState(fp, ST_CLOSED);        break;      default:        NewState(fp, ST_STOPPED);        break;      }      /* See above */      /* (*fp->parent->LayerFinish)(fp->parent->object, fp); */    }    break;  case PROTO_IPCP:    if (fp->proto == PROTO_LCP) {      log_Printf(LogPHASE, "%s: IPCP protocol reject closes IPCP !\n",                fp->link->name);      fsm_Close(&fp->bundle->ncp.ipcp.fsm);    }    break;#ifndef NOINET6  case PROTO_IPV6CP:    if (fp->proto == PROTO_LCP) {      log_Printf(LogPHASE, "%s: IPV6CP protocol reject closes IPV6CP !\n",                fp->link->name);      fsm_Close(&fp->bundle->ncp.ipv6cp.fsm);    }    break;#endif  case PROTO_MP:    if (fp->proto == PROTO_LCP) {      struct lcp *lcp = fsm2lcp(fp);      if (lcp->want_mrru && lcp->his_mrru) {        log_Printf(LogPHASE, "%s: MP protocol reject is fatal !\n",                  fp->link->name);        fsm_Close(fp);      }    }    break;  }  m_freem(bp);}static voidFsmRecvEchoReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp){  struct lcp *lcp = fsm2lcp(fp);  u_char *cp;  u_int32_t magic;  bp = m_pullup(bp);  m_settype(bp, MB_ECHOIN);  if (lcp && ntohs(lhp->length) - sizeof *lhp >= 4) {    cp = MBUF_CTOP(bp);    ua_ntohl(cp, &magic);    if (magic != lcp->his_magic) {      log_Printf(fp->LogLevel, "%s: RecvEchoReq: magic 0x%08lx is wrong,"                 " expecting 0x%08lx\n", fp->link->name, (u_long)magic,                 (u_long)lcp->his_magic);      /* XXX: We should send terminate request */    }    if (fp->state == ST_OPENED) {      ua_htonl(&lcp->want_magic, cp);		/* local magic */      fsm_Output(fp, CODE_ECHOREP, lhp->id, cp,                 ntohs(lhp->length) - sizeof *lhp, MB_ECHOOUT);    }  }  m_freem(bp);}static voidFsmRecvEchoRep(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp){  if (fsm2lcp(fp))    bp = lqr_RecvEcho(fp, bp);  m_freem(bp);}static voidFsmRecvDiscReq(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp){  m_freem(bp);}static voidFsmRecvIdent(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp){  u_int32_t magic;  u_short len;  u_char *cp;  len = ntohs(lhp->length) - sizeof *lhp;  if (len >= 4) {    bp = m_pullup(m_append(bp, "", 1));    cp = MBUF_CTOP(bp);    ua_ntohl(cp, &magic);    if (magic != fp->link->lcp.his_magic)      log_Printf(fp->LogLevel, "%s: RecvIdent: magic 0x%08lx is wrong,"                 " expecting 0x%08lx\n", fp->link->name, (u_long)magic,                 (u_long)fp->link->lcp.his_magic);    cp[len] = '\0';    lcp_RecvIdentification(&fp->link->lcp, cp + 4);  }  m_freem(bp);}static voidFsmRecvTimeRemain(struct fsm *fp, struct fsmheader *lhp, struct mbuf *bp){  m_freem(bp);}