Building a Wireless Access Point with Linux

Introduction
Hardware
Recompile the kernel
Compile pcmcia-cs
Compile wireless_tools
Get the NIC running
Configure Startup Scripts
Configure Windows Client Machine
Conclusion
Glossary
References

Introduction

This article is outdated. It refers to old versions of the hostap code, old D-Link hardware, and it doesn't work with WEP or WPA. Once I got everything working back in 2002, I did not feel the need to change anything.

This article describes how to build an 802.11b wireless access point using Redhat Linux and a 2.4 kernel. The network interface card used is a D-Link DWL-650 PCMCIA card. The DWL-500 PCI card is also supported. You can use this article to configure a wireless Linux client as well; the difference between a WAP and a client is only 1 line in /etc/pcmcia/wireless.opts.

The Linux WAP server described in this document uses Infrastructure (aka "managed") mode. I originally tried Ad-Hoc mode, but I found that Adhoc mode worked fine as long as I had exactly two wireless peers in my network. As soon as I added a third machine, Ad-Hoc mode started behaving badly. I saw serious packet loss, and one member of the cell would periodically "drop out" and decide to form its own cell. These problems went away when I decided to use Managed mode instead.

Hardware

DWL-650 PCMCIA DWL-650 Cardbus DWL-650+ Cardbus DWL-500 PCI/PCMCIA
DWL-650
PCMCIA
802.11b
works for me
DWL-650
Cardbus
802.11b
?
DWL-650+
Cardbus
802.11g
see sourceforge
DWL-500
PCI/PCMCIA
802.11b
works for me

I use the DWL-650 PCMCIA card. PCMCIA is 16 bit technology and is known as "PC Card". D-Link also makes a second generation DWL-650 Cardbus card that uses 32 bit technology. I do not have any Cardbus hardware, so I am not able to test these 32 bit DWL-650 Cardbus cards. If you are successful in getting a DWL-650 Cardbus adapter working, please let me know if I need to update this article.

D-Link also sells the more recent DWL-650+ Cardbus adapter (note the plus sign!). This card uses the Texas Instruments ACX 100 chipset unlike the PrismII chipset of its predecessor. See the Sourceforge project page for DWL-650+ support. I do not have experience with the DWL-650+.

The DWL-500 is a PCI card that has a PCMCIA socket to accommodate a DWL-650 PCMCIA card. The DWL-500 bridges PCI to PCMCIA. D-Link does not market the DWL-500 any more, but you can find them on eBay.

My WAP machine is a Sabre 1815 purchased at my local Fry's Electronics. It is small, quiet, and has a built-in PCMCIA slot. I chose the DWL-650 PCMCIA card because of its low cost and Linux support. I have three of these cards, one in the Linux WAP and the remaining two in my Linux and Windows 2000 clients.

Recompile the kernel

You need a 2.4.4 or later kernel. I have used Redhat Linux 7.2, 7.3, 8.0, and 9.0 successfully.

Set the following options with "make xconfig":

  1. Disable version information on all module symbols under "Loadable Module support"
  2. Disable PCMCIA under "General Setup"
  3. Enable Wireless LAN (CONFIG_NET_RADIO) under "Network Device Support"
  4. Enable iptables under Networking Options: "Network packet filtering (replaces ipchains)" and enable iptables options under "IP: Netfilter Configuration"
Here is my kernel config file. The steps for recompiling Linux kernels can be found in the Linux Kernel Howto at The Linux Documentation Project. Reboot with your new kernel.

Compile pcmcia-cs

PCMCIA support in the kernel is constantly updated. The separate pcmcia-cs ("card services") package provides the most recent PCMCIA support and is compiled outside the kernel. You must build the kernel with PCMCIA disabled in order to compile the pcmcia-cs drivers as modules. If you don't, the pcmcia-cs make will report, "Your kernel is already configured with PCMCIA support" and refuse to compile. (The concept of pcmcia-cs as a separate component outside the kernel will go away in the 2.5 and 2.6 kernels.)

Even though generic PCMCIA support is enabled with the pcmcia-cs package, you still need to install a driver for your specific wireless NIC. The D-Link DWL-650 is an Intersil PrismII-based card (a rebranded WaveLAN card). Unfortunately, the prism2 driver in pcmcia-cs is not the most recent. You will need to install a recent prism2 driver in addition to pcmcia-cs to get a driver that supports WAP functionality. Older versions of the prism2 driver are called prism2.o, while newer versions are called hostap_cs.o. Follow the Prism2 README to copy the prism2 source files on top of the pcmcia-cs source.

