void send_ip_header( unsigned short totallen, const unsigned char * to, unsigned char proto ) { /* //This uses about 50 bytes less of flash, but 12 bytes more of ram. You can choose that tradeoff. static unsigned char data[] = { 0x45, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 64, 0x00, 0x00, 0x00 }; data[2] = totallen >> 8; data[3] = totallen & 0xFF; data[9] = proto; enc424j600_pushblob( data, 12 ); */ enc424j600_push16( 0x4500 ); enc424j600_push16( totallen ); enc424j600_push16( 0x0000 ); //ID enc424j600_push16( 0x4000 ); //Don't frgment, no fragment offset enc424j600_push8( 64 ); // TTL enc424j600_push8( proto ); // protocol enc424j600_push16( 0 ); //Checksum enc424j600_pushblob( MyIP, 4 ); enc424j600_pushblob( to, 4 ); }
int8_t RequestARP( uint8_t * ip ) { uint8_t i; for( i = 0; i < ARP_CLIENT_TABLE_SIZE; i++ ) { if( memcmp( (char*)&ClientArpTable[i].ip, ip, 4 ) == 0 ) //XXX did I mess up my casting? { return i; } } SwitchToBroadcast(); //No MAC Found. Send an ARP request. enc424j600_finish_callback_now(); enc424j600_startsend( NetGetScratch() ); send_etherlink_header( 0x0806 ); enc424j600_push16( 0x0001 ); //Ethernet enc424j600_push16( 0x0800 ); //Protocol (IP) enc424j600_push16( 0x0604 ); //HW size, Proto size enc424j600_push16( 0x0001 ); //Request enc424j600_pushblob( MyMAC, 6 ); enc424j600_pushblob( MyIP, 4 ); enc424j600_push16( 0x0000 ); enc424j600_push16( 0x0000 ); enc424j600_push16( 0x0000 ); enc424j600_pushblob( ip, 4 ); enc424j600_endsend(); return -1; }
void send_etherlink_header( unsigned short type ) { enc424j600_pushblob( macfrom, 6 ); // The mac does this for us. enc424j600_pushblob( MyMAC, 6 ); enc424j600_push16( type ); }
void DoPing( uint8_t pingslot ) { unsigned short ppl; uint16_t seqnum = ++ClientPingEntries[pingslot].last_send_seqnum; uint16_t checksum = (seqnum + pingslot + 0x0800) ; int8_t arpslot = RequestARP( ClientPingEntries[pingslot].ip ); if (arpslot < 0) { return; } //must set macfrom to be the IP address of the target. memcpy( macfrom, ClientArpTable[arpslot].mac, 6 ); enc424j600_startsend( NetGetScratch() ); send_etherlink_header( 0x0800 ); send_ip_header( 32, ClientPingEntries[pingslot].ip, 0x01 ); enc424j600_push16( 0x0800 ); //ping request + 0 for code enc424j600_push16( ~checksum ); //Checksum enc424j600_push16( pingslot ); //Idneitifer enc424j600_push16( seqnum ); //Sequence number enc424j600_push16( 0x0000 ); //Payload enc424j600_push16( 0x0000 ); enc424j600_start_checksum( 8, 20 ); ppl = enc424j600_get_checksum(); enc424j600_alter_word( 18, ppl ); enc424j600_endsend(); }
//Mode = 1 for discover, Mode = 3 for request - if discover, dhcp_server should be 0. void RequestNewIP( uint8_t mode, uint8_t * negotiating_ip, uint8_t * dhcp_server ) { uint8_t oldip[4]; SwitchToBroadcast(); enc424j600_stopop(); enc424j600_startsend( NetGetScratch() ); send_etherlink_header( 0x0800 ); //Tricky - backup our IP - we want to spoof it to 0.0.0.0 memcpy( oldip, MyIP, 4 ); MyIP[0] = 0; MyIP[1] = 0; MyIP[2] = 0; MyIP[3] = 0; send_ip_header( 0, "\xff\xff\xff\xff", 17 ); //UDP Packet to 255.255.255.255 memcpy( MyIP, oldip, 4 ); /* enc424j600_push16( 68 ); //From bootpc enc424j600_push16( 67 ); //To bootps enc424j600_push16( 0 ); //length for later enc424j600_push16( 0 ); //csum for later //Payload of BOOTP packet. // 1, //Bootp request // 1, //Ethernet enc424j600_push16( 0x0101 ); // 6, //MAC Length // 0, //Hops enc424j600_push16( 0x0600 ); */ enc424j600_pushpgmblob( PSTR("\x00\x44\x00\x43\x00\x00\x00\x00\x01\x01\x06"), 12 ); //NOTE: Last digit is 0 on wire, not included in string. enc424j600_pushblob( MyMAC, 4 ); enc424j600_push16( dhcp_clocking ); //seconds enc424j600_pushzeroes( 10 ); //unicast, CLIADDR, YIADDR if( dhcp_server ) enc424j600_pushblob( dhcp_server, 4 ); else enc424j600_pushzeroes( 4 ); enc424j600_pushzeroes( 4 ); //GIADDR IP enc424j600_pushblob( MyMAC, 6 ); //client mac enc424j600_pushzeroes( 10 + 0x40 + 0x80 ); //padding + Server Host Name enc424j600_push16( 0x6382 ); //DHCP Magic Cookie enc424j600_push16( 0x5363 ); //Now we are on our DHCP portion enc424j600_push8( 0x35 ); //DHCP Message Type enc424j600_push16( 0x0100 | mode ); { enc424j600_push16( 0x3204 ); //Requested IP address. (4 length) enc424j600_pushblob( negotiating_ip, 4 ); } if( dhcp_server ) //request { enc424j600_push16( 0x3604 ); enc424j600_pushblob( dhcp_server, 4 ); } if( DHCPName ) { uint8_t namelen = strlen( DHCPName ); enc424j600_push8( 0x0c ); //Name enc424j600_push8( namelen ); enc424j600_pushblob( DHCPName, namelen ); } enc424j600_push16( 0x3702 ); //Parameter request list enc424j600_push16( 0x0103 ); //subnet mask, router // enc424j600_push16( 0x2a06 ); //NTP server, DNS server (We don't use either NTP or DNS) enc424j600_push8( 0xff ); //End option enc424j600_pushzeroes( 32 ); //Padding util_finish_udp_packet(); }
static void HandleICMP() { unsigned short id; unsigned short seqnum; unsigned char type; unsigned short payloadsize = iptotallen - SIZEOFICMP; unsigned short payload_from_start, payload_dest_start; icmp_in++; type = enc424j600_pop8(); enc424j600_pop8(); //code enc424j600_pop16(); //Checksum switch( type ) { // Ping Response case 0: { uint16_t id; id = enc424j600_pop16(); if( id < PING_RESPONSES_SIZE ) { ClientPingEntries[id].last_recv_seqnum = enc424j600_pop16(); //Seqnum } enc424j600_stopop(); enc424j600_finish_callback_now(); break; } // Ping Request case 8: { //Tricky: We would ordinarily POPB to read out the payload, but we're using //the DMA engine to copy that data. // POPB( payload, payloadsize ); //Suspend reading for now (but don't allow over-writing of the data) enc424j600_stopop(); payload_from_start = enc424j600_read_ctrl_reg16( EERXRDPTL ); enc424j600_startsend( NetGetScratch() ); send_etherlink_header( 0x0800 ); send_ip_header( iptotallen, ipsource, 0x01 ); enc424j600_push16( 0 ); //ping reply + code enc424j600_push16( 0 ); //Checksum // enc424j600_push16( id ); // enc424j600_push16( seqnum ); //Packet confiugred. Need to copy payload. //Ordinarily, we'd enc424j600_pushblob for the payload, but we're currently using the DMA engine for our work here. enc424j600_stopop(); payload_dest_start = enc424j600_read_ctrl_reg16( EEGPWRPTL ); //+4 = id + seqnum (we're DMAing that, too) enc424j600_copy_memory( payload_dest_start, payload_from_start, payloadsize + 4, RX_BUFFER_START, RX_BUFFER_END-1 ); enc424j600_write_ctrl_reg16( EEGPWRPTL, payload_dest_start + payloadsize + 4 ); enc424j600_finish_callback_now(); //Calculate header and ICMP checksums enc424j600_start_checksum( 8+6, 20 ); unsigned short ppl = enc424j600_get_checksum(); enc424j600_start_checksum( 28+6, payloadsize + 8 ); enc424j600_alter_word( 18+6, ppl ); ppl = enc424j600_get_checksum(); enc424j600_alter_word( 30+6, ppl ); enc424j600_endsend(); icmp_out++; break; } } }
static void HandleArp (void) { unsigned short i; unsigned char sendermac_ip_and_targetmac[16]; // unsigned char senderip[10]; //Actually sender ip + target mac, put in one to shrink code. unsigned short proto; unsigned char opcode; // unsigned char ipproto; enc424j600_pop16(); //Hardware type proto = enc424j600_pop16(); enc424j600_pop16(); //hwsize, protosize opcode = enc424j600_pop16(); //XXX: This includes "code" as well, it seems. switch( opcode ) { // ARP Request case 1: { unsigned char match; enc424j600_popblob( sendermac_ip_and_targetmac, 16 ); match = 1; //sendhex2( 0xff ); //Target IP (check for copy) for( i = 0; i < 4; i++ ) if( enc424j600_pop8() != MyIP[i] ) match = 0; if( match == 0 ) return; //We must send a response, so we termiante the packet now. enc424j600_finish_callback_now(); enc424j600_startsend( NetGetScratch() ); send_etherlink_header( 0x0806 ); enc424j600_push16( 0x0001 ); //Ethernet enc424j600_push16( proto ); //Protocol enc424j600_push16( 0x0604 ); //HW size, Proto size enc424j600_push16( 0x0002 ); //Reply enc424j600_pushblob( MyMAC, 6 ); enc424j600_pushblob( MyIP, 4 ); enc424j600_pushblob( sendermac_ip_and_targetmac, 10 ); // do not send target mac. enc424j600_endsend(); // Have a match! break; } // ARP Reply case 2: { uint8_t sender_mac_and_ip_and_comp_mac[16]; enc424j600_popblob( sender_mac_and_ip_and_comp_mac, 16 ); enc424j600_finish_callback_now(); //First, make sure that we're the ones who are supposed to receive the ARP. for( i = 0; i < 6; i++ ) { if( sender_mac_and_ip_and_comp_mac[i+10] != MyMAC[i] ) break; } if( i != 6 ) break; //We're the right recipent. Put it in the table. memcpy( &ClientArpTable[ClientArpTablePointer], sender_mac_and_ip_and_comp_mac, 10 ); ClientArpTablePointer = (ClientArpTablePointer+1)%ARP_CLIENT_TABLE_SIZE; break; } default: { //???? don't know what to do. return; } } }