diff --git a/cmd_parser.c b/cmd_parser.c index 4fc2b0cf..d1a3e74a 100644 --- a/cmd_parser.c +++ b/cmd_parser.c @@ -364,6 +364,98 @@ void print_ip(__xdata uint8_t * ptr) } } +// Prints a MAC address. +void print_mac(__xdata uint8_t *ptr) +{ + uint8_t idx = 0; + uint8_t num; + + while (1) { + num = *ptr++; + print_byte(num); + if (++idx == 6) + break; + + write_char(':'); + } +} + +// Parses a MAC address (12 hex digits, ':' or '-' separators optional) from +// cmd_buffer starting at idx into mac[6]. Returns the number of bytes +// consumed, or 0 on error. +uint8_t parse_mac(uint8_t idx, __xdata uint8_t *mac) +{ + uint8_t b = 0; + uint8_t hi = 0xff; /* 0xff = waiting for the high nibble */ + uint8_t c; + + while (b < 6) { + c = cmd_buffer[idx]; + if (c == NUL || c == ' ' || c == '\r' || c == '\n') + break; + idx++; + if (c == ':' || c == '-') + continue; + c |= 0x20; + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'a' && c <= 'f') + c -= 'a' - 10; + else + break; + if (hi == 0xff) { + hi = c; + } else { + mac[b++] = (hi << 4) | c; + hi = 0xff; + } + } + if (b != 6 || hi != 0xff) + return 0; + return idx; +} + +// Sets the management MAC from a "mac " command (or prints +// the current one with a bare "mac"). Refuses blank/multicast/locally +// administered/all-zero-OUI addresses so the running MAC stays reachable, and +// re-registers the static L2 management entry so the change applies without a +// reboot. As a regular command a "mac ..." line in the startup config applies +// on every boot (execute_config runs before the final static L2 entry). +void parse_mac_cmd(void) +{ + __xdata uint8_t mac[6]; + + if (cmd_words_len == 1) { + print_string("Current MAC: "); + print_mac(uip_ethaddr.addr); + write_char('\n'); + return; + } + if (cmd_words_len != 2 || !parse_mac(cmd_words_b[1], mac)) { + print_string("Error: mac []\n"); + return; + } + if ((mac[0] & 0x03) || ((mac[0] | mac[1] | mac[2]) == 0)) { + print_string("refusing: must be unicast, globally administered\n"); + return; + } + if (memcmp(mac, uip_ethaddr.addr, 6) == 0) { + print_string("MAC unchanged\n"); + return; + } + + // Swap the static management entry over to the new address: remove the + // old one (still in uip_ethaddr) before overwriting it. + port_l2_static_mgmt(uip_ethaddr.addr, management_vlan, true); + memcpy(uip_ethaddr.addr, mac, 6); + port_l2_static_mgmt(uip_ethaddr.addr, management_vlan, false); + + print_string("MAC set to: "); + print_mac(uip_ethaddr.addr); + write_char('\n'); + print_string("Save the startup config to keep it across reboots\n"); +} + void parse_lag(void) { @@ -1694,6 +1786,8 @@ void cmd_parser(void) __banked igmp_show(); else print_string("Error: igmp on|off|show\n"); + } else if (cmd_compare(0, "mac")) { + parse_mac_cmd(); } else if (cmd_compare(0, "hostname")) { /* "hostname" alone reports the current name; "hostname " * sets it, sanitized to JSON-safe printable ASCII. A name with diff --git a/machine.c b/machine.c index 3ce13d33..dcc34844 100644 --- a/machine.c +++ b/machine.c @@ -247,6 +247,7 @@ __code const struct machine machine = { .led_mux = {0x00, 0x01, 0x04, 0x05, 0x08, 0x09, 0x0c, 0x09, 0x0d, 0x10, 0x11, 0x0e, 0x14, 0x11, 0x12, 0x15, 0x15, 0x16, 0x18, 0x19, 0x1a, 0x19, 0x1d, 0x1e, 0x1c, 0x1d, 0x20, 0x21}, + .mac_flash_offset = 0x1FC000, }; #elif defined MACHINE_SWGT024_V2_0_MANAGED diff --git a/rtl837x_common.h b/rtl837x_common.h index 0d4ccc01..e4b90fed 100644 --- a/rtl837x_common.h +++ b/rtl837x_common.h @@ -173,6 +173,7 @@ void reset_chip(void); void memcpy(__xdata void * __xdata dst, __xdata const void * __xdata src, uint16_t len); void memcpyc(__xdata uint8_t *dst, __code uint8_t *src, uint16_t len); void memset(__xdata uint8_t *dst, __xdata uint8_t v, uint8_t len); +int memcmp(__xdata const void *a, __xdata const void *b, uint16_t len); uint16_t strlen(__code const char *s); uint16_t strlen_x(__xdata const char *s); uint16_t strtox(__xdata uint8_t *dst, __code const char *s); diff --git a/rtlplayground.c b/rtlplayground.c index 700df0b8..88993473 100644 --- a/rtlplayground.c +++ b/rtlplayground.c @@ -359,6 +359,19 @@ void memcpy(__xdata void * __xdata dst, __xdata const void * __xdata src, uint16 *d++ = *s++; } +int memcmp(__xdata const void *a, __xdata const void *b, uint16_t len) +{ + __xdata const uint8_t *x = a; + __xdata const uint8_t *y = b; + while (len--) { + if (*x != *y) + return *x - *y; + x++; + y++; + } + return 0; +} + void memcpyc(__xdata uint8_t *dst, __code uint8_t *src, uint16_t len) { while (len--)