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); + /* */ + + /* + * 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 }; + /* */ #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 {