/* * TAP-Windows -- A kernel driver to provide virtual tap * device functionality on Windows. * * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. * * This source code is Copyright (C) 2002-2010 OpenVPN Technologies, Inc., * and is released under the GPL version 2 (see below). * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program (see the file COPYING included with this * distribution); if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "macinfo.h" int HexStringToDecimalInt (const int p_Character) { int l_Value = 0; if (p_Character >= 'A' && p_Character <= 'F') l_Value = (p_Character - 'A') + 10; else if (p_Character >= 'a' && p_Character <= 'f') l_Value = (p_Character - 'a') + 10; else if (p_Character >= '0' && p_Character <= '9') l_Value = p_Character - '0'; return l_Value; } BOOLEAN ParseMAC (MACADDR dest, const char *src) { int c; int mac_index = 0; BOOLEAN high_digit = FALSE; int delim_action = 1; MYASSERT (src); MYASSERT (dest); CLEAR_MAC (dest); while (c = *src++) { if (IsMacDelimiter (c)) { mac_index += delim_action; high_digit = FALSE; delim_action = 1; } else if (IsHexDigit (c)) { const int digit = HexStringToDecimalInt (c); if (mac_index < sizeof (MACADDR)) { if (!high_digit) { dest[mac_index] = (char)(digit); high_digit = TRUE; delim_action = 1; } else { dest[mac_index] = (char)(dest[mac_index] * 16 + digit); ++mac_index; high_digit = FALSE; delim_action = 0; } } else return FALSE; } else return FALSE; } return (mac_index + delim_action) >= sizeof (MACADDR); } /* * Generate a MAC using the GUID in the adapter name. * * The mac is constructed as 00:FF:xx:xx:xx:xx where * the Xs are taken from the first 32 bits of the GUID in the * adapter name. This is similar to the Linux 2.4 tap MAC * generator, except linux uses 32 random bits for the Xs. * * In general, this solution is reasonable for most * applications except for very large bridged TAP networks, * where the probability of address collisions becomes more * than infintesimal. * * Using the well-known "birthday paradox", on a 1000 node * network the probability of collision would be * 0.000116292153. On a 10,000 node network, the probability * of collision would be 0.01157288998621678766. */ VOID GenerateRandomMac (MACADDR mac, const unsigned char *adapter_name) { unsigned const char *cp = adapter_name; unsigned char c; unsigned int i = 2; unsigned int byte = 0; int brace = 0; int state = 0; CLEAR_MAC (mac); mac[0] = 0x00; mac[1] = 0xFF; while (c = *cp++) { if (i >= sizeof (MACADDR)) break; if (c == '{') brace = 1; if (IsHexDigit (c) && brace) { const unsigned int digit = HexStringToDecimalInt (c); if (state) { byte <<= 4; byte |= digit; mac[i++] = (unsigned char) byte; state = 0; } else { byte = digit; state = 1; } } } } VOID GenerateRelatedMAC (MACADDR dest, const MACADDR src, const int delta) { COPY_MAC (dest, src); dest[2] += (UCHAR) delta; }