Skip to content

Commit

Permalink
extend the library so udp sending to lan IP works njh#309
Browse files Browse the repository at this point in the history
  • Loading branch information
hecko committed Oct 20, 2018
1 parent 80d1906 commit 46d8812
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/EtherCard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ uint8_t EtherCard::gwip[IP_LEN]; // gateway
uint8_t EtherCard::dhcpip[IP_LEN]; // dhcp server
uint8_t EtherCard::dnsip[IP_LEN]; // dns server
uint8_t EtherCard::hisip[IP_LEN]; // ip address of remote host
uint8_t EtherCard::returned_mac[ETH_LEN]; // Returning ARP request response with MAC address - from blocking ARP request
uint16_t EtherCard::hisport = HTTP_PORT; // tcp port to browse to
bool EtherCard::using_dhcp = false;
bool EtherCard::persist_tcp_connection = false;
Expand Down
8 changes: 8 additions & 0 deletions src/EtherCard.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ class EtherCard : public Ethernet {
static uint8_t dhcpip[IP_LEN]; ///< DHCP server IP address
static uint8_t dnsip[IP_LEN]; ///< DNS server IP address
static uint8_t hisip[IP_LEN]; ///< DNS lookup result
static uint8_t returned_mac[ETH_LEN]; // Returning ARP request response with MAC address - from blocking ARP request
static uint16_t hisport; ///< TCP port to connect to (default 80)
static bool using_dhcp; ///< True if using DHCP
static bool persist_tcp_connection; ///< False to break connections on first packet received
Expand Down Expand Up @@ -265,6 +266,8 @@ class EtherCard : public Ethernet {
*/
static void udpPrepare (uint16_t sport, const uint8_t *dip, uint16_t dport);

static void udpPrepare_mac (uint16_t sport, const uint8_t *dip, const uint8_t *mac, uint16_t dport);

/** @brief Transmit UDP packet
* @param len Size of payload
*/
Expand All @@ -280,6 +283,9 @@ class EtherCard : public Ethernet {
static void sendUdp (const char *data, uint8_t len, uint16_t sport,
const uint8_t *dip, uint16_t dport);

static void sendUdp_mac (const char *data, uint8_t len, uint16_t sport,
const uint8_t *dip, const uint8_t *mac, uint16_t dport);

/** @brief Resister the function to handle ping events
* @param cb Pointer to function
*/
Expand Down Expand Up @@ -461,6 +467,8 @@ class EtherCard : public Ethernet {
*/
static uint8_t parseIp(uint8_t *bytestr,char *str);

void client_arp_whohas_blocking(uint8_t *ip_we_search);

/** @brief Convert a byte array to a human readable display string
* @param resultstr Pointer to a buffer to hold the resulting null terminated string
* @param bytestr Pointer to the byte array containing the address to convert
Expand Down
66 changes: 64 additions & 2 deletions src/tcpip.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ static boolean waiting_for_dns_mac = false; //might be better to use bit flags a
static boolean has_dns_mac = false;
static boolean waiting_for_dest_mac = false;
static boolean has_dest_mac = false;
static boolean waiting_for_mac = false; // we have manually requested a arp request and now waiting for the response before doing anything else further
static uint8_t gwmacaddr[ETH_LEN]; // Hardware (MAC) address of gateway router
static uint8_t waitgwmac; // Bitwise flags of gateway router status - see below for states
//Define gateway router ARP statuses
Expand Down Expand Up @@ -373,6 +374,30 @@ uint8_t EtherCard::ntpProcessAnswer (uint32_t *time,uint8_t dstport_l) {
return 1;
}

void EtherCard::udpPrepare_mac (uint16_t sport, const uint8_t *dip, const uint8_t *mac, uint16_t dport) {
if(is_lan(myip, dip)) { // this works because both dns mac and destinations mac are stored in same variable - destmacaddr
setMACandIPs(mac, dip); // at different times. The program could have separate variable for dns mac, then here should be
} else { // checked if dip is dns ip and separately if dip is hisip and then use correct mac.
setMACandIPs(gwmacaddr, dip);
}
// see http://tldp.org/HOWTO/Multicast-HOWTO-2.html
// multicast or broadcast address, https://github.com/njh/EtherCard/issues/59
if ((dip[0] & 0xF0) == 0xE0 || *((unsigned long*) dip) == 0xFFFFFFFF || !memcmp(broadcastip,dip,IP_LEN))
EtherCard::copyMac(gPB + ETH_DST_MAC, allOnes);
gPB[ETH_TYPE_H_P] = ETHTYPE_IP_H_V;
gPB[ETH_TYPE_L_P] = ETHTYPE_IP_L_V;
memcpy_P(gPB + IP_P,iphdr,sizeof iphdr);
gPB[IP_TOTLEN_H_P] = 0;
gPB[IP_PROTO_P] = IP_PROTO_UDP_V;
gPB[UDP_DST_PORT_H_P] = (dport>>8);
gPB[UDP_DST_PORT_L_P] = dport;
gPB[UDP_SRC_PORT_H_P] = (sport>>8);
gPB[UDP_SRC_PORT_L_P] = sport;
gPB[UDP_LEN_H_P] = 0;
gPB[UDP_CHECKSUM_H_P] = 0;
gPB[UDP_CHECKSUM_L_P] = 0;
}

void EtherCard::udpPrepare (uint16_t sport, const uint8_t *dip, uint16_t dport) {
if(is_lan(myip, dip)) { // this works because both dns mac and destinations mac are stored in same variable - destmacaddr
setMACandIPs(destmacaddr, dip); // at different times. The program could have separate variable for dns mac, then here should be
Expand Down Expand Up @@ -416,6 +441,15 @@ void EtherCard::sendUdp (const char *data, uint8_t datalen, uint16_t sport,
udpTransmit(datalen);
}

void EtherCard::sendUdp_mac (const char *data, uint8_t datalen, uint16_t sport,
const uint8_t *dip, const uint8_t *mac, uint16_t dport) {
udpPrepare_mac(sport, dip, mac, dport);
if (datalen>220)
datalen = 220;
memcpy(gPB + UDP_DATA_P, data, datalen);
udpTransmit(datalen);
}

void EtherCard::sendWol (uint8_t *wolmac) {
setMACandIPs(allOnes, allOnes);
gPB[ETH_TYPE_H_P] = ETHTYPE_IP_H_V;
Expand All @@ -442,7 +476,7 @@ void EtherCard::sendWol (uint8_t *wolmac) {
packetSend(pos + 6);
}

// make a arp request
// make an arp request
static void client_arp_whohas(uint8_t *ip_we_search) {
setMACs(allOnes);
gPB[ETH_TYPE_H_P] = ETHTYPE_ARP_H_V;
Expand All @@ -455,6 +489,20 @@ static void client_arp_whohas(uint8_t *ip_we_search) {
EtherCard::packetSend(42);
}

// make an arp request
void EtherCard::client_arp_whohas_blocking(uint8_t *ip_we_search) {
waiting_for_mac = true;
setMACs(allOnes);
gPB[ETH_TYPE_H_P] = ETHTYPE_ARP_H_V;
gPB[ETH_TYPE_L_P] = ETHTYPE_ARP_L_V;
memcpy_P(gPB + ETH_ARP_P, arpreqhdr, sizeof arpreqhdr);
memset(gPB + ETH_ARP_DST_MAC_P, 0, ETH_LEN);
EtherCard::copyMac(gPB + ETH_ARP_SRC_MAC_P, EtherCard::mymac);
EtherCard::copyIp(gPB + ETH_ARP_DST_IP_P, ip_we_search);
EtherCard::copyIp(gPB + ETH_ARP_SRC_IP_P, EtherCard::myip);
EtherCard::packetSend(42);
}

uint8_t EtherCard::clientWaitingGw () {
return !(waitgwmac & WGW_HAVE_GW_MAC);
}
Expand Down Expand Up @@ -712,16 +760,30 @@ uint16_t EtherCard::packetLoop (uint16_t plen) {
return 0;
}

// Handling ARP packets here
if (eth_type_is_arp_and_my_ip(plen))
{ //Service ARP request
{ // Send response to external ARP request
if (gPB[ETH_ARP_OPCODE_L_P]==ETH_ARP_OPCODE_REQ_L_V)
make_arp_answer_from_request();

// We have been waiting for ARP response and this is it
if (waiting_for_mac) {
waiting_for_mac = false;
EtherCard::copyMac(EtherCard::returned_mac, gPB + ETH_ARP_SRC_MAC_P);
}

// We have been waiting for GW ARP response and this is it
if (waitgwmac & WGW_ACCEPT_ARP_REPLY && (gPB[ETH_ARP_OPCODE_L_P]==ETH_ARP_OPCODE_REPLY_L_V) && client_store_mac(gwip, gwmacaddr))
waitgwmac = WGW_HAVE_GW_MAC;

// We have been waiting for DNS server ARP response and this is it
if (!has_dns_mac && waiting_for_dns_mac && client_store_mac(dnsip, destmacaddr)) {
has_dns_mac = true;
waiting_for_dns_mac = false;
}

// We have been waiting for generic ARP response and this is it
// We will save the received MAC address in destmacaddr variable
if (!has_dest_mac && waiting_for_dest_mac && client_store_mac(hisip, destmacaddr)) {
has_dest_mac = true;
waiting_for_dest_mac = false;
Expand Down

0 comments on commit 46d8812

Please sign in to comment.