[kismac] Changing MAC address in Tiger - A partial solution
- From: "Java Nut" <javanut20@xxxxxxxxxxx>
- To: wirelessdriver-devel@xxxxxxxxxxxxxxxxxxxxx
- Date: Fri, 09 Sep 2005 22:06:34 -0500
I dug into the CVS code for beta 6 of the Source Forge Wireless Driver and
added extra IOLog statements and experimental code to explore the difficulty
in changing the Mac Address in Tiger.
I had success revising the driver to use a hardcoded address and identified
the issues that prevent the feature from working in the CVS code.
Perhaps, after seeing my partial solution below, someone can offer me some
advice on how to proceed to complete a fix, or take my information and run
with it.
The issues are as follows:
1) org_noncontiguous_WirelessDriver::init(OSDictionary * properties) is
seldom called in Tiger, so the code that is included in the CVS version to
setup the custom Mac seldomly executes. I do not know the rules of when it
should execute, but the Kernal seems to call it rarely, and not even
consistently on every startup or card insertion.
2) When init() is called, the following expression returns a null pointer:
OSString *str = OSDynamicCast(OSString,
properties->getObject(kIOMACAddress));
This prevents the Wireless Driver from reading the MAC address that is
stored in info.plist by the WirelessMac application.
Being unfamiliar with specifics of OS X programming and Unix device driver
programming, I do not know how to iterate through the OSDictionary to see
what is in it, but would like to use IOLog statements to see what is going
on.
3) If I hard code a MAC in both init() and
org_noncontiguous_WirelessDriver::_wi_readChipInfos(), the MAC *will* take
effect. See code snippets below for how I did this.
In Tiger, _wi_readChipInfos() is called after init(), if init() is called at
all. So any custom MAC set in init() (if the OSDynamicCast returned a
value) would get overwritten with the hardware address in
_wi_readChipInfos(), if the custom MAC is not set in that method.
4) I do not know how to access the info.plist or the user's
org.noncontiguous.WirelessDriver.plist (in user's preferences) from
_wi_readChipInfos().
5) I do not know how to add a field on the preference pane and get the value
down to the Wireless Driver.
What version of XCode should be used to build the preference pane? I have
only rebuilt the WirelessDriver.kext in Tiger without errors (after deleting
a non-existent file from the project). I am curious, which version(s) of
XCode were last used to build the kext and the other parts in the CVS?
6) If I change the Wireless Driver and want to replace my
WirelessDriver.kext with a new build after having installed KisMac, is there
anything I need to do to it other then placing the following empty file
inside the kext to enable it to work with Kismac?
-rw-r--r-- 1 root wheel 0 Jun 12 21:01 bipatch
In otherwords, what exactly does Kismac do to the Wireless Driver as it
installs its patch, that I would need to replicate if I replace the Wireless
Driver after installing Kismac?
In conclusion, all that remains to repair the feature to set the MAC is to
find a way to pass a user's desired MAC address string down to
_wi_readChipInfos() methods and then to call _setMyAddress() from there. It
probably does not need to be in init().
How to Hard Code a MAC address in the Wireless Driver for Tiger:
In PCCardTemplate.h, add:
void _setMyAddress(OSString *str);
In PCCardTemplate.cpp, in method
org_noncontiguous_WirelessDriver::init(OSDictionary * properties), replace
the following:
OSString *str = OSDynamicCast(OSString,
properties->getObject(kIOMACAddress));
if (str) {
memset(myAddress.bytes,0,kIOEthernetAddressSize);
if ((str->getLength()<=17)&&(str->getLength()>=11)) {
int cur = 0;
int val;
char c;
for (unsigned int i = 0; i < str->getLength(); i++) {
c = str->getChar(i);
if ( c != ':' ) {
if (( c >= '0' ) && ( c <= '9')) val = c - 0x30;
else if (( c >= 'A' ) && ( c <= 'F')) val = c - 0x37;
else if (( c >= 'a' ) && ( c <= 'f')) val = c - 0x57;
else val = 0;
myAddress.bytes[cur]=((myAddress.bytes[cur] << 4) + val)
& 0xFF;
} else if ((++cur)==6) break;
}
IOLog("%s: init(): custom MAC address detected. set MAC to
%.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", getName(), myAddress.bytes[0],
myAddress.bytes[1], myAddress.bytes[2], myAddress.bytes[3],
myAddress.bytes[4], myAddress.bytes[5]);
} else {
IOLog("%s: init(): invalid MAC address.\n", getName());
memset(myAddress.bytes,0,kIOEthernetAddressSize);
}
} else {
memset(myAddress.bytes,0,kIOEthernetAddressSize);
}
with this:
memset(myAddress.bytes,0,kIOEthernetAddressSize);
str = OSString::withCString("00:11:22:33:44:55");
_setMyAddress(str);
In Wireless_Private.cpp, add the following method:
void org_noncontiguous_WirelessDriver::_setMyAddress(OSString *str)
{
IOLog("org_noncontiguous_WirelessDriver::_setMyAddress entry");
if (str) {
IOLog("org_noncontiguous_WirelessDriver::_setMyAddress - Custom MAC String
found");
if ((str->getLength()<=17)&&(str->getLength()>=11)) {
int cur = 0;
int val;
char c;
for (unsigned int i = 0; i < str->getLength(); i++) {
c = str->getChar(i);
if ( c != ':' ) {
if (( c >= '0' ) && ( c <= '9')) val = c - 0x30;
else if (( c >= 'A' ) && ( c <= 'F')) val = c - 0x37;
else if (( c >= 'a' ) && ( c <= 'f')) val = c - 0x57;
else val = 0;
myAddress.bytes[cur]=((myAddress.bytes[cur] << 4) + val)
& 0xFF;
} else if ((++cur)==6) break;
}
IOLog("%s::_setMyAddress: custom MAC address detected. set MAC =
%.2X:%.2X:%.2X:%.2X:%.2X:%.2X\n", getName(), myAddress.bytes[0],
myAddress.bytes[1], myAddress.bytes[2], myAddress.bytes[3],
myAddress.bytes[4], myAddress.bytes[5]);
} else {
IOLog("%s::_setMyAddress: invalid MAC address.\n", getName());
}
}
}
In Wireless_Private.cpp,
org_noncontiguous_WirelessDriver::_wi_readChipInfos() method, add the
following line:
_setMyAddress(OSString::withCString("00:11:22:33:44:55"));
immediately after
memcpy(&myAddress, mac.wi_mac_addr, ETHER_ADDR_LEN);
Other related posts:
- » [kismac] Changing MAC address in Tiger - A partial solution