⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ipcp.c

📁 基于STM32F107的UDP服务器程序
💻 C
📖 第 1 页 / 共 3 页
字号:
         * then accept it.
         */
        GETLONG(tl, p);    /* Parse source address (his) */
        ciaddr1 = htonl(tl);
        IPCPDEBUG((LOG_INFO, "his addr %s\n", inet_ntoa(ciaddr1)));
        if (ciaddr1 != wo->hisaddr
            && (ciaddr1 == 0 || !wo->accept_remote)) {
          orc = CONFNAK;
          if (!reject_if_disagree) {
            DECPTR(sizeof(u32_t), p);
            tl = ntohl(wo->hisaddr);
            PUTLONG(tl, p);
          }
        } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
          /*
           * If neither we nor he knows his address, reject the option.
           */
          orc = CONFREJ;
          wo->req_addr = 0;  /* don't NAK with 0.0.0.0 later */
          break;
        }

        /*
         * If he doesn't know our address, or if we both have our address
         * but disagree about it, then NAK it with our idea.
         */
        GETLONG(tl, p);    /* Parse desination address (ours) */
        ciaddr2 = htonl(tl);
        IPCPDEBUG((LOG_INFO, "our addr %s\n", inet_ntoa(ciaddr2)));
        if (ciaddr2 != wo->ouraddr) {
          if (ciaddr2 == 0 || !wo->accept_local) {
            orc = CONFNAK;
            if (!reject_if_disagree) {
              DECPTR(sizeof(u32_t), p);
              tl = ntohl(wo->ouraddr);
              PUTLONG(tl, p);
            }
          } else {
            go->ouraddr = ciaddr2;  /* accept peer's idea */
          }
        }

        ho->neg_addr = 1;
        ho->old_addrs = 1;
        ho->hisaddr = ciaddr1;
        ho->ouraddr = ciaddr2;
        break;
