Exemple #1
0
// Perform all processing to get an IP address plus other addresses returned, e.g. gw, dns, dhcp server.
// Returns 1 for successful IP address allocation, 0 otherwise
uint8_t EtherShield::allocateIPAddress(uint8_t *buf, uint16_t buffer_size, uint8_t *mymac, uint16_t myport, uint8_t *myip, uint8_t *mynetmask, uint8_t *gwip, uint8_t *dnsip, uint8_t *dhcpsvrip ) {
  uint16_t dat_p;
  int plen = 0;
  long lastDhcpRequest = millis();
  uint8_t dhcpState = 0;
  boolean gotIp = false;
  uint8_t dhcpTries = 10;	// After 10 attempts fail gracefully so other action can be carried out

  dhcp_start( buf, mymac, myip, mynetmask,gwip, dnsip, dhcpsvrip );

  while( !gotIp ) {
    // handle ping and wait for a tcp packet
    plen = enc28j60PacketReceive(buffer_size, buf);
    dat_p=packetloop_icmp_tcp(buf,plen);
    if(dat_p==0) {
      int retstat = check_for_dhcp_answer( buf, plen);
      dhcpState = dhcp_state();
      // we are idle here
      if( dhcpState != DHCP_STATE_OK ) {
        if (millis() > (lastDhcpRequest + 10000L) ){
          lastDhcpRequest = millis();
	  if( --dhcpTries <= 0 ) 
		  return 0;		// Failed to allocate address
          // send dhcp
          dhcp_start( buf, mymac, myip, mynetmask,gwip, dnsip, dhcpsvrip );
        }
      } else {
        if( !gotIp ) {
          gotIp = true;

          //init the ethernet/ip layer:
          init_ip_arp_udp_tcp(mymac, myip, myport);

          // Set the Router IP
          client_set_gwip(gwip);  // e.g internal IP of dsl router

          // Set the DNS server IP address if required, or use default
          dnslkup_set_dnsip( dnsip );

        }
      }
    }
  }

  return 1;

}
static void _eth_spi_handle_frame() {
  u16_t rx_stat;
  int plen = enc28j60PacketReceive(ETHSPI_MAX_PKT_SIZE, ethspi.rxbuf, &rx_stat);
  if (plen == 0) {
    DBG(D_ETH, D_DEBUG, "ethspi no frame, rx_stat:%04x\n", rx_stat);
    return;
  }
#ifdef ETH_STATS
  ethspi.rx_frames++;
  ethspi.rx_data += plen;
#endif

  DBG(D_ETH, D_DEBUG, "ethspi got frame, len %i, rx_stat:%04x\n", plen, rx_stat);
  //printbuf(ethspi.rxbuf, MIN(64, plen));
  // doing dhcp, do not allow anything else right now
  if (ethspi.dhcp.query && ethspi.dhcp.active) {
    int dhcp_res;
    dhcp_res = check_for_dhcp_answer(ethspi.rxbuf, plen);
    DBG(D_ETH, D_DEBUG, "ethspi DHCP:%i state:%i\n", dhcp_res, dhcp_state());
    if (dhcp_state() == DHCP_STATE_OK) {
      ethspi.dhcp.query = FALSE;
      DBG(D_ETH, D_DEBUG, "ethspi DHCP OK\n");
      DBG(D_ETH, D_INFO, "ethspi DHCP ip   %i.%i.%i.%i\n", ethspi.dhcp.ipaddr[0], ethspi.dhcp.ipaddr[1], ethspi.dhcp.ipaddr[2], ethspi.dhcp.ipaddr[3]);
      DBG(D_ETH, D_DEBUG, "ethspi DHCP gwip %i.%i.%i.%i\n", ethspi.dhcp.gwip[0], ethspi.dhcp.gwip[1], ethspi.dhcp.gwip[2], ethspi.dhcp.gwip[3]);
      DBG(D_ETH, D_DEBUG, "ethspi DHCP mask %i.%i.%i.%i\n", ethspi.dhcp.mask[0], ethspi.dhcp.mask[1], ethspi.dhcp.mask[2], ethspi.dhcp.mask[3]);
      DBG(D_ETH, D_DEBUG, "ethspi DHCP dhcp %i.%i.%i.%i\n", ethspi.dhcp.dhcp_server[0], ethspi.dhcp.dhcp_server[1], ethspi.dhcp.dhcp_server[2], ethspi.dhcp.dhcp_server[3]);
      DBG(D_ETH, D_DEBUG, "ethspi DHCP dns  %i.%i.%i.%i\n", ethspi.dhcp.dns_server[0], ethspi.dhcp.dns_server[1], ethspi.dhcp.dns_server[2], ethspi.dhcp.dns_server[3]);
      memcpy(ip_address, ethspi.dhcp.ipaddr, 4);
      set_ip(ethspi.dhcp.ipaddr);
      client_set_gwip(ethspi.dhcp.gwip);
#ifdef CONFIG_ETH_DHCP_SHOW
      print("eth ip address %i.%i.%i.%i\n", ethspi.dhcp.ipaddr[0], ethspi.dhcp.ipaddr[1], ethspi.dhcp.ipaddr[2], ethspi.dhcp.ipaddr[3]);
#endif
    }
    return;
  }

  // arp is broadcast if unknown but a host may also
  // verify the mac address by sending it to
  // a unicast address.
  if (eth_type_is_arp_and_my_ip(ethspi.rxbuf, plen)) {
    make_arp_answer_from_request(ethspi.rxbuf);
    return;
  }

  // check if ip frames (icmp or udp) are for us or broadcast:
  if (eth_type_is_ip_and_broadcast(ethspi.rxbuf, plen) == 0) {
    if (eth_type_is_ip_and_my_ip(ethspi.rxbuf, plen) == 0) {
      return;
    }
    if (ethspi.rxbuf[IP_PROTO_P]==IP_PROTO_ICMP_V &&
        ethspi.rxbuf[ICMP_TYPE_P]==ICMP_TYPE_ECHOREQUEST_V){
      // a ping frame, let's send pong
      make_echo_reply_from_request(ethspi.rxbuf, plen);
      return;
    }
  }

#if 0
  // we listen on port 0xcafe
  if (ethspi.rxbuf[IP_PROTO_P] == IP_PROTO_UDP_V
      && ethspi.rxbuf[UDP_DST_PORT_H_P] == 0xca  && ethspi.rxbuf[UDP_DST_PORT_L_P] == 0xf) {
    int payloadlen = ethspi.rxbuf[UDP_LEN_L_P];//plen - 34 - UDP_HEADER_LEN;
    DBG(D_ETH, D_DEBUG, "ethspi UDP len:%i\n", payloadlen);
    //char *nisse = "hello wurlde";
    //make_udp_reply_from_request(ethbuf, nisse, strlen(nisse), 1200);
    DBG(D_ETH, D_DEBUG, "ethspi eth mac dst: %02x.%02x.%02x.%02x.%02x.%02x\n",
        ethspi.rxbuf[0], ethspi.rxbuf[1], ethspi.rxbuf[2], ethspi.rxbuf[3], ethspi.rxbuf[4], ethspi.rxbuf[5]); // ETH_DST_MAC
    DBG(D_ETH, D_DEBUG, "ethspi eth mac src: %02x.%02x.%02x.%02x.%02x.%02x\n",
        ethspi.rxbuf[6], ethspi.rxbuf[7], ethspi.rxbuf[8], ethspi.rxbuf[9], ethspi.rxbuf[10], ethspi.rxbuf[11]); // ETH_SRC_MAC
    DBG(D_ETH, D_DEBUG, "ethspi eth type:    %02x %02x\n",
        ethspi.rxbuf[12], ethspi.rxbuf[13]); // ETH_TYPE_H_P, ETH_TYPE_L_P
    DBG(D_ETH, D_DEBUG, "ethspi ip src:  %i.%i.%i.%i\n",
        ethspi.rxbuf[26], ethspi.rxbuf[27], ethspi.rxbuf[28], ethspi.rxbuf[29]); // IP_SRC_P
    DBG(D_ETH, D_DEBUG, "ethspi ip dst:  %i.%i.%i.%i\n",
        ethspi.rxbuf[30], ethspi.rxbuf[31], ethspi.rxbuf[32], ethspi.rxbuf[33]); // IP_DST_P
    DBG(D_ETH, D_DEBUG, "ethspi udp src port:  %i\n",
        (ethspi.rxbuf[34] << 8) | ethspi.rxbuf[35]); // UDP_SRC_PORT_H_P
    DBG(D_ETH, D_DEBUG, "ethspi udp dst port:  %i\n",
        (ethspi.rxbuf[36] << 8) | ethspi.rxbuf[37]); // UDP_DST_PORT_H_P
    DBG(D_ETH, D_DEBUG, "ethspi udp len:       %04x\n",
        (ethspi.rxbuf[38] << 8) | ethspi.rxbuf[39]); // UDP_LEN_H_P
    DBG(D_ETH, D_DEBUG, "ethspi udp checksum:  %04x\n",
        (ethspi.rxbuf[40] << 8) | ethspi.rxbuf[41]); // UDP_CHECKSUM_H_P
  }
  IF_DBG(D_ETH, D_DEBUG) {
    printbuf(&ethspi.rxbuf[0], plen);
  }
Exemple #3
0
// This handles both the initialisation of DHCP, and subsequent
// renegotiations.  Lacking a dedicated timer, EtherCard::dhcpLease()
// must be called on a regular basis to keep things on track.
//
// Returns:     True    Success
//              False   Otherwise
//
static bool dhcp_fsm () {
    // Enable reception of broadcast packets as some DHCP servers
    // use this to send responses. Use only in DHCP_STATE_INIT ???
    EtherCard::enableBroadcast();

    // We typically wait up to 20 seconds for an answer
    uint32_t end = millis() + DHCP_WAIT;
    while (dhcpState != DHCP_STATE_BOUND && millis() < end) {
        byte rc = DHCP_STATE_BAD;
        word len = 0;

        // We have no hardware link, so no further point
        if (!EtherCard::isLinkUp())
            continue;

        // Get a packet, and check it's ok. packetReceive returns the
        // sum of the source address (6), the destination address (6),
        // the type/length (2), and the data/padding (46-1500) fields.
        // The trailing CRC field (4) is dropped by the software.
        // packetLoop(), unfortunately, is strange and undocumented.
        if (dhcpState != DHCP_STATE_INIT) {
            len = EtherCard::packetReceive();
            // Reject inadequate packets
            if (len == 0 || EtherCard::packetLoop(len) > 0)
                continue;
#if 0
            // These are a waste of space
            // Reject ARP packets
            if (gPB[ETHTYPE_IP_H_V] == ETHTYPE_ARP_H_V &&
                        gPB[ETHTYPE_IP_L_V] == ETHTYPE_ARP_L_V)
                continue;
            // Reject ICMP packets (why are they here ???)
            if (gPB[IP_PROTO_P] == IP_PROTO_ICMP_V)
                continue;
#endif
            // Reject everything but UDP packets
            if (gPB[IP_PROTO_P] != IP_PROTO_UDP_V)
                continue;
        }

        // Switch between DHCP states.  This is a pretty
        // minimal DHCP state machine, but it should be
        // reliable, if slow.
        switch (dhcpState) {
        case DHCP_STATE_INIT:
            EtherCard::copyIp(EtherCard::myip, allZeros);
            EtherCard::copyIp(EtherCard::dhcpip, allZeros);
            currentXid = millis();
            currentXid = (currentXid << 16) + millis();
            dhcp_send(DHCP_MSG_DISCOVER, true);
            dhcpState = DHCP_STATE_SELECT;
            leaseStart = 0; // Set an invalid start time
            break;
        case DHCP_STATE_SELECT:
            if (check_for_dhcp_answer(len) == DHCP_STATE_SELECT) {
                parse_dhcpoffer(len);
                dhcp_send(DHCP_MSG_REQUEST, false);
                dhcpState = DHCP_STATE_REQUEST;
            }
            else
                dhcpState = DHCP_STATE_INIT;
            break;
        case DHCP_STATE_REQUEST:
            if (check_for_dhcp_answer(len) == DHCP_STATE_REQUEST) {
                dhcpState = DHCP_STATE_BOUND;
                leaseStart = millis();
            }
            else
                dhcpState = DHCP_STATE_INIT;
            break;
        case DHCP_STATE_BOUND:
            // Lease timed at 50%   :  move to DHCP_STATE_RENEW
            // We're only bounced out of this state by a timer.
            // Otherwise just hang on to the lease.
            break;
        case DHCP_STATE_RENEW:
            // Lease timed at 87.5% :  move to DHCP_STATE_REBIND
            // Otherwise just hang on to the lease if possible.
            rc = check_for_dhcp_answer(len);
            if (rc == DHCP_STATE_BOUND) {
                dhcpState = DHCP_STATE_BOUND;
                leaseStart = millis();
            }
            else if (rc == DHCP_STATE_INIT)
                dhcpState = DHCP_STATE_INIT;
            break;
        case DHCP_STATE_REBIND:
            // Lease timed at 100%  :  move to DHCP_STATE_INIT
            // Otherwise just hang on to the lease if possible.
            rc = check_for_dhcp_answer(len);
            if (rc == DHCP_STATE_BOUND) {
                dhcpState = DHCP_STATE_BOUND;
                leaseStart = millis();
            }
            else if (rc == DHCP_STATE_INIT)
                dhcpState = DHCP_STATE_INIT;
            break;
        // Never happen
        default:
            dhcpState = DHCP_STATE_INIT;
            break;
        }
    }

    EtherCard::disableBroadcast();

    // Did we get here with an IP or a timeout?
    if (EtherCard::myip[0] != 0) {
        if (EtherCard::gwip[0] != 0)
            EtherCard::setGwIp(EtherCard::gwip);
        return true;
    }

    return false;
}
Exemple #4
0
uint8_t EtherShield::ES_check_for_dhcp_answer(uint8_t *buf,uint16_t plen){
	return( check_for_dhcp_answer( buf, plen) );
}