Skip to content

Commit

Permalink
Make ARP probe public. Add ARP event
Browse files Browse the repository at this point in the history
  • Loading branch information
cpq authored and scaprile committed Oct 3, 2024
1 parent c49036a commit 507c3ee
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 9 deletions.
9 changes: 6 additions & 3 deletions mongoose.c
Original file line number Diff line number Diff line change
Expand Up @@ -5107,7 +5107,7 @@ static size_t ether_output(struct mg_tcpip_if *ifp, size_t len) {
return n;
}

static void arp_ask(struct mg_tcpip_if *ifp, uint32_t ip) {
void mg_tcpip_arp_request(struct mg_tcpip_if *ifp, uint32_t ip, uint8_t *mac) {
struct eth *eth = (struct eth *) ifp->tx.buf;
struct arp *arp = (struct arp *) (eth + 1);
memset(eth->dst, 255, sizeof(eth->dst));
Expand All @@ -5118,6 +5118,7 @@ static void arp_ask(struct mg_tcpip_if *ifp, uint32_t ip) {
arp->plen = 4;
arp->op = mg_htons(1), arp->tpa = ip, arp->spa = ifp->ip;
memcpy(arp->sha, ifp->mac, sizeof(arp->sha));
if (mac != NULL) memcpy(arp->tha, mac, sizeof(arp->tha));
ether_output(ifp, PDIFF(eth, arp + 1));
}

Expand All @@ -5126,7 +5127,7 @@ static void onstatechange(struct mg_tcpip_if *ifp) {
MG_INFO(("READY, IP: %M", mg_print_ip4, &ifp->ip));
MG_INFO((" GW: %M", mg_print_ip4, &ifp->gw));
MG_INFO((" MAC: %M", mg_print_mac, &ifp->mac));
arp_ask(ifp, ifp->gw); // unsolicited GW ARP request
mg_tcpip_arp_request(ifp, ifp->gw, NULL); // unsolicited GW ARP request
} else if (ifp->state == MG_TCPIP_STATE_UP) {
MG_ERROR(("Link up"));
srand((unsigned int) mg_millis());
Expand Down Expand Up @@ -5784,6 +5785,7 @@ static void mg_tcpip_rx(struct mg_tcpip_if *ifp, void *buf, size_t len) {
if (pkt.eth->type == mg_htons(0x806)) {
pkt.arp = (struct arp *) (pkt.eth + 1);
if (sizeof(*pkt.eth) + sizeof(*pkt.arp) > pkt.raw.len) return; // Truncated
mg_tcpip_call(ifp, MG_TCPIP_EV_ARP, &pkt.raw);
rx_arp(ifp, &pkt);
} else if (pkt.eth->type == mg_htons(0x86dd)) {
pkt.ip6 = (struct ip6 *) (pkt.eth + 1);
Expand Down Expand Up @@ -5833,6 +5835,7 @@ static void mg_tcpip_poll(struct mg_tcpip_if *ifp, uint64_t now) {
onstatechange(ifp);
}
if (ifp->state == MG_TCPIP_STATE_DOWN) MG_ERROR(("Network is down"));
mg_tcpip_call(ifp, MG_TCPIP_EV_TIMER_1S, NULL);
}
if (ifp->state == MG_TCPIP_STATE_DOWN) return;

Expand Down Expand Up @@ -5994,7 +5997,7 @@ void mg_connect_resolved(struct mg_connection *c) {
rem_ip != ifp->gw) { // skip if gw (onstatechange -> READY -> ARP)
// If we're in the same LAN, fire an ARP lookup.
MG_DEBUG(("%lu ARP lookup...", c->id));
arp_ask(ifp, rem_ip);
mg_tcpip_arp_request(ifp, rem_ip, NULL);
settmout(c, MIP_TTYPE_ARP);
c->is_arplooking = 1;
} else if ((*((uint8_t *) &rem_ip) & 0xE0) == 0xE0) {
Expand Down
3 changes: 3 additions & 0 deletions mongoose.h
Original file line number Diff line number Diff line change
Expand Up @@ -2733,6 +2733,8 @@ enum {
MG_TCPIP_EV_ST_CHG, // state change uint8_t * (&ifp->state)
MG_TCPIP_EV_DHCP_DNS, // DHCP DNS assignment uint32_t *ipaddr
MG_TCPIP_EV_DHCP_SNTP, // DHCP SNTP assignment uint32_t *ipaddr
MG_TCPIP_EV_ARP, // Got ARP packet struct mg_str *
MG_TCPIP_EV_TIMER_1S, // 1 second timer NULL
MG_TCPIP_EV_USER // Starting ID for user events
};

Expand Down Expand Up @@ -2776,6 +2778,7 @@ struct mg_tcpip_if {
void mg_tcpip_init(struct mg_mgr *, struct mg_tcpip_if *);
void mg_tcpip_free(struct mg_tcpip_if *);
void mg_tcpip_qwrite(void *buf, size_t len, struct mg_tcpip_if *ifp);
void mg_tcpip_arp_request(struct mg_tcpip_if *ifp, uint32_t ip, uint8_t *mac);

extern struct mg_tcpip_driver mg_tcpip_driver_stm32f;
extern struct mg_tcpip_driver mg_tcpip_driver_w5500;
Expand Down
9 changes: 6 additions & 3 deletions src/net_builtin.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ static size_t ether_output(struct mg_tcpip_if *ifp, size_t len) {
return n;
}

static void arp_ask(struct mg_tcpip_if *ifp, uint32_t ip) {
void mg_tcpip_arp_request(struct mg_tcpip_if *ifp, uint32_t ip, uint8_t *mac) {
struct eth *eth = (struct eth *) ifp->tx.buf;
struct arp *arp = (struct arp *) (eth + 1);
memset(eth->dst, 255, sizeof(eth->dst));
Expand All @@ -196,6 +196,7 @@ static void arp_ask(struct mg_tcpip_if *ifp, uint32_t ip) {
arp->plen = 4;
arp->op = mg_htons(1), arp->tpa = ip, arp->spa = ifp->ip;
memcpy(arp->sha, ifp->mac, sizeof(arp->sha));
if (mac != NULL) memcpy(arp->tha, mac, sizeof(arp->tha));
ether_output(ifp, PDIFF(eth, arp + 1));
}

Expand All @@ -204,7 +205,7 @@ static void onstatechange(struct mg_tcpip_if *ifp) {
MG_INFO(("READY, IP: %M", mg_print_ip4, &ifp->ip));
MG_INFO((" GW: %M", mg_print_ip4, &ifp->gw));
MG_INFO((" MAC: %M", mg_print_mac, &ifp->mac));
arp_ask(ifp, ifp->gw); // unsolicited GW ARP request
mg_tcpip_arp_request(ifp, ifp->gw, NULL); // unsolicited GW ARP request
} else if (ifp->state == MG_TCPIP_STATE_UP) {
MG_ERROR(("Link up"));
srand((unsigned int) mg_millis());
Expand Down Expand Up @@ -862,6 +863,7 @@ static void mg_tcpip_rx(struct mg_tcpip_if *ifp, void *buf, size_t len) {
if (pkt.eth->type == mg_htons(0x806)) {
pkt.arp = (struct arp *) (pkt.eth + 1);
if (sizeof(*pkt.eth) + sizeof(*pkt.arp) > pkt.raw.len) return; // Truncated
mg_tcpip_call(ifp, MG_TCPIP_EV_ARP, &pkt.raw);
rx_arp(ifp, &pkt);
} else if (pkt.eth->type == mg_htons(0x86dd)) {
pkt.ip6 = (struct ip6 *) (pkt.eth + 1);
Expand Down Expand Up @@ -911,6 +913,7 @@ static void mg_tcpip_poll(struct mg_tcpip_if *ifp, uint64_t now) {
onstatechange(ifp);
}
if (ifp->state == MG_TCPIP_STATE_DOWN) MG_ERROR(("Network is down"));
mg_tcpip_call(ifp, MG_TCPIP_EV_TIMER_1S, NULL);
}
if (ifp->state == MG_TCPIP_STATE_DOWN) return;

Expand Down Expand Up @@ -1072,7 +1075,7 @@ void mg_connect_resolved(struct mg_connection *c) {
rem_ip != ifp->gw) { // skip if gw (onstatechange -> READY -> ARP)
// If we're in the same LAN, fire an ARP lookup.
MG_DEBUG(("%lu ARP lookup...", c->id));
arp_ask(ifp, rem_ip);
mg_tcpip_arp_request(ifp, rem_ip, NULL);
settmout(c, MIP_TTYPE_ARP);
c->is_arplooking = 1;
} else if ((*((uint8_t *) &rem_ip) & 0xE0) == 0xE0) {
Expand Down
3 changes: 3 additions & 0 deletions src/net_builtin.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ enum {
MG_TCPIP_EV_ST_CHG, // state change uint8_t * (&ifp->state)
MG_TCPIP_EV_DHCP_DNS, // DHCP DNS assignment uint32_t *ipaddr
MG_TCPIP_EV_DHCP_SNTP, // DHCP SNTP assignment uint32_t *ipaddr
MG_TCPIP_EV_ARP, // Got ARP packet struct mg_str *
MG_TCPIP_EV_TIMER_1S, // 1 second timer NULL
MG_TCPIP_EV_USER // Starting ID for user events
};

Expand Down Expand Up @@ -65,6 +67,7 @@ struct mg_tcpip_if {
void mg_tcpip_init(struct mg_mgr *, struct mg_tcpip_if *);
void mg_tcpip_free(struct mg_tcpip_if *);
void mg_tcpip_qwrite(void *buf, size_t len, struct mg_tcpip_if *ifp);
void mg_tcpip_arp_request(struct mg_tcpip_if *ifp, uint32_t ip, uint8_t *mac);

extern struct mg_tcpip_driver mg_tcpip_driver_stm32f;
extern struct mg_tcpip_driver mg_tcpip_driver_w5500;
Expand Down
39 changes: 36 additions & 3 deletions tutorials/tcpip/pcap-driver/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
#include <pcap.h>
#include "mongoose.h"

#define MQTT_URL "mqtt://broker.emqx.io:1883" // MQTT broker URL
#define MQTTS_URL "mqtts://mongoose.ws:8883" // HiveMQ does not TLS1.3
#define MQTT_TOPIC "mg/rx" // Topic to subscribe to
#define MQTT_URL "mqtt://broker.emqx.io:1883" // MQTT broker URL
#define MQTTS_URL "mqtts://mongoose.ws:8883" // HiveMQ does not TLS1.3
#define MQTT_TOPIC "mg/rx" // Topic to subscribe to

// // Taken from broker.emqx.io
static const char *s_ca_cert =
Expand Down Expand Up @@ -192,6 +192,35 @@ static void mqtt_ev_handler(struct mg_connection *c, int ev, void *ev_data) {
}
}

static void if_ev_handler(struct mg_tcpip_if *ifp, int ev, void *ev_data) {
static uint32_t ip = 0;
static unsigned counter = 0;

// Set initial self-assigned IP
if (ip == 0) ip = MG_IPV4(169, 254, 2, 100);

// Catch ARP packets. Parse them yourself, that's easy.
if (ev == MG_TCPIP_EV_ARP) {
struct mg_str *frame = ev_data;
MG_INFO(("Iface %p: Got ARP frame", ifp));
mg_hexdump(frame->buf, frame->len);
// TODO: check for conflict. On conflict, increment ip and reset counter
}

// Catch 1 second timer events
if (ev == MG_TCPIP_EV_TIMER_1S && ifp->ip == 0) {
MG_INFO(("Sending ARP probe"));
mg_tcpip_arp_request(ifp, ip, NULL);

// Seems to be no conflict. Assign us an IP
if (counter++ > 2) {
MG_INFO(("Assigning %M, sending ARP probe", mg_print_ip4, &ip));
ifp->ip = ip;
mg_tcpip_arp_request(ifp, ip, ifp->mac);
}
}
}

int main(int argc, char *argv[]) {
const char *iface = "lo0"; // Network iface
const char *mac = "02:00:01:02:03:77"; // MAC address
Expand Down Expand Up @@ -252,6 +281,10 @@ int main(int argc, char *argv[]) {
&mif.mac[2], &mif.mac[3], &mif.mac[4], &mif.mac[5]);
mg_tcpip_init(&mgr, &mif);

// Call order is important: call after mg_tcpip_init()
mif.fn = if_ev_handler;
mif.enable_dhcp_client = false;

MG_INFO(("Init done, starting main loop"));
mg_http_listen(&mgr, "http://0.0.0.0:8000", http_ev_handler, NULL);
mg_http_listen(&mgr, "https://0.0.0.0:8443", http_ev_handler, "tls enabled");
Expand Down

0 comments on commit 507c3ee

Please sign in to comment.