diff --git a/sys/net80211/ieee80211_acl.c b/sys/net80211/ieee80211_acl.c index ccd0c2b8b281..2dadff99c730 100644 --- a/sys/net80211/ieee80211_acl.c +++ b/sys/net80211/ieee80211_acl.c @@ -75,6 +75,7 @@ struct acl { struct aclstate { acl_lock_t as_lock; int as_policy; + int as_nacls; TAILQ_HEAD(, acl) as_list; /* list of all ACL's */ LIST_HEAD(, acl) as_hash[ACL_HASHSIZE]; struct ieee80211com *as_ic; @@ -94,7 +95,7 @@ acl_attach(struct ieee80211com *ic) struct aclstate *as; MALLOC(as, struct aclstate *, sizeof(struct aclstate), - M_DEVBUF, M_NOWAIT | M_ZERO); + M_80211_ACL, M_NOWAIT | M_ZERO); if (as == NULL) return 0; ACL_LOCK_INIT(as, "acl"); @@ -138,6 +139,7 @@ _acl_free(struct aclstate *as, struct acl *acl) TAILQ_REMOVE(&as->as_list, acl, acl_list); LIST_REMOVE(acl, acl_hash); FREE(acl, M_80211_ACL); + as->as_nacls--; } static int @@ -186,6 +188,7 @@ acl_add(struct ieee80211com *ic, const u_int8_t mac[IEEE80211_ADDR_LEN]) IEEE80211_ADDR_COPY(new->acl_macaddr, mac); TAILQ_INSERT_TAIL(&as->as_list, new, acl_list); LIST_INSERT_HEAD(&as->as_hash[hash], new, acl_hash); + as->as_nacls++; ACL_UNLOCK(as); IEEE80211_DPRINTF(ic, IEEE80211_MSG_ACL, @@ -260,6 +263,53 @@ acl_getpolicy(struct ieee80211com *ic) return as->as_policy; } +static int +acl_setioctl(struct ieee80211com *ic, struct ieee80211req *ireq) +{ + + return EINVAL; +} + +static int +acl_getioctl(struct ieee80211com *ic, struct ieee80211req *ireq) +{ + struct aclstate *as = ic->ic_as; + struct acl *acl; + struct ieee80211req_maclist *ap; + int error, space, i; + + switch (ireq->i_val) { + case IEEE80211_MACCMD_POLICY: + ireq->i_val = as->as_policy; + return 0; + case IEEE80211_MACCMD_LIST: + space = as->as_nacls * IEEE80211_ADDR_LEN; + if (ireq->i_len == 0) { + ireq->i_len = space; /* return required space */ + return 0; /* NB: must not error */ + } + MALLOC(ap, struct ieee80211req_maclist *, space, + M_TEMP, M_NOWAIT); + if (ap == NULL) + return ENOMEM; + i = 0; + ACL_LOCK(as); + TAILQ_FOREACH(acl, &as->as_list, acl_list) { + IEEE80211_ADDR_COPY(ap[i].ml_macaddr, acl->acl_macaddr); + i++; + } + ACL_UNLOCK(as); + if (ireq->i_len >= space) { + error = copyout(ap, ireq->i_data, space); + ireq->i_len = space; + } else + error = copyout(ap, ireq->i_data, ireq->i_len); + FREE(ap, M_TEMP); + return error; + } + return EINVAL; +} + static const struct ieee80211_aclator mac = { .iac_name = "mac", .iac_attach = acl_attach, @@ -270,6 +320,8 @@ static const struct ieee80211_aclator mac = { .iac_flush = acl_free_all, .iac_setpolicy = acl_setpolicy, .iac_getpolicy = acl_getpolicy, + .iac_setioctl = acl_setioctl, + .iac_getioctl = acl_getioctl, }; /* diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c index e8cf5c4e4f17..9d5a28579fcf 100644 --- a/sys/net80211/ieee80211_ioctl.c +++ b/sys/net80211/ieee80211_ioctl.c @@ -1242,6 +1242,14 @@ ieee80211_ioctl_getwmeparam(struct ieee80211com *ic, struct ieee80211req *ireq) return 0; } +static int +ieee80211_ioctl_getmaccmd(struct ieee80211com *ic, struct ieee80211req *ireq) +{ + const struct ieee80211_aclator *acl = ic->ic_acl; + + return (acl == NULL ? EINVAL : acl->iac_getioctl(ic, ireq)); +} + /* * When building the kernel with -O2 on the i386 architecture, gcc * seems to want to inline this function into ieee80211_ioctl() @@ -1475,6 +1483,9 @@ ieee80211_ioctl_get80211(struct ieee80211com *ic, u_long cmd, struct ieee80211re case IEEE80211_IOC_FRAGTHRESHOLD: ireq->i_val = ic->ic_fragthreshold; break; + case IEEE80211_IOC_MACCMD: + error = ieee80211_ioctl_getmaccmd(ic, ireq); + break; default: error = EINVAL; break; @@ -1740,7 +1751,7 @@ ieee80211_ioctl_macmac(struct ieee80211com *ic, struct ieee80211req *ireq) } static int -ieee80211_ioctl_maccmd(struct ieee80211com *ic, struct ieee80211req *ireq) +ieee80211_ioctl_setmaccmd(struct ieee80211com *ic, struct ieee80211req *ireq) { const struct ieee80211_aclator *acl = ic->ic_acl; @@ -1768,7 +1779,10 @@ ieee80211_ioctl_maccmd(struct ieee80211com *ic, struct ieee80211req *ireq) } break; default: - return EINVAL; + if (acl == NULL) + return EINVAL; + else + return acl->iac_setioctl(ic, ireq); } return 0; } @@ -2302,7 +2316,7 @@ ieee80211_ioctl_set80211(struct ieee80211com *ic, u_long cmd, struct ieee80211re error = ieee80211_ioctl_macmac(ic, ireq); break; case IEEE80211_IOC_MACCMD: - error = ieee80211_ioctl_maccmd(ic, ireq); + error = ieee80211_ioctl_setmaccmd(ic, ireq); break; case IEEE80211_IOC_STA_TXPOW: error = ieee80211_ioctl_setstatxpow(ic, ireq); diff --git a/sys/net80211/ieee80211_ioctl.h b/sys/net80211/ieee80211_ioctl.h index 83ff1182199c..8c3b2abbb2f4 100644 --- a/sys/net80211/ieee80211_ioctl.h +++ b/sys/net80211/ieee80211_ioctl.h @@ -252,6 +252,12 @@ enum { IEEE80211_MACCMD_POLICY_DENY = 2, /* set policy: deny traffic */ IEEE80211_MACCMD_FLUSH = 3, /* flush ACL database */ IEEE80211_MACCMD_DETACH = 4, /* detach ACL policy */ + IEEE80211_MACCMD_POLICY = 5, /* get ACL policy */ + IEEE80211_MACCMD_LIST = 6, /* get ACL database */ +}; + +struct ieee80211req_maclist { + u_int8_t ml_macaddr[IEEE80211_ADDR_LEN]; }; /* diff --git a/sys/net80211/ieee80211_proto.h b/sys/net80211/ieee80211_proto.h index 45fe1641e715..694eff5b6b2d 100644 --- a/sys/net80211/ieee80211_proto.h +++ b/sys/net80211/ieee80211_proto.h @@ -144,6 +144,7 @@ void ieee80211_authenticator_register(int type, void ieee80211_authenticator_unregister(int type); const struct ieee80211_authenticator *ieee80211_authenticator_get(int auth); +struct ieee80211req; /* * Template for an MAC ACL policy module. Such modules * register with the protocol code and are passed the sender's @@ -162,6 +163,8 @@ struct ieee80211_aclator { int (*iac_flush)(struct ieee80211com *); int (*iac_setpolicy)(struct ieee80211com *, int); int (*iac_getpolicy)(struct ieee80211com *); + int (*iac_setioctl)(struct ieee80211com *, struct ieee80211req *); + int (*iac_getioctl)(struct ieee80211com *, struct ieee80211req *); }; void ieee80211_aclator_register(const struct ieee80211_aclator *); void ieee80211_aclator_unregister(const struct ieee80211_aclator *);