#endif

      case CI_ADDR:
        if (!ao->neg_addr) {
          IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR not allowed\n"));
          orc = CONFREJ;        /* Reject CI */
          break;
        } else if (cilen != CILEN_ADDR) {  /* Check CI length */
          IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR bad len\n"));
          orc = CONFREJ;        /* Reject CI */
          break;
        }

        /*
         * If he has no address, or if we both have his address but
         * disagree about it, then NAK it with our idea.
         * In particular, if we don't know his address, but he does,
         * then accept it.
         */
        GETLONG(tl, p);  /* Parse source address (his) */
        ciaddr1 = htonl(tl);
        if (ciaddr1 != wo->hisaddr
            && (ciaddr1 == 0 || !wo->accept_remote)) {
          orc = CONFNAK;
          if (!reject_if_disagree) {
            DECPTR(sizeof(u32_t), p);
            tl = ntohl(wo->hisaddr);
            PUTLONG(tl, p);
          }
          IPCPDEBUG((LOG_INFO, "ipcp_reqci: Nak ADDR %s\n", inet_ntoa(ciaddr1)));
        } else if (ciaddr1 == 0 && wo->hisaddr == 0) {
          /*
           * Don't ACK an address of 0.0.0.0 - reject it instead.
           */
          IPCPDEBUG((LOG_INFO, "ipcp_reqci: Reject ADDR %s\n", inet_ntoa(ciaddr1)));
          orc = CONFREJ;
          wo->req_addr = 0;  /* don't NAK with 0.0.0.0 later */
          break;
        }

        ho->neg_addr = 1;
        ho->hisaddr = ciaddr1;
        IPCPDEBUG((LOG_INFO, "ipcp_reqci: ADDR %s\n", inet_ntoa(ciaddr1)));
        break;

      case CI_MS_DNS1:
      case CI_MS_DNS2:
        /* Microsoft primary or secondary DNS request */
        d = citype == CI_MS_DNS2;

        /* If we do not have a DNS address then we cannot send it */
        if (ao->dnsaddr[d] == 0 ||
            cilen != CILEN_ADDR) {  /* Check CI length */
          IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting DNS%d Request\n", d+1));
          orc = CONFREJ;        /* Reject CI */
          break;
        }
        GETLONG(tl, p);
        if (htonl(tl) != ao->dnsaddr[d]) {
          IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking DNS%d Request %d\n",
                d+1, inet_ntoa(tl)));
          DECPTR(sizeof(u32_t), p);
          tl = ntohl(ao->dnsaddr[d]);
          PUTLONG(tl, p);
          orc = CONFNAK;
        }
        IPCPDEBUG((LOG_INFO, "ipcp_reqci: received DNS%d Request\n", d+1));
        break;

      case CI_MS_WINS1:
      case CI_MS_WINS2:
        /* Microsoft primary or secondary WINS request */
        d = citype == CI_MS_WINS2;
        IPCPDEBUG((LOG_INFO, "ipcp_reqci: received WINS%d Request\n", d+1));

        /* If we do not have a DNS address then we cannot send it */
        if (ao->winsaddr[d] == 0 ||
          cilen != CILEN_ADDR) {  /* Check CI length */
          orc = CONFREJ;      /* Reject CI */
          break;
        }
        GETLONG(tl, p);
        if (htonl(tl) != ao->winsaddr[d]) {
          DECPTR(sizeof(u32_t), p);
          tl = ntohl(ao->winsaddr[d]);
          PUTLONG(tl, p);
          orc = CONFNAK;
        }
        break;

      case CI_COMPRESSTYPE:
        if (!ao->neg_vj) {
          IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE not allowed\n"));
          orc = CONFREJ;
          break;
        } else if (cilen != CILEN_VJ && cilen != CILEN_COMPRESS) {
          IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE len=%d\n", cilen));
          orc = CONFREJ;
          break;
        }
        GETSHORT(cishort, p);

        if (!(cishort == IPCP_VJ_COMP ||
            (cishort == IPCP_VJ_COMP_OLD && cilen == CILEN_COMPRESS))) {
          IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting COMPRESSTYPE %d\n", cishort));
          orc = CONFREJ;
          break;
        }

        ho->neg_vj = 1;
        ho->vj_protocol = cishort;
        if (cilen == CILEN_VJ) {
          GETCHAR(maxslotindex, p);
          if (maxslotindex > ao->maxslotindex) { 
            IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking VJ max slot %d\n", maxslotindex));
            orc = CONFNAK;
            if (!reject_if_disagree) {
              DECPTR(1, p);
              PUTCHAR(ao->maxslotindex, p);
            }
          }
          GETCHAR(cflag, p);
          if (cflag && !ao->cflag) {
            IPCPDEBUG((LOG_INFO, "ipcp_reqci: Naking VJ cflag %d\n", cflag));
            orc = CONFNAK;
            if (!reject_if_disagree) {
              DECPTR(1, p);
              PUTCHAR(wo->cflag, p);
            }
          }
          ho->maxslotindex = maxslotindex;
          ho->cflag = cflag;
        } else {
          ho->old_vj = 1;
          ho->maxslotindex = MAX_SLOTS - 1;
          ho->cflag = 1;
        }
        IPCPDEBUG((LOG_INFO, 
              "ipcp_reqci: received COMPRESSTYPE p=%d old=%d maxslot=%d cflag=%d\n",
              ho->vj_protocol, ho->old_vj, ho->maxslotindex, ho->cflag));
        break;

      default:
        IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting unknown CI type %d\n", citype));
        orc = CONFREJ;
        break;
    }

