Hello all.
Attached is an other patch (against the CVS) to allow for more flexible mac
address parsing from the command line. Specifically it allows:
-using the '-' as separator (as Windows uses it)
-using no separator at all (just 12 hexadecimal characters in a row) - again
Windows uses this style in some configuration dialogs
-using an offset from the default address (like +2 or -10). This is useful for
quickly bringing up a virtual lan without having to remember the base macaddr,
you just specify different offsets (an other option would be to use mac
addresses like 12:34:56:78:9A:BC which are easy to remember, however I found
that WinXP for example does not react well - duplicate packets, no conectivity
at the IP level although the ARP level is fine, etc - if the OUI - the first 3
bytes of the mac address - is incorrect)
Also, there was a suggestion on the list some time ago to use the crc of the
path to the disk image as part of the macaddr to ensure uniqueness. If people
feel that this would be useful, I'm happy to provide a patch.
Best regards
___________________________________________________________
Yahoo! Mail is the world's favourite email. Don't settle for less, sign up for
your free account today
http://uk.rd.yahoo.com/evt=44106/*http://uk.docs.yahoo.com/mail/winter07.html 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)