Using the latest and greatest version of the hostap_cs driver is not always advised. Sometimes the leading edge is the bleeding edge. I say this without any disrespect to the hostap_cs author. The hostap_cs driver is extremely solid. In fact, it is the only driver I have found to work with my DWL-650. I have tried wvlan_cs, orinoco_cs, and wlan-ng to no avail, and I'm not the only one. The hostap_cs driver works quite well, and once I found a version that worked, I continued to use it. Here are some combinations that I have observed to work:

Update: I have found that WEP does not work with these versions. WEP will seem to work at first, but then the hostap driver will lock up after a certain amount of network traffic. If you want WEP, you'll need to use more recent versions. I do not have experience with more recent versions, so you are on your own in this case.

If you use a version of pcmcia-cs that is not compatible with your kernel, you may see "prism2: CardServices release does not match!" in the output of dmesg after loading the module. Things will not work in this state, and you need to find a version of pcmcia-cs that does not produce this error when used in conjunction with your kernel.

After compiling and doing a make install, you should see your newly created modules in /lib/modules/2.4.x/pcmcia/. For RedHat 7.2 only, you will need to edit /etc/pcmcia/prism2.conf to reflect using the hostap_cs driver instead of prism2.

Compile wireless_tools (Redhat 7.2 only)

You need the iwconfig program to set the 802.11b characteristics of the card. iwconfig is part of wireless_tools, a set of user-space programs used to control wireless pcmcia cards. This program may already be present with your Linux distribution. If you need to download and compile it, be sure to configure the Makefile to point to your kernel source's headers, not the current headers in /usr/include/linux, which may be outdated. This diff shows the options you will need for a Redhat 7.2 install. I had to install the man pages manually (no pun intended) with cp.

Get the NIC running

Now you need to configure the PCMCIA subsystem and start it up.
  1. Edit /etc/sysconfig/pcmcia to configure your PCMCIA interface controller. Redhat's anaconda program may configure your interface controller to use the "yenta_socket" driver, but that driver is only used when PCMCIA is compiled into your kernel.

    This is what /etc/sysconfig/pcmcia may look like before editing:

    PCMCIA=yes
    PCIC=yenta_socket
    PCIC_OPTS=
    CORE_OPTS=
    
    Configure the file like this if you are using a DWL-650 without the DWL-500:
    PCMCIA=yes 
    PCIC=i82365
    PCIC_OPTS= 
    CORE_OPTS= 
    
    Configure the file like this if you are using the DWL-500:
    PCMCIA=yes 
    PCIC=i82365
    PCIC_OPTS="irq_mode=0"
    CORE_OPTS= 
    
    Do man i82365 for more info on the irq_mode setting for the DWL-500. The PCMCIA interface controller needs to be configured to use PCI interrupts with the DWL-500. This makes sense since the DWL-500 is a PCI card!
  2. Restart pcmcia services.
    # /etc/init.d/pcmcia restart
    
  3. You should now be able to do iwconfig wlan0 and see something like this:
    # iwconfig wlan0
    
    wlan0 IEEE 802.11-DS  ESSID:"wireless"  
          Mode:Ad-Hoc  Frequency:2.422GHz  Cell: 02:05:90:0D:EF:A7
          Bit Rate:11Mb/s   Sensitivity=1/3  
          RTS thr=2347 B   Fragment thr=2346 B   
          Encryption key:off
          Link Quality:0  Signal level:0  Noise level:0
          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
          Tx excessive retries:0  Invalid misc:44  Missed beacon:0
    
    Note the valid Ethernet MAC address as well as the 11Mb/sec sync rate. If you see instead
    wlan0     no wireless extensions.
    
    that means you did something wrong during the compilation steps.
  4. Configure the wlan0 device. You will need to give it an IP address so that it shows up in iwconfig.
    # iwconfig wlan0 mode modetype
      (where modetype is either "master" or "managed" for wap or client, respectively)
    # iwconfig wlan0 essid wireless
      (where "wireless" is just an example)
    # ifconfig wlan0 192.168.x.y
    

    You will need to choose an essid string that identifies your wireless network ("wireless" in this example) and an IP address that makes sense for your network.

  5. If you are a wireless linux client, you should be able to ping the wap IP address now.
  6. You can examine /proc/net/prism2/wlan0/macaddr to view statistics of the wlan0 interface.

Configure Startup Scripts

