Index: vl.c =================================================================== RCS file: /sources/qemu/qemu/vl.c,v retrieving revision 1.317 diff -u -r1.317 vl.c --- vl.c 29 Jun 2007 23:26:08 -0000 1.317 +++ vl.c 1 Jul 2007 11:42:53 -0000 @@ -3020,21 +3020,66 @@ } } +static inline int is_hex_char(char c) +{ + return (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || (c >= '0' && c <= '9'); +} + static int parse_macaddr(uint8_t *macaddr, const char *p) { - int i; - for(i = 0; i < 6; i++) { - macaddr[i] = strtol(p, (char **)&p, 16); - if (i == 5) { - if (*p != '\0') - return -1; - } else { - if (*p != ':') - return -1; - p++; - } - } - return 0; + if (NULL == p) + return -1; + + if ('-' == *p || '+' == *p) + { + /* an offset relative to the default address */ + char *endptr; + int offset = strtol(p, (char**)&endptr, 0); + if ('\0' != *endptr) + return -1; + /* convert the macaddr to 64 bit num, add the offset and convert it back */ + uint64_t macaddr_l = ((uint64_t)macaddr[0] << 40UL) + ((uint64_t)macaddr[1] << 32UL) + + ((uint64_t)macaddr[2] << 24UL) + ((uint64_t)macaddr[3] << 16UL) + ((uint64_t)macaddr[4] << 8UL) + + ((uint64_t)macaddr[5]); + macaddr_l += offset; + macaddr[0] = (uint8_t)((macaddr_l >> 40UL) & 0xFF); + macaddr[1] = (uint8_t)((macaddr_l >> 32UL) & 0xFF); + macaddr[2] = (uint8_t)((macaddr_l >> 24UL) & 0xFF); + macaddr[3] = (uint8_t)((macaddr_l >> 16UL) & 0xFF); + macaddr[4] = (uint8_t)((macaddr_l >> 8UL) & 0xFF); + macaddr[5] = (uint8_t)((macaddr_l >> 0UL) & 0xFF); + } + else if (is_hex_char(*p)) + { + /* a full mac address - hopefully :) */ + int mac_i = 0; + while ('\0' != *p) + { + /* skip separator chars */ + while ( ('\0' != *p) && (':' == *p || '-' == *p) ) p++; + char hex_chars[3]; hex_chars[2] = '\0'; + /* get two hexdec chars and parse it */ + if ( is_hex_char(*p) && is_hex_char(*(p+1)) ) + { + hex_chars[0] = *p; hex_chars[1] = *(p+1); + macaddr[mac_i] = strtol(hex_chars, NULL, 16); + p += 2; mac_i++; + /* the string should contain only 6 pairs */ + if (mac_i >= 6 && *p != '\0') + return -1; + } + else + { + return -1; + } + } + } + else + { + /* error, unexpected character */ + return -1; + } + return 0; } static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)