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)

Reply via email to