diff -c Prism2-2002-04-24/driver/modules/prism2_ap.c modules/prism2_ap.c
*** Prism2-2002-04-24/driver/modules/prism2_ap.c	Wed Apr 17 19:48:59 2002
--- modules/prism2_ap.c	Wed May  1 05:09:53 2002
***************
*** 18,23 ****
--- 18,27 ----
   */
  
  #ifndef PRISM2_HOSTAPD
+ struct mac_restrictions *mac_access;
+ struct ap_data *ctrl_ap;
+ static void ap_free_sta(struct ap_data *ap, struct sta_info *sta);
+ 
  static void prism2_send_mgmt(struct net_device *dev,
  			     struct hfa384x_tx_frame *txdesc,
  			     int type, int subtype, char *body,
***************
*** 56,61 ****
--- 60,183 ----
  	return (p - page);
  }
  
+ static int ap_control_proc_read(char *page, char **start, off_t off,
+                             int count, int *eof, void *data)
+ {
+   char *p = page;
+   struct ap_data *ap = (struct ap_data *) data;
+   struct list_head *ptr;
+   struct mac_entry *entry;
+   
+   if (off != 0) {
+     *eof = 1;
+     return 0;
+   }
+ 
+   p += sprintf(p, "MAC policy: %s\n", mac_policies[ap->mac_restrictions.policy]);
+   p += sprintf(p, "MAC entries: %d\n", ap->mac_restrictions.entries);
+   p += sprintf(p, "MAC list:\n");
+ 
+   for(ptr = ap->mac_restrictions.mac_list.next;(ptr != NULL) && (ptr != &ap->mac_restrictions.mac_list);ptr=ptr->next) {
+     entry=list_entry(ptr,struct mac_entry,list);
+     p += sprintf(p, "%02X:%02X:%02X:%02X:%02X:%02X\n", entry->mac_addr[0],entry->mac_addr[1],entry->mac_addr[2],entry->mac_addr[3],entry->mac_addr[4],entry->mac_addr[5]);
+   }
+   return (p - page);
+ }
+ 
+ static int ap_control_add_mac(struct mac_restrictions *mac_restrictions, u8 *mac) {
+   struct list_head *ptr;
+   struct mac_entry *entry;
+ 
+   for(ptr = mac_restrictions->mac_list.next;(ptr != NULL) && (ptr != &mac_restrictions->mac_list);ptr=ptr->next) {
+     entry=list_entry(ptr,struct mac_entry,list);
+     if(memcmp(entry->mac_addr,mac,6)==0)
+       return -1; /* MAC already in list */
+   }
+   if((entry=kmalloc(sizeof(struct mac_entry),GFP_KERNEL))==NULL)
+     return -2;
+   memcpy(entry->mac_addr,mac,6);
+   list_add_tail(&entry->list,&mac_restrictions->mac_list);
+   mac_restrictions->entries++;
+   return 0;
+ }
+ 
+ static int ap_control_del_mac(struct mac_restrictions *mac_restrictions, u8 *mac) {
+   struct list_head *ptr;
+   struct mac_entry *entry;
+ 
+   for(ptr = mac_restrictions->mac_list.next;(ptr != NULL) && (ptr != &mac_restrictions->mac_list);ptr=ptr->next) {
+     entry=list_entry(ptr,struct mac_entry,list);
+     if(memcmp(entry->mac_addr,mac,6)==0) {
+       list_del(ptr);
+       kfree(entry);
+       mac_restrictions->entries--;
+       return 0;
+     }
+   }
+   return -1;
+ }
+ 
+ static int ap_control_mac_deny(struct mac_restrictions *mac_restrictions, u8 *mac) {
+   struct list_head *ptr;
+   struct mac_entry *entry;
+   int found=0;
+ 
+   if (mac_restrictions->policy==MAC_POLICY_OPEN)
+     return 0;
+ 
+   for(ptr = mac_restrictions->mac_list.next;(ptr != NULL) && (ptr != &mac_restrictions->mac_list);ptr=ptr->next) {
+     entry=list_entry(ptr,struct mac_entry,list);
+     if(memcmp(entry->mac_addr,mac,6)==0)
+       found=1;
+   }
+   if(found) {
+     if(mac_restrictions->policy==MAC_POLICY_ALLOW)
+       return 0;
+     else
+       return 1;
+   }
+   else {
+     if(mac_restrictions->policy==MAC_POLICY_DENY)
+       return 0;
+     else
+       return 1;
+   }
+ }
+ 
+ static int ap_control_flush_macs(struct mac_restrictions *mac_restrictions) {
+   struct list_head *ptr;
+   
+   for(ptr = mac_restrictions->mac_list.next;(ptr != NULL) && (ptr != &mac_restrictions->mac_list);ptr = ptr->next) {
+               struct mac_entry *entry;
+               entry=list_entry(ptr,struct mac_entry,list);
+               list_del(ptr);
+               kfree(entry);
+   }
+   mac_restrictions->entries=0;
+   return 0;
+ }
+ 
+ static int ap_control_kickall(struct ap_data *ap) {
+   struct list_head *ptr,*n;
+   
+   for (ptr = ap->sta_list.next, n = ptr->next; ptr != &ap->sta_list; ptr = n, n = ptr->next)
+     ap_free_sta(ap, list_entry(ptr,struct sta_info,list));
+   return 0;
+ }
+ 
+ static int ap_control_kick_mac(struct ap_data *ap, u8 *mac) {
+   struct list_head *ptr,*n;
+   struct sta_info *entry;
+   
+   for (ptr = ap->sta_list.next, n = ptr->next; ptr != &ap->sta_list; ptr = n, n = ptr->next) {
+     entry=list_entry(ptr,struct sta_info,list);
+     if(memcmp(entry->addr,mac,6)==0) {
+       ap_free_sta(ap, entry);
+       return 0;
+     }
+   }
+   return -EINVAL;
+ }
  
  static void ap_sta_hash_add(struct ap_data *ap, struct sta_info *sta)
  {
***************
*** 301,306 ****
--- 423,437 ----
  				       ap_debug_proc_read, ap);
  	}
  