Now that the physical layer is running, all that's left is configuring the Linux startup files so that the PCMCIA NIC is correctly initialized at bootup.
  1. Enable ip_forwarding in /etc/sysctl.conf on the WAP machine only. This will allow the WAP to route packets.
  2. Configure /etc/pcmcia/config to have a section for the D-Link card if it isn't already there.
    card "D-Link DWL-650"
      version "D", "Link DWL-650 11Mbps WLAN Card"
      bind "hostap_cs"
    
    The driver in the bind line only matters in RedHat 7.2.
  3. Configure /etc/pcmcia/wireless.opts for the type of station you have (wap or client).
    # Pick up any Access Point, should work on most 802.11 cards
    *,*,*,*)
        ESSID="wireless"
        RATE="auto"
        MODE="master" # "master" for wap; "managed" for client
        ;;
    
  4. Edit /etc/pcmcia/network.opts with your wireless IP address information. Using this file forces your ESSID to be set properly at bootup. I wouldn't rely on /etc/sysconfig/network-scripts/ifcfg-wlan0 because Redhat 9 moved the device configuration scripts to /etc/sysconfig/networking/devices/. Use redhat-config-network at your discretion.
  5. Make sure the following commands work without errors:
    # /etc/init.d/pcmcia restart
    # /etc/init.d/network restart
    
  6. Make sure you can still ping.
  7. Reboot just to make sure everything starts up properly.
  8. Ping and surf to hosts on the other side of your new wireless access point.
  9. Topics such as DHCP, bridging, iptables, and wireless security are left as exercises for the reader.

Configure Windows Client Machine

Install a DWL-650 in your client laptop following the D-Link instructions. Configure the NIC for 802.11b "Infrastructure" mode using the D-Link configuration program. Set the SSID to your "wireless" string.
configuration linkinfo
You should see the angry red icon turn into a happy green icon in the system tray when the Windows client has successfully synced up with the Linux wap.

Assign a static IP address to the wireless NIC using the Network Control Panel. You should now be able to ping the IP address of the Linux server's wlan0 interface from a DOS prompt. If you get physical sync but can't ping, you probably forgot to assign an IP address to the wlan0 interface on the Linux box.

Conclusion

This article described how to create a wireless access point with Linux. In summary, the steps are:
  1. Recompile the kernel without pcmcia support.
  2. Overlay the Prism2 driver source on the pcmcia-cs source and compile the modules outside the kernel.
  3. Edit the appropriate files in /etc/pcmcia/ and /etc/sysconfig/
  4. Restart pcmcia with /etc/init.d/pcmcia restart

Glossary

BSS = Basic Service Set
A cell of stations which may or may not have an access point. A "coordination function" acts as collision detection.
IBSS = Independent Basic Service Set
A self-contained BSS with no access point, one of the members can assume the "coordination function". This is the 802.11 peer-to-peer mode of operation also known as Ad-Hoc mode. Only one wireless "cell" is supported for each different SSID. All communication is done from Client to Client without the use of an Access Point. Clients use the same SSID for establishing the wireless connection.
SSID = Service Set Identifier
A 32 octet-long network name; exactly one per ESS or IBSS.
Infrastructure mode = Managed mode
This mode of operation requires the presence of an 802.11 Access Point. All communication is done via the Access Point which relays packets to other wireless Clients in the BSS as well as to nodes on a wired network such as Ethernet.
ESS = Extended Service Set
A set of one or more interconnected BSSes. All traffic flows through an access point.
BSSID
6 octet cell identifier for a BSS. Value is the same as access point MAC address. Used in iwconfig for the cell value.

References

http://hostap.epitest.fi
Prism2 driver that provides wireless access point functionality.
http://pcmcia-cs.sourceforge.net/
pcmcia-cs homepage
http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Tools.html
wireless_tools homepage
http://www.oreillynet.com/pub/a/wireless/2001/03/06/recipe.html
O'Reilly article, Recipe for a Linux 802.11b Home Network
http://www.focusresearch.com/gregor/dwl-650/ (DEAD LINK)
How to use the DWL-650 as a client. I found the wvlan_cs driver to croak under heavy load.
ftp://download.intel.com/technology/itj/q22000/pdf/art_5.pdf
Overview of IEEE 802.11b Security
http://www.handhelds.org/pipermail/handhelds/19/1903.html
DWL-650 on a Compaq ipaq
http://www.linux-wlan.org/
The WLAN-NG package, which I could not get to work.