void enc424j600_receivecallback( uint16_t packetlen ) { uint8_t is_the_packet_for_me = 1; unsigned char i; unsigned char ipproto; //First and foremost, make sure we have a big enough packet to work with. if( packetlen < 8 ) { #ifdef ETH_DEBUG sendstr( "Runt\n" ); #endif return; } //macto (ignore) our mac filter handles this. enc424j600_dumpbytes( 6 ); POPB( macfrom, 6 ); //Make sure it's ethernet! if( POP != 0x08 ) { #ifdef ETH_DEBUG sendstr( "Not ethernet.\n" ); #endif return; } //Is it ARP? if( POP == 0x06 ) { HandleArp( ); return; } //otherwise it's standard IP //So, we're expecting a '45 if( POP != 0x45 ) { #ifdef ETH_DEBUG sendstr( "Not IP.\n" ); #endif return; } POP; //differentiated services field. iptotallen = POP16; enc424j600_dumpbytes( 5 ); //ID, Offset+FLAGS+TTL ipproto = POP; POP16; //header checksum POPB( ipsource, 4 ); for( i = 0; i < 4; i++ ) { unsigned char m = ~MyMask[i]; unsigned char ch = POP; if( ch == MyIP[i] || (ch & m) == 0xff ) continue; is_the_packet_for_me = 0; } //Tricky, for DHCP packets, we have to detect it even if it is not to us. if( ipproto == 17 ) { remoteport = POP16; localport = POP16; #ifdef ENABLE_DHCP_CLIENT if( localport == 68 && !dhcp_seconds_remain ) { HandleDHCP( POP16 ); return; } #endif } if( !is_the_packet_for_me ) { #ifdef ETH_DEBUG sendstr( "not for me\n" ); #endif return; } //XXX TODO Handle IPL > 5 (IHL?) switch( ipproto ) { case 1: //ICMP HandleICMP(); break; #ifdef INCLUDE_UDP case 17: { //err is this dangerous? HandleUDP( POP16 ); break; } #endif #ifdef INCLUDE_TCP case 6: // TCP { remoteport = POP16; localport = POP16; iptotallen-=20; HandleTCP( iptotallen ); break; } #endif // HAVE_TCP_SUPPORT default: break; } //finishcb: // enc424j600_finish_callback_now(); }
void HandleDHCP( uint16_t len ) { uint8_t tmpip[4]; uint8_t tmp[4]; uint8_t optionsleft = 48; //We only allow for up to 48 options uint8_t is_ack_packet = 0; uint16_t first4, second4; POP16; //Clear out checksum //Process DHCP! if( POP != 2 ) return; //Not a reply? if( POP != 1 ) return; //Not Ethernet? POP16; //size of packets + Hops //Make sure transaction IDs match. enc424j600_popblob( tmp, 4 ); if( memcmp( tmp, MyMAC, 4 ) != 0 ) { //Not our request? return; } enc424j600_dumpbytes( 8 ); //time elapsed + bootpflags + Client IP address enc424j600_popblob( tmpip, 4 ); //MY IP ADDRESS!!! enc424j600_dumpbytes( 0x18 + 0xc0 ); //Next IP + Relay IP + Mac + Padding + server name + boot name first4 = POP16; second4 = POP16; if( first4 != 0x6382 || second4 != 0x5363 ) { return; } //Ok, we know we have a valid DHCP packet. //We dont want to get stuck, so we will eventually bail if we have an issue pasrsing. while( optionsleft-- ) { uint8_t option = POP; uint8_t length = POP; switch(option) { case 0x35: //DHCP Message Type { if( length < 1 ) return; uint8_t rqt = POP; if( rqt == 0x02 ) { //We have an offer, extend a request. //We will ignore the rest of the packet. enc424j600_finish_callback_now(); RequestNewIP( 3, tmpip, ipsource ); //Request return; } else if( rqt == 0x05 ) // We received an ack, accept it. { //IP Is valid. is_ack_packet = 1; if( 0 == dhcp_seconds_remain ) dhcp_seconds_remain = 0xffff; memcpy( MyIP, tmpip, 4 ); } length--; break; } case 0x3a: //Renewal time { if( length < 4 || !is_ack_packet ) break; first4 = POP16; second4 = POP16; // printf( "LEASE TIME: %d %d\n", first4, second4 ); if( first4 ) { dhcp_seconds_remain = 0xffff; } else { dhcp_seconds_remain = second4; } length -= 4; break; } case 0x01: //Subnet mask { if( length < 4 || !is_ack_packet ) break; enc424j600_popblob( MyMask, 4 ); length -= 4; break; } case 0x03: //Router mask { if( length < 4 || !is_ack_packet ) break; enc424j600_popblob( MyGateway, 4 ); length -= 4; break; } case 0xff: //End of list. enc424j600_finish_callback_now(); if( is_ack_packet ) GotDHCPLease(); return; case 0x42: //Time server case 0x06: //DNS server default: break; } enc424j600_dumpbytes( length ); } }
int enc424j600_receivecallback( uint16_t packetlen ) { uint8_t is_the_packet_for_me = 1; unsigned char i; unsigned char ipproto; //First and foremost, make sure we have a big enough packet to work with. if (packetlen < 8) { // ERROR: Received runt packet return 1; } //macto (ignore) our mac filter handles this. enc424j600_dumpbytes( 6 ); enc424j600_popblob( macfrom, 6 ); //Make sure it's ethernet! if (enc424j600_pop8() != 0x08) { // ERROR: Not an ethernet packet return 1; } //Is it ARP? if (enc424j600_pop8() == 0x06) { HandleArp(); return 0; } //otherwise it's standard IP //So, we're expecting a '45 if (enc424j600_pop8() != 0x45) { // ERROR: Not an IP packet return 1; } enc424j600_pop8(); //differentiated services field. iptotallen = enc424j600_pop16(); enc424j600_dumpbytes( 5 ); //ID, Offset+FLAGS+TTL ipproto = enc424j600_pop8(); enc424j600_pop16(); //header checksum enc424j600_popblob( ipsource, 4 ); for (i = 0; i < 4; i++) { unsigned char m = ~MyMask[i]; unsigned char ch = enc424j600_pop8(); if (ch == MyIP[i] || (ch & m) == 0xff) { continue; } is_the_packet_for_me = 0; } //Tricky, for DHCP packets, we have to detect it even if it is not to us. if (ipproto == 17) { remoteport = enc424j600_pop16(); localport = enc424j600_pop16(); } if (!is_the_packet_for_me) { // ERROR: Packet is not for us return 1; } //XXX TODO Handle IPL > 5 (IHL?) switch(ipproto) { // ICMP case 1: { HandleICMP(); break; } // UDP case 17: { HandleUDP(enc424j600_pop16()); break; } default: { break; } } return 0; //finishcb: // enc424j600_finish_callback_now(); }