+ 	/* MAC-restriction auth */
+ 	INIT_LIST_HEAD(&ap->mac_restrictions.mac_list);
+ 	if (ap->proc != NULL) {
+ 	       create_proc_read_entry("ap_control", 0, ap->proc,
+ 	                               ap_control_proc_read, ap);
+ 	}
+ 	mac_access=&ap->mac_restrictions;
+ 	ctrl_ap=ap;
+ 	      
  	/* Initialize task queue structure for AP management */
  #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
  	local->ap->ap_queue.next = NULL;
***************
*** 344,349 ****
--- 475,486 ----
  	if (ap->proc != NULL) {
  		remove_proc_entry("ap_debug", ap->proc);
  	}
+         /* MAC restrictions */
+         ap_control_flush_macs(&ap->mac_restrictions);
+  
+         if (ap->proc != NULL) {
+                 remove_proc_entry("ap_control", ap->proc);
+         }
  }
  
  
***************
*** 578,583 ****
--- 715,728 ----
  	}
  
  	if (sta == NULL) {
+ 		if(ap_control_mac_deny(&local->ap->mac_restrictions, rxdesc->addr2))
+ 		{
+ 		       PDEBUG(DEBUG_AP, "AP: STA " MACSTR " auth denied\n",
+ 		                 MAC2STR(rxdesc->addr2));
+ 		       resp = WLAN_STATUS_UNSPECIFIED_FAILURE;
+ 		       goto fail;
+ 		}
+ 
  		PDEBUG(DEBUG_AP, "%s: new STA " MACSTR "\n", dev->name,
  		       MAC2STR(rxdesc->addr2));
  
diff -c Prism2-2002-04-24/driver/modules/prism2_ap.h modules/prism2_ap.h
*** Prism2-2002-04-24/driver/modules/prism2_ap.h	Sat Apr 13 19:22:00 2002
--- modules/prism2_ap.h	Wed May  1 05:15:46 2002
***************
*** 95,100 ****
--- 95,113 ----
  #define AP_QUEUE_LEN 10
  enum { AP_QUEUED_RXDESC, AP_QUEUED_SKB };
  
+ /* MAC address based restrictions */
+ #define AP_CTRL_MAJOR 42
+ struct mac_entry {
+ struct list_head list;
+ 	u8 mac_addr[6];
+ };
+  
+ struct mac_restrictions {
+        unsigned int policy;
+        unsigned int entries;
+        struct list_head mac_list;
+ };
+ 
  /* ap_policy: whether to accept frames to/from other APs/IBSS */
  typedef enum {
  	AP_OTHER_AP_SKIP_ALL = 0,
***************
*** 135,140 ****
--- 148,155 ----
  	struct timer_list timer;
  #endif /* PRISM2_HOSTAPD */
  	struct proc_dir_entry *proc;
+ 	/* MAC based auth */    
+ 	struct mac_restrictions mac_restrictions;
  
  	ap_policy_enum ap_policy;
  	unsigned int max_inactivity;
***************
*** 158,162 ****
--- 173,203 ----
  int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[],
  			   struct iw_quality qual[], int buf_size,
  			   int aplist);
+ /* <macfilter> */
+ 
+ /*
+  * these are the mac add del and flush commands
+  */
+ 
+ enum { AP_CTRL_MAC_ADD,
+        AP_CTRL_MAC_DEL,
+        AP_CTRL_MAC_KICK };
+ 
+ /*
+  * defines descriptions 
+  * for the policies, policies have to be the same numbers
+  */
+ #define MAC_ACCESSLEN 3
+ char mac_policies[MAC_ACCESSLEN][6]={ "open", "allow", "deny" };
+  
+ /*
+  */
+ enum {        MAC_POLICY_OPEN, 
+        MAC_POLICY_ALLOW, 
+        MAC_POLICY_DENY, 
+        
+        AP_CTRL_MAC_FLUSH, 
+        AP_CTRL_KICKALL };
+ /* </macfilter> */
  
  #endif /* PRISM2_AP_H */
diff -c Prism2-2002-04-24/driver/modules/prism2_ioctl.c modules/prism2_ioctl.c
*** Prism2-2002-04-24/driver/modules/prism2_ioctl.c	Sun Apr 21 18:45:12 2002
--- modules/prism2_ioctl.c	Wed May  1 05:26:10 2002
***************
*** 1028,1034 ****
  		{ PRISM2_IOCTL_WDS_ADD,
  		  IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 18, 0, "wds_add" },
  		{ PRISM2_IOCTL_WDS_DEL,
! 		  IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 18, 0, "wds_del" }
  	};
  
  	if (!data->pointer ||
--- 1028,1042 ----
  		{ PRISM2_IOCTL_WDS_ADD,
  		  IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 18, 0, "wds_add" },
  		{ PRISM2_IOCTL_WDS_DEL,
! 		  IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 18, 0, "wds_del" },
! 		{ PRISM2_IOCTL_MACCMD,
! 		  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "maccmd" },
! 		{ PRISM2_IOCTL_ADDMAC,
! 		  IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 18, 0, "addmac" },
! 		{ PRISM2_IOCTL_DELMAC,
! 		  IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 18, 0, "delmac" },
! 		{ PRISM2_IOCTL_KICKMAC,
! 		  IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 18, 0, "kickmac" }
  	};
  
  	if (!data->pointer ||
***************
*** 1394,1399 ****
--- 1402,1548 ----
  		return prism2_wds_del(local, addr, 1, 0);
  }
  
