[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