@@ -4511,9 +4511,20 @@ void mg_tcpip_arp_request(struct mg_tcpip_if *ifp, uint32_t ip, uint8_t *mac) {
45114511
45124512static void onstatechange(struct mg_tcpip_if *ifp) {
45134513 if (ifp->state == MG_TCPIP_STATE_READY) {
4514+ struct mg_connection *c;
45144515 MG_INFO(("READY, IP: %M", mg_print_ip4, &ifp->ip));
45154516 MG_INFO((" GW: %M", mg_print_ip4, &ifp->gw));
45164517 MG_INFO((" MAC: %M", mg_print_mac, &ifp->mac));
4518+ for (c = ifp->mgr->conns; c != NULL; c = c->next) {
4519+ if (ifp->is_ip_changed) {
4520+ if (c->is_listening || c->is_udp) {
4521+ c->loc.ip4 = c->mgr->ifp->ip;
4522+ } else {
4523+ c->is_closing = 1;
4524+ }
4525+ }
4526+ }
4527+ ifp->is_ip_changed = false;
45174528 } else if (ifp->state == MG_TCPIP_STATE_IP) {
45184529 mg_tcpip_arp_request(ifp, ifp->gw, NULL); // unsolicited GW ARP request
45194530 } else if (ifp->state == MG_TCPIP_STATE_UP) {
@@ -4800,6 +4811,7 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) {
48004811 MG_INFO(("Lease: %u sec (%lld)", lease, ifp->lease_expire / 1000));
48014812 // assume DHCP server = router until ARP resolves
48024813 memcpy(ifp->gwmac, pkt->eth->src, sizeof(ifp->gwmac));
4814+ if (ifp->ip != ip) ifp->is_ip_changed = true;
48034815 ifp->ip = ip, ifp->gw = gw, ifp->mask = mask;
48044816 ifp->state = MG_TCPIP_STATE_IP; // BOUND state
48054817 mg_random(&rand, sizeof(rand));
@@ -5012,15 +5024,15 @@ static bool fill_global(uint64_t *ip6, uint8_t *prefix, uint8_t prefix_len,
50125024 uint8_t *mac) {
50135025 uint8_t full = prefix_len / 8;
50145026 uint8_t rem = prefix_len % 8;
5015- if (full >= 8 && rem != 0) {
5027+ if (full > 8 || (full == 8 && rem != 0) ) {
50165028 MG_ERROR(("Prefix length > 64, UNSUPPORTED"));
50175029 return false;
50185030 } else if (full == 8 && rem == 0) {
50195031 ip6gen((uint8_t *) ip6, prefix, mac);
50205032 } else {
50215033 ip6[0] = ip6[1] = 0; // already zeroed before firing RS...
5022- if (full) memcpy(ip6, prefix, full);
5023- if (rem) {
5034+ if (full > 0 ) memcpy(ip6, prefix, full);
5035+ if (rem > 0 ) {
50245036 uint8_t mask = (uint8_t) (0xFF << (8 - rem));
50255037 ((uint8_t *) ip6)[full] = prefix[full] & mask;
50265038 }
@@ -5029,6 +5041,27 @@ static bool fill_global(uint64_t *ip6, uint8_t *prefix, uint8_t prefix_len,
50295041 return true;
50305042}
50315043
5044+ static bool match_prefix(uint8_t *new, uint8_t len, uint8_t *cur,
5045+ uint8_t *cur_len) {
5046+ uint8_t full = len / 8;
5047+ uint8_t rem = len % 8;
5048+ bool res = true;
5049+ if (full > 8 || (full == 8 && rem != 0))
5050+ return false; // Prefix length > 64: UNSUPPORTED
5051+ if (*cur_len != len) res = false;
5052+ if (full > 0) {
5053+ if (res && memcmp(cur, new, full) != 0) res = false;
5054+ memcpy(cur, new, full);
5055+ }
5056+ if (rem > 0) {
5057+ uint8_t mask = (uint8_t) (0xFF << (8 - rem));
5058+ if (res && cur[full] != (new[full] & mask)) res = false;
5059+ cur[full] = new[full] & mask;
5060+ }
5061+ *cur_len = len;
5062+ return res;
5063+ }
5064+
50325065// Router Advertisement, 4.2
50335066static void rx_ndp_ra(struct mg_tcpip_if *ifp, struct pkt *pkt) {
50345067 if (pkt->pay.len < 12) return;
@@ -5063,14 +5096,13 @@ static void rx_ndp_ra(struct mg_tcpip_if *ifp, struct pkt *pkt) {
50635096 uint8_t *prefix = opts + 16;
50645097
50655098 // TODO (robertc2000): handle prefix options if necessary
5066- (void) prefix_len;
50675099 (void) pfx_flags;
50685100 (void) valid;
50695101 (void) pref_lifetime;
5070- (void) prefix;
50715102
5072- // fill prefix length and global
5073- ifp->prefix_len = prefix_len;
5103+ // fill prefix and global address
5104+ if (!match_prefix(prefix, prefix_len, ifp->prefix, &ifp->prefix_len))
5105+ ifp->is_ip6_changed = true;
50745106 if (!fill_global(ifp->ip6, prefix, prefix_len, ifp->mac)) return;
50755107 }
50765108 opts += length;
@@ -5113,10 +5145,21 @@ static void rx_icmp6(struct mg_tcpip_if *ifp, struct pkt *pkt) {
51135145}
51145146
51155147static void onstate6change(struct mg_tcpip_if *ifp) {
5148+ struct mg_connection *c;
51165149 if (ifp->state6 == MG_TCPIP_STATE_READY) {
51175150 MG_INFO(("READY, IP: %M", mg_print_ip6, &ifp->ip6));
51185151 MG_INFO((" GW: %M", mg_print_ip6, &ifp->gw6));
51195152 MG_INFO((" MAC: %M", mg_print_mac, &ifp->mac));
5153+ for (c = ifp->mgr->conns; c != NULL; c = c->next) {
5154+ if (ifp->is_ip6_changed) {
5155+ if (c->is_listening || c->is_udp) {
5156+ c->loc.ip6[0] = ifp->ip6[0], c->loc.ip6[1] = ifp->ip6[1];
5157+ } else {
5158+ c->is_closing = 1;
5159+ }
5160+ }
5161+ }
5162+ ifp->is_ip6_changed = false;
51205163 } else if (ifp->state6 == MG_TCPIP_STATE_IP) {
51215164 tx_ndp_ns(ifp, ifp->gw6, ifp->gw6mac); // unsolicited GW MAC resolution
51225165 } else if (ifp->state6 == MG_TCPIP_STATE_UP) {
@@ -5603,10 +5646,10 @@ static void rx_ip(struct mg_tcpip_if *ifp, struct pkt *pkt) {
56035646 if (ihl < 5) return; // bad IHL
56045647 if (pkt->pay.len < (uint16_t) (ihl * 4)) return; // Truncated / malformed
56055648 // There can be link padding, take length from IP header
5606- len = mg_ntohs(pkt->ip->len); // IP datagram length
5649+ len = mg_ntohs(pkt->ip->len); // IP datagram length
56075650 if (len < (uint16_t) (ihl * 4) || len > pkt->pay.len) return; // malformed
5608- pkt->pay.len = len; // strip padding
5609- mkpay(pkt, (uint32_t *) pkt->ip + ihl); // account for opts
5651+ pkt->pay.len = len; // strip padding
5652+ mkpay(pkt, (uint32_t *) pkt->ip + ihl); // account for opts
56105653 frag = mg_ntohs(pkt->ip->frag);
56115654 if (frag & IP_MORE_FRAGS_MSK || frag & IP_FRAG_OFFSET_MSK) {
56125655 struct mg_connection *c;
@@ -25213,15 +25256,11 @@ enum {
2521325256 EPHYSTS = 16
2521425257}; // PHY constants
2521525258
25216- static inline void tm4cspin(volatile uint32_t count) {
25217- while (count--) (void) 0;
25218- }
25219-
2522025259static uint32_t emac_read_phy(uint8_t addr, uint8_t reg) {
2522125260 EMAC->EMACMIIADDR &= (0xf << 2);
2522225261 EMAC->EMACMIIADDR |= ((uint32_t) addr << 11) | ((uint32_t) reg << 6);
2522325262 EMAC->EMACMIIADDR |= MG_BIT(0);
25224- while (EMAC->EMACMIIADDR & MG_BIT(0)) tm4cspin(1) ;
25263+ while (EMAC->EMACMIIADDR & MG_BIT(0)) (void) 0 ;
2522525264 return EMAC->EMACMIIDATA;
2522625265}
2522725266
@@ -25231,7 +25270,7 @@ static void emac_write_phy(uint8_t addr, uint8_t reg, uint32_t val) {
2523125270 EMAC->EMACMIIADDR |=
2523225271 ((uint32_t) addr << 11) | ((uint32_t) reg << 6) | MG_BIT(1);
2523325272 EMAC->EMACMIIADDR |= MG_BIT(0);
25234- while (EMAC->EMACMIIADDR & MG_BIT(0)) tm4cspin(1) ;
25273+ while (EMAC->EMACMIIADDR & MG_BIT(0)) (void) 0 ;
2523525274}
2523625275
2523725276static uint32_t get_sysclk(void) {
@@ -25323,9 +25362,8 @@ static bool mg_tcpip_driver_tm4c_init(struct mg_tcpip_if *ifp) {
2532325362 (uint32_t) (uintptr_t) s_txdesc[(i + 1) % ETH_DESC_CNT]; // Chain
2532425363 }
2532525364
25326- EMAC->EMACDMABUSMOD |= MG_BIT(0); // Software reset
25327- while ((EMAC->EMACDMABUSMOD & MG_BIT(0)) != 0)
25328- tm4cspin(1); // Wait until done
25365+ EMAC->EMACDMABUSMOD |= MG_BIT(0); // Software reset
25366+ while ((EMAC->EMACDMABUSMOD & MG_BIT(0)) != 0) (void) 0; // Wait until done
2532925367
2533025368 // Set MDC clock divider. If user told us the value, use it. Otherwise, guess
2533125369 int cr = (d == NULL || d->mdc_cr < 0) ? guess_mdc_cr() : d->mdc_cr;
0 commit comments