+ static int ap_mac_cmd_ioctl(int cmd){
+       if (cmd < MAC_ACCESSLEN)
+          mac_access->policy = cmd;
+       else {
+               switch (cmd){
+               case AP_CTRL_MAC_FLUSH: 
+                       ap_control_flush_macs(mac_access);
+                       return 0;
+                       break;
+               case AP_CTRL_KICKALL:  
+                       return ap_control_kickall(ctrl_ap);        
+                       break;
+               default:
+                       printk("cmd not allowed\n");
+                       return 1;
+               }
+       }
+ 
+       return 0;
+ }
+ 
+ /* this lineparser is cause the fucking 
+  * /usr/src/linux/lib/vsprintf.c sscanf function 
+  * is broken!
+  *
+  * It can be removed after the fix is done
+  */
+ 
+ int macparser(char *macstring, u8 *mac) {
+       int count=0;
+       int c;
+       int c2;
+       int base;
+       
+       for (c=0;c<=5;c++){
+               *(mac+c)=0;
+               
+               for (c2=0; c2<=1; c2++){
+                       
+                       if (c2 == 0) {
+                               base=16;
+                       } else {
+                               base=1;
+                       }
+                       
+                       switch (*(macstring+count)){
+                               case '0':
+                                       break;
+                               case '1':
+                                       *(mac+c)=(*(mac+c)+1)*base;
+                                       break;
+                               case '2':
+                                       *(mac+c)=(*(mac+c)+2)*base;
+                                       break;
+                               case '3':
+                                       *(mac+c)=(*(mac+c)+3)*base;
+                                       break;
+                               case '4':
+                                       *(mac+c)=(*(mac+c)+4)*base;
+                                       break;
+                               case '5':
+                                       *(mac+c)=(*(mac+c)+5)*base;
+                                       break;
+                               case '6':
+                                       *(mac+c)=(*(mac+c)+6)*base;
+                                       break;
+                               case '7':
+                                       *(mac+c)=(*(mac+c)+7)*base;
+                                       break;
+                               case '8':
+                                       *(mac+c)=(*(mac+c)+8)*base;
+                                       break;
+                               case '9':
+                                       *(mac+c)=(*(mac+c)+9)*base;
+                                       break;
+                               case 'A':
+                                       *(mac+c)=(*(mac+c)+10)*base;
+                                       break;
+                               case 'B':
+                                       *(mac+c)=(*(mac+c)+11)*base;
+                                       break;
+                               case 'C':
+                                       *(mac+c)=(*(mac+c)+12)*base;
+                                       break;
+                               case 'D':
+                                       *(mac+c)=(*(mac+c)+13)*base;
+                                       break;
+                               case 'E':
+                                       *(mac+c)=(*(mac+c)+14)*base;
+                                       break;
+                               case 'F':
+                                       *(mac+c)=(*(mac+c)+15)*base;
+                                       break;
+                               default:
+                                       printk("macparser: char not a hex digit\n");
+                                       return 1;
+                       }
+                       count++;
+               }
+ 
+               switch (*(macstring+count)) {
+                       case ':':
+                               break;
+                       default:
+                               if (c!=5) {
+                                       printk("macparser: not \":\"\n");
+                                       return 1;
+                               }
+               }
+               count++;
+       }
+       return 0;
+ }
+ 
+ static int ap_mac_ioctl(char *macstring, int cmd){
+       u8 mac[6];
+       *(macstring+17)='\0';
+       
+       if (macparser(macstring,mac)==0){
+               
+               switch (cmd) {
+               case AP_CTRL_MAC_ADD:
+                       return ap_control_add_mac(mac_access,mac);
+                       break;
+               case AP_CTRL_MAC_DEL:
+                       return ap_control_del_mac(mac_access,mac);
+                       break;
+               case AP_CTRL_MAC_KICK:
+                       return ap_control_kick_mac(ctrl_ap,mac);
+                       break;
+               default:
+                       printk("Error, ap_mac_ioctl cmd unknown\n");
+                       return 1;
+               }
+ 
+       } else {
+               printk("Error, bad MAC address %s\n",macstring);
+               return 1;
+       }
+       return 0;
+ }
  
  static int prism2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
  {
***************
*** 1585,1591 ****
  						 (char *) wrq->u.data.pointer);
  		break;
  
