diff --git a/hostapd/config_file.c b/hostapd/config_file.c index 19d6ad324..0ec170131 100644 --- a/hostapd/config_file.c +++ b/hostapd/config_file.c @@ -2907,6 +2907,14 @@ static int hostapd_config_fill(struct hostapd_config *conf, "sae_groups value '%s'", line, pos); return 1; } + } else if (os_strcmp(buf, "local_pwr_constraint") == 0) { + int val = atoi(pos); + if (val < 0 || val > 255) { + wpa_printf(MSG_ERROR, "Line %d: Invalid local_pwr_constraint %d (expected 0..255)", + line, val); + return 1; + } + conf->local_pwr_constraint = val; } else { wpa_printf(MSG_ERROR, "Line %d: unknown configuration " "item '%s'", line, buf); diff --git a/hostapd/hostapd.conf b/hostapd/hostapd.conf index c503ce290..63232d750 100644 --- a/hostapd/hostapd.conf +++ b/hostapd/hostapd.conf @@ -108,6 +108,13 @@ ssid=test # (default: 0 = disabled) #ieee80211h=1 +# Add Power Constraint element to Beacon and Probe Response frames +# This config option adds Power Constraint element when applicable and Country +# element is added. Power Constraint element is required by Transmit Power +# Control. This can be used only with ieee80211d=1. +# Valid values are 0..255. +#local_pwr_constraint=3 + # Operation mode (a = IEEE 802.11a, b = IEEE 802.11b, g = IEEE 802.11g, # ad = IEEE 802.11ad (60 GHz); a/g options are used with IEEE 802.11n, too, to # specify band) diff --git a/src/ap/ap_config.c b/src/ap/ap_config.c index 368b2020e..a9e8bfac1 100644 --- a/src/ap/ap_config.c +++ b/src/ap/ap_config.c @@ -154,6 +154,8 @@ struct hostapd_config * hostapd_config_defaults(void) conf->rts_threshold = -1; /* use driver default: 2347 */ conf->fragm_threshold = -1; /* user driver default: 2346 */ conf->send_probe_response = 1; + /* Set to invalid value means do not add Power Constraint IE */ + conf->local_pwr_constraint = -1; conf->wmm_ac_params[0] = ac_be; conf->wmm_ac_params[1] = ac_bk; @@ -829,6 +831,12 @@ int hostapd_config_check(struct hostapd_config *conf, int full_config) return -1; } + if (full_config && conf->local_pwr_constraint != -1 && + !conf->ieee80211d) { + wpa_printf(MSG_ERROR, "Cannot add Power Constraint element without Country element"); + return -1; + } + for (i = 0; i < conf->num_bss; i++) { if (hostapd_config_check_bss(conf->bss[i], conf, full_config)) return -1; diff --git a/src/ap/ap_config.h b/src/ap/ap_config.h index 4631ca9ed..26a0ef6c9 100644 --- a/src/ap/ap_config.h +++ b/src/ap/ap_config.h @@ -519,6 +519,13 @@ struct hostapd_config { int ieee80211h; /* DFS */ + /* + * Local power constraint is an octet encoded as an unsigned integer in + * units of decibels. Invalid value -1 indicates that Power Constraint + * element will not be added. + */ + int local_pwr_constraint; + struct hostapd_tx_queue_params tx_queue[NUM_TX_QUEUES]; /* diff --git a/src/ap/beacon.c b/src/ap/beacon.c index b1ebf6e3a..d84af9534 100644 --- a/src/ap/beacon.c +++ b/src/ap/beacon.c @@ -102,6 +102,36 @@ static u8 * hostapd_eid_erp_info(struct hostapd_data *hapd, u8 *eid) } +static u8 * hostapd_eid_pwr_constraint(struct hostapd_data *hapd, u8 *eid) +{ + u8 *pos = eid; + + if (hapd->iconf->local_pwr_constraint == -1 || + hapd->iface->current_mode == NULL || + hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A) + return eid; + + /* + * A STA that is not an AP shall use a transmit power less than or + * equal to the local maximum transmit power level for the channel. + * The local maximum transmit power can be calculated from the formula: + * local max TX pwr = max TX pwr - local pwr constraint + * Where max TX pwr is maximum transmit power level specified for + * channel in Country element and local pwr constraint is specified + * for channel in this Power Constraint element. + */ + + /* Element ID */ + *pos++ = WLAN_EID_PWR_CONSTRAINT; + /* Length */ + *pos++ = 1; + /* Local Power Constraint */ + *pos++ = hapd->iconf->local_pwr_constraint; + + return pos; +} + + static u8 * hostapd_eid_country_add(u8 *pos, u8 *end, int chan_spacing, struct hostapd_channel_data *start, struct hostapd_channel_data *prev) @@ -315,6 +345,9 @@ static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, pos = hostapd_eid_country(hapd, pos, epos - pos); + /* Power Constraint element */ + pos = hostapd_eid_pwr_constraint(hapd, pos); + /* ERP Information element */ pos = hostapd_eid_erp_info(hapd, pos); @@ -721,6 +754,9 @@ int ieee802_11_build_ap_params(struct hostapd_data *hapd, tailpos = hostapd_eid_country(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE - tailpos); + /* Power Constraint element */ + tailpos = hostapd_eid_pwr_constraint(hapd, tailpos); + /* ERP Information element */ tailpos = hostapd_eid_erp_info(hapd, tailpos);