endswitch:
    if (orc == CONFACK &&    /* Good CI */
        rc != CONFACK) {     /*  but prior CI wasnt? */
      continue;              /* Don't send this one */
    }

    if (orc == CONFNAK) {    /* Nak this CI? */
      if (reject_if_disagree) {  /* Getting fed up with sending NAKs? */
        IPCPDEBUG((LOG_INFO, "ipcp_reqci: Rejecting too many naks\n"));
        orc = CONFREJ;       /* Get tough if so */
      } else {
        if (rc == CONFREJ) { /* Rejecting prior CI? */
          continue;          /* Don't send this one */
        }
        if (rc == CONFACK) { /* Ack'd all prior CIs? */
          rc = CONFNAK;      /* Not anymore... */
          ucp = inp;         /* Backup */
        }
      }
    }

    if (orc == CONFREJ &&    /* Reject this CI */
        rc != CONFREJ) {  /*  but no prior ones? */
      rc = CONFREJ;
      ucp = inp;        /* Backup */
    }
    
    /* Need to move CI? */
    if (ucp != cip) {
      BCOPY(cip, ucp, cilen);  /* Move it */
    }

    /* Update output pointer */
    INCPTR(cilen, ucp);
  }

  /*
   * If we aren't rejecting this packet, and we want to negotiate
   * their address, and they didn't send their address, then we
   * send a NAK with a CI_ADDR option appended.  We assume the
   * input buffer is long enough that we can append the extra
   * option safely.
   */
  if (rc != CONFREJ && !ho->neg_addr &&
      wo->req_addr && !reject_if_disagree) {
    IPCPDEBUG((LOG_INFO, "ipcp_reqci: Requesting peer address\n"));
    if (rc == CONFACK) {
      rc = CONFNAK;
      ucp = inp;        /* reset pointer */
      wo->req_addr = 0;    /* don't ask again */
    }
    PUTCHAR(CI_ADDR, ucp);
    PUTCHAR(CILEN_ADDR, ucp);
    tl = ntohl(wo->hisaddr);
    PUTLONG(tl, ucp);
  }

  *len = (int)(ucp - inp);    /* Compute output length */
  IPCPDEBUG((LOG_INFO, "ipcp_reqci: returning Configure-%s\n", CODENAME(rc)));
  return (rc);      /* Return final code */
}


#if 0
/*
 * ip_check_options - check that any IP-related options are OK,
 * and assign appropriate defaults.
 */
static void
ip_check_options(u_long localAddr)
{
  ipcp_options *wo = &ipcp_wantoptions[0];

  /*
   * Load our default IP address but allow the remote host to give us
   * a new address.
   */
  if (wo->ouraddr == 0 && !ppp_settings.disable_defaultip) {
    wo->accept_local = 1;  /* don't insist on this default value */
    wo->ouraddr = htonl(localAddr);
  }
}
#endif


/*
 * ipcp_up - IPCP has come UP.
 *
 * Configure the IP network interface appropriately and bring it up.
 */
static void
ipcp_up(fsm *f)
{
  u32_t mask;
  ipcp_options *ho = &ipcp_hisoptions[f->unit];
  ipcp_options *go = &ipcp_gotoptions[f->unit];
  ipcp_options *wo = &ipcp_wantoptions[f->unit];

  np_up(f->unit, PPP_IP);
  IPCPDEBUG((LOG_INFO, "ipcp: up\n"));

  /*
   * We must have a non-zero IP address for both ends of the link.
   */
  if (!ho->neg_addr) {
    ho->hisaddr = wo->hisaddr;
  }

  if (ho->hisaddr == 0) {
    IPCPDEBUG((LOG_ERR, "Could not determine remote IP address\n"));
    ipcp_close(f->unit, "Could not determine remote IP address");
    return;
  }
  if (go->ouraddr == 0) {
    IPCPDEBUG((LOG_ERR, "Could not determine local IP address\n"));
    ipcp_close(f->unit, "Could not determine local IP address");
    return;
  }

  if (ppp_settings.usepeerdns && (go->dnsaddr[0] || go->dnsaddr[1])) {
    /*pppGotDNSAddrs(go->dnsaddr[0], go->dnsaddr[1]);*/
  }

  /*
   * Check that the peer is allowed to use the IP address it wants.
   */
  if (!auth_ip_addr(f->unit, ho->hisaddr)) {
    IPCPDEBUG((LOG_ERR, "Peer is not authorized to use remote address %s\n",
        inet_ntoa(ho->hisaddr)));
    ipcp_close(f->unit, "Unauthorized remote IP address");
    return;
  }

  /* set tcp compression */
  sifvjcomp(f->unit, ho->neg_vj, ho->cflag, ho->maxslotindex);

  /*
   * Set IP addresses and (if specified) netmask.
   */
  mask = GetMask(go->ouraddr);

  if (!sifaddr(f->unit, go->ouraddr, ho->hisaddr, mask, go->dnsaddr[0], go->dnsaddr[1])) {
    IPCPDEBUG((LOG_WARNING, "sifaddr failed\n"));
    ipcp_close(f->unit, "Interface configuration failed");
    return;
  }

  /* bring the interface up for IP */
  if (!sifup(f->unit)) {
    IPCPDEBUG((LOG_WARNING, "sifup failed\n"));
    ipcp_close(f->unit, "Interface configuration failed");
    return;
  }

  sifnpmode(f->unit, PPP_IP, NPMODE_PASS);

  /* assign a default route through the interface if required */
  if (ipcp_wantoptions[f->unit].default_route) {
    if (sifdefaultroute(f->unit, go->ouraddr, ho->hisaddr)) {
      default_route_set[f->unit] = 1;
    }
  }

  IPCPDEBUG((LOG_NOTICE, "local  IP address %s\n", inet_ntoa(go->ouraddr)));
  IPCPDEBUG((LOG_NOTICE, "remote IP address %s\n", inet_ntoa(ho->hisaddr)));
  if (go->dnsaddr[0]) {
    IPCPDEBUG((LOG_NOTICE, "primary   DNS address %s\n", inet_ntoa(go->dnsaddr[0])));
  }
  if (go->dnsaddr[1]) {
    IPCPDEBUG((LOG_NOTICE, "secondary DNS address %s\n", inet_ntoa(go->dnsaddr[1])));
  }
}


