Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ICMP] replace ICMP offsets by struct IcmpHeader #357

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 16 additions & 11 deletions examples/SSDP/SSDP.ino
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <EtherCard.h>// |Mac adress|
#include <EtherUtil.h>
const char SSDP_RESPONSE[] PROGMEM = "HTTP/1.1 200 OK\r\nCACHE-CONTROL: max-age=1200\r\nEXT:\r\nSERVER:Arduino\r\nST: upnp:rootdevice\r\nUSN: uuid:abcdefgh-7dec-11d0-a765-7499692d3040\r\nLOCATION: http://"; //dont forget our mac adress USN: uuid:abcdefgh-7dec-11d0-a765-Mac addr
const char SSDP_RESPONSE_XML[] PROGMEM = "/??\r\n\r\n"; // here is the adress of xml file /?? in this exemple but you could use another /upnp.xml\r\n\r\n
const char XML_DESCRIP[] PROGMEM = "HTTP/1.1 200 OK\r\nContent-Type: text/xml\r\n\r\n<?xml version='1.0'?>\r<root xmlns='urn:schemas-upnp-org:device-1-0'><device><deviceType>urn:schemas-upnp-org:device:BinaryLight:1</deviceType><presentationURL>/</presentationURL><friendlyName>Arduino</friendlyName><manufacturer>Fredycpu</manufacturer><manufacturerURL>http://fredycpu.pro</manufacturerURL><serialNumber>1</serialNumber><UDN>uuid:abcdefgh-7dec-11d0-a765-7499692d3040</UDN></device></root> ";
Expand Down Expand Up @@ -48,6 +49,10 @@ const char pageD[] PROGMEM =
"</em></p>"
;

void ssdpresp();
void addip(uint8_t *udppos);
void ssdpnotify();

