Broadcom IOCTLs on OSX

I figured out how to call all the nice ioctls the Broadcom linux driver provides (for linksys APs, cf. under OS X. This is possible since they use one driver source for everything.

This is based on the code found at

You can call arbitrary IOCTLs with this. What they do and what parameters they expect you'll need to figure out yourself.

The wlioctl.h file might give you a hint on what parameters each call expects, I have a list of implemented commands.

The airport.m tool as given must be called when Airport is turned OFF and will perform a loopback test, returning with an error if it fails.

First of all, add this to Apple80211.h

extern WIErr WirelessPrivate(
        WirelessContextPtr inContext,
        void* in_ptr,
        int in_bytes,
        void* out_ptr,
        int out_bytes);

It's the private command call. You can do lots more with it, but I'll leave it at calling the ioctls.

Next, find wlioctl.h, for example from

And finally, here's airport.m, based on the code from It's not clean at all. But you can make it so :)

#include <CoreFoundation/CoreFoundation.h>
#include <Foundation/Foundation.h>
#include <stdio.h>

#include "Apple80211.h"

/* you'll need to strip that file down as it doesn't compile as-is */
#include "wlioctl.h"

WirelessContextPtr gWCtxt = NULL;
char *gProgname;

  WIErr err = 0;

  if(gWCtxt != NULL) {
    err = WirelessDetach(gWCtxt);
    if(err) fprintf(stderr, "Error: WirelessDetach: %d\n", (int) err);

  return err;

wlCheckAvail(int avail)

  fprintf(stderr, "%s: Error: Wireless interface not available!\n",


wlc_ioctl(int command, int bufsize, void* buffer, int outsize, void* out) {
        if (!buffer) bufsize = 0;
        int* buf = malloc(bufsize+8);
        buf[0] = 3; /* private ioctl command code */
        buf[1] = command;
        if (bufsize && buffer)
                memcpy(&buf[2], buffer, bufsize);
        return WirelessPrivate(gWCtxt, buf, bufsize+8, out, outsize);

main(int argc, char **argv)
  WIErr err = 0;
  NSAutoreleasePool *pool;
  int retVal = 0;
  int avail = 0;

  gProgname = argv[0];

  pool = [[NSAutoreleasePool alloc] init];

  avail = WirelessIsAvailable();

  if(avail) {
    err = WirelessAttach(&gWCtxt, 0);
    if(err) {
      fprintf(stderr, "Error: WirelessAttach: %d\n", (int) err);

  int cookie, tmp;
  if (wlc_ioctl(WLC_GET_MAGIC, 0, NULL, 4, &cookie)) {
        fprintf(stderr, "%s: Error: %d\n", gProgname, (int) err);
        return -1;

  if (cookie != 0x14e46c77) {
    fprintf(stderr, "cookie mismatch\n");
        return -1;

  tmp = 1;
  wlc_ioctl(WLC_SET_CLK, 4, &tmp, 0, NULL);
  err = wlc_ioctl(WLC_DIAG_LOOPBACK, 4, &tmp, 0, NULL);
  tmp = 0;
  wlc_ioctl(WLC_SET_CLK, 4, &tmp, 0, NULL);

  if(err != noErr) {
    fprintf(stderr, "%s: Error: %d\n", gProgname, (int) err);
    retVal = -1;


  return retVal;

For a Makefile, copy the one from airport.tar.gz and remove all the hermes stuff.