/*
 * ipcp_down - IPCP has gone DOWN.
 *
 * Take the IP network interface down, clear its addresses
 * and delete routes through it.
 */
static void
ipcp_down(fsm *f)
{
  IPCPDEBUG((LOG_INFO, "ipcp: down\n"));
  np_down(f->unit, PPP_IP);
  sifvjcomp(f->unit, 0, 0, 0);

  sifdown(f->unit);
  ipcp_clear_addrs(f->unit);
}


/*
 * ipcp_clear_addrs() - clear the interface addresses, routes, etc.
 */
static void
ipcp_clear_addrs(int unit)
{
  u32_t ouraddr, hisaddr;

  ouraddr = ipcp_gotoptions[unit].ouraddr;
  hisaddr = ipcp_hisoptions[unit].hisaddr;
  if (default_route_set[unit]) {
    cifdefaultroute(unit, ouraddr, hisaddr);
    default_route_set[unit] = 0;
  }
  cifaddr(unit, ouraddr, hisaddr);
}


/*
 * ipcp_finished - possibly shut down the lower layers.
 */
static void
ipcp_finished(fsm *f)
{
  np_finished(f->unit, PPP_IP);
}

#if 0
static int
ipcp_printpkt(u_char *p, int plen, void (*printer) (void *, char *, ...), void *arg)
{
  LWIP_UNUSED_ARG(p);
  LWIP_UNUSED_ARG(plen);
  LWIP_UNUSED_ARG(printer);
  LWIP_UNUSED_ARG(arg);
  return 0;
}

/*
 * ip_active_pkt - see if this IP packet is worth bringing the link up for.
 * We don't bring the link up for IP fragments or for TCP FIN packets
 * with no data.
 */
#define IP_HDRLEN   20  /* bytes */
#define IP_OFFMASK  0x1fff
#define IPPROTO_TCP 6
#define TCP_HDRLEN  20
#define TH_FIN      0x01

/*
 * We use these macros because the IP header may be at an odd address,
 * and some compilers might use word loads to get th_off or ip_hl.
 */

#define net_short(x)    (((x)[0] << 8) + (x)[1])
#define get_iphl(x)     (((unsigned char *)(x))[0] & 0xF)
#define get_ipoff(x)    net_short((unsigned char *)(x) + 6)
#define get_ipproto(x)  (((unsigned char *)(x))[9])
#define get_tcpoff(x)   (((unsigned char *)(x))[12] >> 4)
#define get_tcpflags(x) (((unsigned char *)(x))[13])

static int
ip_active_pkt(u_char *pkt, int len)
{
  u_char *tcp;
  int hlen;

  len -= PPP_HDRLEN;
  pkt += PPP_HDRLEN;
  if (len < IP_HDRLEN) {
    return 0;
  }
  if ((get_ipoff(pkt) & IP_OFFMASK) != 0) {
    return 0;
  }
  if (get_ipproto(pkt) != IPPROTO_TCP) {
    return 1;
  }
  hlen = get_iphl(pkt) * 4;
  if (len < hlen + TCP_HDRLEN) {
    return 0;
  }
  tcp = pkt + hlen;
  if ((get_tcpflags(tcp) & TH_FIN) != 0 && len == hlen + get_tcpoff(tcp) * 4) {
    return 0;
  }
  return 1;
}
#endif

#endif /* PPP_SUPPORT */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -