Example #1
0
static void
CcpDecodeConfig(Fsm fp, FsmOption list, int num, int mode)
{
    Bund 	b = (Bund)fp->arg;
  CcpState	const ccp = &b->ccp;
  u_int		ackSizeSave, rejSizeSave;
  int		k, rej;

  /* Forget our previous choice on new request */
  if (mode == MODE_REQ)
    ccp->recv = NULL;

  /* Decode each config option */
  for (k = 0; k < num; k++) {
    FsmOption	const opt = &list[k];
    int		index;
    CompType	ct;
    char	buf[32];

    Log(LG_CCP, ("[%s]   %s", b->name, CcpTypeName(opt->type, buf, sizeof(buf))));
    if ((ct = CcpFindComp(opt->type, &index)) == NULL) {
      if (mode == MODE_REQ) {
	Log(LG_CCP, ("[%s]     Not supported", b->name));
	FsmRej(fp, opt);
      }
      continue;
    }
    switch (mode) {
      case MODE_REQ:
	ackSizeSave = gAckSize;
	rejSizeSave = gRejSize;
	rej = (!Acceptable(&ccp->options, index)
	  || CCP_SELF_REJECTED(ccp, index)
	  || (ccp->recv && ccp->recv != ct));
	if (rej) {
	  (*ct->DecodeConfig)(fp, opt, MODE_NOP);
	  FsmRej(fp, opt);
	  break;
	}
	(*ct->DecodeConfig)(fp, opt, mode);
	if (gRejSize != rejSizeSave) {		/* we rejected it */
	  CCP_SELF_REJ(ccp, index);
	  break;
	}
	if (gAckSize != ackSizeSave)		/* we accepted it */
	  ccp->recv = ct;
	break;

      case MODE_REJ:
	(*ct->DecodeConfig)(fp, opt, mode);
	CCP_PEER_REJ(ccp, index);
	break;

      case MODE_NAK:
      case MODE_NOP:
	(*ct->DecodeConfig)(fp, opt, mode);
	break;
    }
  }
}
Example #2
0
static void
Ipv6cpDecodeConfig(Fsm fp, FsmOption list, int num, int mode)
{
	Bund b = (Bund) fp->arg;
	Ipv6cpState const ipv6cp = &b->ipv6cp;
	int k;

	/* Decode each config option */
	for (k = 0; k < num; k++) {
		FsmOption const opt = &list[k];
		FsmOptInfo const oi = FsmFindOptInfo(gIpv6cpConfOpts, opt->type);

		if (!oi) {
			Log(LG_IPV6CP, ("[%s]   UNKNOWN[%d] len=%d", b->name, opt->type, opt->len));
			if (mode == MODE_REQ)
				FsmRej(fp, opt);
			continue;
		}
		if (!oi->supported) {
			Log(LG_IPV6CP, ("[%s]   %s", b->name, oi->name));
			if (mode == MODE_REQ) {
				Log(LG_IPV6CP, ("[%s]     Not supported", b->name));
				FsmRej(fp, opt);
			}
			continue;
		}
		if (opt->len < oi->minLen + 2 || opt->len > oi->maxLen + 2) {
			Log(LG_IPV6CP, ("[%s]   %s", b->name, oi->name));
			if (mode == MODE_REQ) {
				Log(LG_IPV6CP, ("[%s]     bogus len=%d min=%d max=%d", b->name, opt->len, oi->minLen + 2, oi->maxLen + 2));
				FsmRej(fp, opt);
			}
			continue;
		}
		switch (opt->type) {
		case TY_INTIDENT:
			{
				Log(LG_IPV6CP2, ("[%s]   %s %02x%02x:%02x%02x:%02x%02x:%02x%02x", b->name, oi->name,
				    opt->data[0], opt->data[1], opt->data[2], opt->data[3],
				    opt->data[4], opt->data[5], opt->data[6], opt->data[7]));
				switch (mode) {
				case MODE_REQ:
					if ((((u_int32_t *)opt->data)[0] == 0) && (((u_int32_t *)opt->data)[1] == 0)) {
						Log(LG_IPV6CP2, ("[%s]     Empty INTIDENT, propose our.", b->name));
						CreateInterfaceID(ipv6cp->hisintid, 1);
						memcpy(opt->data, ipv6cp->hisintid, 8);
						FsmNak(fp, opt);
					} else if (bcmp(opt->data, ipv6cp->myintid, 8) == 0) {
						Log(LG_IPV6CP2, ("[%s]     Duplicate INTIDENT, generate and propose other.", b->name));
						CreateInterfaceID(ipv6cp->hisintid, 1);
						memcpy(opt->data, ipv6cp->hisintid, 8);
						FsmNak(fp, opt);
					} else {
						Log(LG_IPV6CP2, ("[%s]     It's OK.", b->name));
						memcpy(ipv6cp->hisintid, opt->data, 8);
						FsmAck(fp, opt);
					}
					break;
				case MODE_NAK:
					Log(LG_IPV6CP2, ("[%s]     I agree to get this to myself.", b->name));
					memcpy(ipv6cp->myintid, opt->data, 8);
					break;
				case MODE_REJ:
					IPV6CP_PEER_REJ(ipv6cp, opt->type);
					break;
				}
			}
			break;

		default:
			assert(0);
		}
	}
}
Example #3
0
static void
IpcpDecodeConfig(Fsm fp, FsmOption list, int num, int mode)
{
    Bund 	b = (Bund)fp->arg;
  IpcpState		const ipcp = &b->ipcp;
  struct in_addr	*wantip, *peerip;
  int			k;

  /* Decode each config option */
  for (k = 0; k < num; k++) {
    FsmOption	const opt = &list[k];
    FsmOptInfo	const oi = FsmFindOptInfo(gIpcpConfOpts, opt->type);

    if (!oi) {
      Log(LG_IPCP, ("[%s]   UNKNOWN[%d] len=%d", b->name, opt->type, opt->len));
      if (mode == MODE_REQ)
	FsmRej(fp, opt);
      continue;
    }
    if (!oi->supported) {
      Log(LG_IPCP, ("[%s]   %s", b->name, oi->name));
      if (mode == MODE_REQ) {
	Log(LG_IPCP, ("[%s]     Not supported", b->name));
	FsmRej(fp, opt);
      }
      continue;
    }
    if (opt->len < oi->minLen + 2 || opt->len > oi->maxLen + 2) {
      Log(LG_IPCP, ("[%s]   %s", b->name, oi->name));
      if (mode == MODE_REQ) {
	Log(LG_IPCP, ("[%s]     bogus len=%d", b->name, opt->len));
	FsmRej(fp, opt);
      }
      continue;
    }
    switch (opt->type) {
      case TY_IPADDR:
	{
	  struct in_addr	ip;
	  struct u_addr		tmp;

	  memcpy(&ip, opt->data, 4);
	  in_addrtou_addr(&ip, &tmp);
	  Log(LG_IPCP, ("[%s]   %s %s", b->name, oi->name, inet_ntoa(ip)));
	  switch (mode) {
	    case MODE_REQ:
	      if (!IpAddrInRange(&ipcp->peer_allow, &tmp) || !ip.s_addr) {
		if (ipcp->peer_addr.s_addr == 0)
		  Log(LG_IPCP, ("[%s]     no IP address available for peer!", b->name));
		if (Enabled(&ipcp->conf.options, IPCP_CONF_PRETENDIP)) {
		  Log(LG_IPCP, ("[%s]     pretending that %s is OK, will ignore",
		      b->name, inet_ntoa(ip)));
		  ipcp->peer_addr = ip;
		  FsmAck(fp, opt);
		  break;
		}
		memcpy(opt->data, &ipcp->peer_addr, 4);
		Log(LG_IPCP, ("[%s]     NAKing with %s", b->name, inet_ntoa(ipcp->peer_addr)));
		FsmNak(fp, opt);
		break;
	      }
	      Log(LG_IPCP, ("[%s]     %s is OK", b->name, inet_ntoa(ip)));
	      ipcp->peer_addr = ip;
	      FsmAck(fp, opt);
	      break;
	    case MODE_NAK:
	      {
		if (IpAddrInRange(&ipcp->self_allow, &tmp)) {
		  Log(LG_IPCP, ("[%s]     %s is OK", b->name, inet_ntoa(ip)));
		  ipcp->want_addr = ip;
		} else if (Enabled(&ipcp->conf.options, IPCP_CONF_PRETENDIP)) {
		  Log(LG_IPCP, ("[%s]     pretending that %s is OK, will ignore",
		      b->name, inet_ntoa(ip)));
		  ipcp->want_addr = ip;
		} else
		  Log(LG_IPCP, ("[%s]     %s is unacceptable", b->name, inet_ntoa(ip)));
	      }
	      break;
	    case MODE_REJ:
	      IPCP_PEER_REJ(ipcp, opt->type);
	      if (ipcp->want_addr.s_addr == 0)
		Log(LG_IPCP, ("[%s]     Problem: I need an IP address!", b->name));
	      break;
	  }
	}
	break;

#ifdef USE_NG_VJC
      case TY_COMPPROTO:
	{
	  struct ipcpvjcomp	vj;

	  memcpy(&vj, opt->data, sizeof(vj));
	  Log(LG_IPCP, ("[%s]   %s %s, %d comp. channels, %s comp-cid",
	    b->name, oi->name, ProtoName(ntohs(vj.proto)),
	    vj.maxchan + 1, vj.compcid ? "allow" : "no"));
	  switch (mode) {
	    case MODE_REQ:
	      if (!Acceptable(&ipcp->conf.options, IPCP_CONF_VJCOMP) && 
	    	  !b->params.vjc_enable) {
		FsmRej(fp, opt);
		break;
	      }
	      if (ntohs(vj.proto) == PROTO_VJCOMP
		  && vj.maxchan <= IPCP_VJCOMP_MAX_MAXCHAN
		  && vj.maxchan >= IPCP_VJCOMP_MIN_MAXCHAN) {
		ipcp->peer_comp = vj;
		FsmAck(fp, opt);
		break;
	      }
	      vj.proto = htons(PROTO_VJCOMP);
	      vj.maxchan = IPCP_VJCOMP_MAX_MAXCHAN;
	      vj.compcid = 0;
	      memcpy(opt->data, &vj, sizeof(vj));
	      FsmNak(fp, opt);
	      break;
	    case MODE_NAK:
	      if (ntohs(vj.proto) != PROTO_VJCOMP) {
		Log(LG_IPCP, ("[%s]     Can't accept proto 0x%04x",
		  b->name, (u_short) ntohs(vj.proto)));
		break;
	      }
	      if (vj.maxchan != ipcp->want_comp.maxchan) {
		if (vj.maxchan <= IPCP_VJCOMP_MAX_MAXCHAN
		    && vj.maxchan >= IPCP_VJCOMP_MIN_MAXCHAN) {
		  Log(LG_IPCP, ("[%s]     Adjusting # compression channels", b->name));
		  ipcp->want_comp.maxchan = vj.maxchan;
		} else {
		  Log(LG_IPCP, ("[%s]     Can't handle %d maxchan", b->name, vj.maxchan));
		}
	      }
	      if (vj.compcid) {
		Log(LG_IPCP, ("[%s]     Can't accept comp-cid", b->name));
		break;
	      }
	      break;
	    case MODE_REJ:
	      IPCP_PEER_REJ(ipcp, opt->type);
	      ipcp->want_comp.proto = 0;
	      break;
	  }
	}
	break;
#endif /* USE_NG_VJC */

      case TY_PRIMARYDNS:
        if (b->params.peer_dns[0].s_addr != 0)
	    peerip = &b->params.peer_dns[0];
	else
	    peerip = &ipcp->conf.peer_dns[0];
	wantip = &ipcp->want_dns[0];
	goto doDnsNbns;
      case TY_PRIMARYNBNS:
        if (b->params.peer_nbns[0].s_addr != 0)
	    peerip = &b->params.peer_nbns[0];
	else
	    peerip = &ipcp->conf.peer_nbns[0];
	wantip = &ipcp->want_nbns[0];
	goto doDnsNbns;
      case TY_SECONDARYDNS:
        if (b->params.peer_dns[1].s_addr != 0)
	    peerip = &b->params.peer_dns[1];
	else
	    peerip = &ipcp->conf.peer_dns[1];
	wantip = &ipcp->want_dns[1];
	goto doDnsNbns;
      case TY_SECONDARYNBNS:
        if (b->params.peer_nbns[1].s_addr != 0)
	    peerip = &b->params.peer_nbns[1];
	else
	    peerip = &ipcp->conf.peer_nbns[1];
	wantip = &ipcp->want_nbns[1];
doDnsNbns:
	{
	  struct in_addr	hisip;

	  memcpy(&hisip, opt->data, 4);
	  Log(LG_IPCP, ("[%s]   %s %s", b->name, oi->name, inet_ntoa(hisip)));
	  switch (mode) {
	    case MODE_REQ:
	      if (hisip.s_addr == 0) {		/* he's asking for one */
		if (peerip->s_addr == 0) {	/* we don't got one */
		  FsmRej(fp, opt);
		  break;
		}
		Log(LG_IPCP, ("[%s]     NAKing with %s", b->name, inet_ntoa(*peerip)));
		memcpy(opt->data, peerip, sizeof(*peerip));
		FsmNak(fp, opt);		/* we got one for him */
		break;
	      }
	      FsmAck(fp, opt);			/* he knows what he wants */
	      break;
	    case MODE_NAK:	/* we asked for his server, he's telling us */
	      *wantip = hisip;
	      break;
	    case MODE_REJ:	/* we asked for his server, he's ignorant */
	      IPCP_PEER_REJ(ipcp, opt->type);
	      break;
	  }
	}
	break;

      default:
	assert(0);
    }
  }
}