! 
  	/* not supported wireless extensions */
  #ifdef SIOCSIWNAME
  	case SIOCSIWNAME:
--- 1734,1755 ----
  						 (char *) wrq->u.data.pointer);
  		break;
  
!         case PRISM2_IOCTL_MACCMD:
!                ret=ap_mac_cmd_ioctl((int) wrq->u.data.pointer);
!                break;
!                
!         case PRISM2_IOCTL_ADDMAC:
!                ret=ap_mac_ioctl((char *) wrq->u.data.pointer,AP_CTRL_MAC_ADD);
! 	       break;
!        
!         case PRISM2_IOCTL_DELMAC:
!                ret=ap_mac_ioctl((char *) wrq->u.data.pointer,AP_CTRL_MAC_DEL);
! 	       break;
!        
!         case PRISM2_IOCTL_KICKMAC:
!                ret=ap_mac_ioctl((char *) wrq->u.data.pointer,AP_CTRL_MAC_KICK); 
!                break;
!                   
  	/* not supported wireless extensions */
  #ifdef SIOCSIWNAME
  	case SIOCSIWNAME:
diff -c Prism2-2002-04-24/driver/modules/prism2_wlan.h modules/prism2_wlan.h
*** Prism2-2002-04-24/driver/modules/prism2_wlan.h	Sun Apr 21 18:45:12 2002
--- modules/prism2_wlan.h	Wed May  1 04:39:34 2002
***************
*** 621,626 ****
--- 621,630 ----
  #define PRISM2_IOCTL_INQUIRE (SIOCDEVPRIVATE + 5)
  #define PRISM2_IOCTL_WDS_ADD (SIOCDEVPRIVATE + 6)
  #define PRISM2_IOCTL_WDS_DEL (SIOCDEVPRIVATE + 7)
+ #define PRISM2_IOCTL_MACCMD (SIOCDEVPRIVATE + 8)
+ #define PRISM2_IOCTL_ADDMAC (SIOCDEVPRIVATE + 9)
+ #define PRISM2_IOCTL_DELMAC (SIOCDEVPRIVATE + 10)
+ #define PRISM2_IOCTL_KICKMAC (SIOCDEVPRIVATE + 11)
  
  /* PRISM2_IOCTL_PRISM2_PARAM ioctl() subtypes: */
  enum {