void setup(){
// Change 'SS' to your Slave Select pin, if you arn't using the default pin
ether.begin(sizeof Ethernet::buffer, mymac, SS);
Expand Down Expand Up @@ -96,46 +101,46 @@ void ssdpresp() { //response to m-search
for( int i=0; i<IP_LEN;i++) { //extract source IP of request
ip_dst[i]=Ethernet::buffer[i+26];
}
int udppos = UDP_DATA_P;
uint8_t *udppos = udp_payload();

EtherCard::udpPrepare(1900,ip_dst,port_dst);
memcpy_P(Ethernet::buffer + udppos, SSDP_RESPONSE, sizeof SSDP_RESPONSE);
memcpy_P(udppos, SSDP_RESPONSE, sizeof SSDP_RESPONSE);
udppos = udppos + sizeof SSDP_RESPONSE-1;
addip(udppos);
}

void ssdpnotify() { //Notification
int udppos = UDP_DATA_P;
int udppos = udp_payload();
EtherCard::udpPrepare(1900,ssdp,1900);
memcpy_P(Ethernet::buffer + udppos, SSDP_NOTIFY, sizeof SSDP_NOTIFY);
memcpy_P(udppos, SSDP_NOTIFY, sizeof SSDP_NOTIFY);
udppos = udppos + sizeof SSDP_NOTIFY-1;
addip(udppos);
}

void addip(int udppos) { // add current ip to the request and send it
void addip(uint8_t *udppos) { // add current ip to the request and send it
int adr;
for(int i=0;i<IP_LEN;i++) { // extract the current ip of arduino
adr = ether.myip[i]/100;
if (adr) {
Ethernet::buffer[udppos]=adr+48;
*udppos=adr+48;
udppos++;
}
adr=(ether.myip[i]%100)/10;
if (adr||(ether.myip[i]/100)) {
Ethernet::buffer[udppos]=adr+48;
*udppos=adr+48;
udppos++;
}
adr=ether.myip[i]%10;
Ethernet::buffer[udppos]=adr+48;
*udppos=adr+48;
udppos++;
Ethernet::buffer[udppos]=46;
*udppos=46;
udppos++; //"."
}
udppos--;//erase the last point
memcpy_P(Ethernet::buffer + udppos,SSDP_RESPONSE_XML,sizeof SSDP_RESPONSE_XML);
memcpy_P(udppos,SSDP_RESPONSE_XML,sizeof SSDP_RESPONSE_XML);
udppos = udppos + sizeof SSDP_RESPONSE_XML;
udppos--;
EtherCard::udpTransmit(udppos-UDP_DATA_P); // send all to the computer who make the request on her ip and port who make the request
EtherCard::udpTransmit(udppos-udp_payload()); // send all to the computer who make the request on her ip and port who make the request
}


47 changes: 45 additions & 2 deletions src/EtherCard.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@
*/
#define ETHERCARD_STASH 1

/** Set ARP cache max entry count */
#ifndef ETHERCARD_ARP_STORE_SIZE
# define ETHERCARD_ARP_STORE_SIZE 4
#endif


/** This type definition defines the structure of a UDP server event handler callback function */
typedef void (*UdpServerCallback)(
Expand All @@ -100,6 +105,7 @@ typedef void (*DhcpOptionCallback)(
const byte* data, ///< DHCP option data
uint8_t len); ///< Length of the DHCP option data

typedef void (*IcmpCallback)(const uint8_t *src_ip);


/** This class provides the main interface to a ENC28J60 based network interface card and is the class most users will use.
Expand Down Expand Up @@ -190,6 +196,16 @@ class EtherCard : public Ethernet {
*/
static void updateBroadcastAddress();

/** @brief Request the IP associated hardware address (ARP lookup). Use
* clientWaitIp(ip) to get the ARP lookup status
*/
static void clientResolveIp(const uint8_t *ip);

/** @brief Check if got IP associated hardware address (ARP lookup)
* @return <i>unit8_t</i> True if gateway found
*/
static uint8_t clientWaitIp(const uint8_t *ip);

/** @brief Check if got gateway hardware address (ARP lookup)
* @return <i>unit8_t</i> True if gateway found
*/
Expand Down Expand Up @@ -283,7 +299,7 @@ class EtherCard : public Ethernet {
/** @brief Resister the function to handle ping events
* @param cb Pointer to function
*/
static void registerPingCallback (void (*cb)(uint8_t*));
static void registerPingCallback (const IcmpCallback cb);

/** @brief Send ping
* @param destip Pointer to 4 byte destination IP address
Expand Down Expand Up @@ -342,7 +358,7 @@ class EtherCard : public Ethernet {
* @param len Not used
* @return <i>bool</i> True if packet processed
*/
static bool udpServerHasProcessedPacket(uint16_t len); //called by tcpip, in packetLoop
static bool udpServerHasProcessedPacket(const IpHeader &ip, const uint8_t *iter, const uint8_t *last); //called by tcpip, in packetLoop

// dhcp.cpp
/** @brief Update DHCP state
Expand Down Expand Up @@ -484,6 +500,33 @@ class EtherCard : public Ethernet {
/** @brief Return the payload length of the current Tcp package
*/
static uint16_t getTcpPayloadLength();

/** @brief Check if IP is in ARP store
* @param ip IP to check (size must be IP_LEN)
* @return <i>bool</i> True if IP is in ARP store
*/
static bool arpStoreHasMac(const uint8_t *ip);

/** @brief convert IP into associated MAC address
* @param ip IP to convert to MAC address (size must be IP_LEN)
* @return <i>uint8_t *</i> mac MAC address or NULL if not found
*/
static const uint8_t *arpStoreGetMac(const uint8_t *ip);

/** @brief set/refresh new couple IP/MAC addresses into ARP store
* @param ip IP address
* @param mac MAC address
*/
static void arpStoreSet(const uint8_t *ip, const uint8_t *mac);

/** @brief remove IP from ARP store
* @param ip IP address to remove
*/
static void arpStoreInvalidIp(const uint8_t *ip);

private:
static void packetLoopIdle();
static void packetLoopArp(const uint8_t *first, const uint8_t *last);
};

extern EtherCard ether; //!< Global presentation of EtherCard class
Expand Down
63 changes: 63 additions & 0 deletions src/EtherUtil.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Shortcuts to different protocols headers/payload
// Hence: GPL V2

#ifndef ETHERUTIL_H
#define ETHERUTIL_H

#include "enc28j60.h"
#include "net.h"

#define gPB ether.buffer

inline EthHeader &ethernet_header()
{
uint8_t *iter = gPB; // avoid strict aliasing warning
return *(EthHeader *)iter;
}

inline uint8_t *ethernet_payload()
{
return (uint8_t *)&ethernet_header() + sizeof(EthHeader);
}

inline ArpHeader &arp_header()
{
return *(ArpHeader *)ethernet_payload();
}

inline IpHeader &ip_header()
{
return *(IpHeader *)ethernet_payload();
}

inline uint8_t *ip_payload()
{
return (uint8_t *)&ip_header() + sizeof(IpHeader);
}

inline uint8_t *tcp_header()
{
return (uint8_t *)ip_payload();
}

inline UdpHeader &udp_header()
{
return *(UdpHeader *)ip_payload();
}

inline uint8_t *udp_payload()
{
return (uint8_t *)&udp_header() + sizeof(UdpHeader);
}

inline IcmpHeader &icmp_header()
{
return *(IcmpHeader *)ip_payload();
}

inline uint8_t *icmp_payload()
{
return (uint8_t *)&icmp_header() + sizeof(IcmpHeader);
}

#endif /* ETHERUTIL_H */
93 changes: 93 additions & 0 deletions src/arp.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#include "EtherCard.h"

struct ArpEntry
{
uint8_t ip[IP_LEN];
uint8_t mac[ETH_LEN];
uint8_t count;
};

static ArpEntry store[ETHERCARD_ARP_STORE_SIZE];

static void incArpEntry(ArpEntry &e)
{
if (e.count < 0xFF)
++e.count;
}

// static ArpEntry print_store()
// {
// Serial.println("ARP store: ");
// for (ArpEntry *iter = store, *last = store + ETHERCARD_ARP_STORE_SIZE;
// iter != last; ++iter)
// {
// ArpEntry &e = *iter;
// Serial.print('\t');
// EtherCard::printIp(e.ip);
// Serial.print(' ');
// for (int i = 0; i < ETH_LEN; ++i)
// {
// if (i > 0)
// Serial.print(':');
// Serial.print(e.mac[i], HEX);
// }
// Serial.print(' ');
// Serial.println(e.count);
// }
// }

static ArpEntry *findArpStoreEntry(const uint8_t *ip)
{
for (ArpEntry *iter = store, *last = store + ETHERCARD_ARP_STORE_SIZE;
iter != last; ++iter)
{
if (memcmp(ip, iter->ip, IP_LEN) == 0)
return iter;
}
return NULL;
}

bool EtherCard::arpStoreHasMac(const uint8_t *ip)
{
return findArpStoreEntry(ip) != NULL;
}

const uint8_t *EtherCard::arpStoreGetMac(const uint8_t *ip)
{
ArpEntry *e = findArpStoreEntry(ip);
if (e)
return e->mac;
return NULL;
}

void EtherCard::arpStoreSet(const uint8_t *ip, const uint8_t *mac)
{
ArpEntry *e = findArpStoreEntry(ip);
if (!e)
{
// find less used entry
e = store;
for (ArpEntry *iter = store + 1, *last = store + ETHERCARD_ARP_STORE_SIZE;
iter != last; ++iter)
{
if (iter->count < e->count)
e = iter;
}

// and replace it with new ip/mac
copyIp(e->ip, ip);
e->count = 1;
}
else
incArpEntry(*e);

copyMac(e->mac, mac);
// print_store();
}

void EtherCard::arpStoreInvalidIp(const uint8_t *ip)
{
ArpEntry *e = findArpStoreEntry(ip);
if (e)
memset(e, 0, sizeof(ArpEntry));
}
Loading