diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2009-02-10 15:25:56 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-02-13 13:45:51 -0500 |
commit | 99cf5f5f3571ce3a837e379d3b87bf5ddf54f17d (patch) | |
tree | cde967301cfcb781d1427112b40b7f7061d2df70 /net | |
parent | 2a5193119269062608582418deba7af82844159a (diff) |
mac80211: dont add BSS when creating IBSS
There's no need to create a BSS struct only to pass it to
ieee80211_sta_join_ibss, so refactor this function into
__ieee80211_sta_join_ibss which takes all the relevant
paramters, and ieee80211_sta_join_ibss which takes a BSS
struct (used when joining an IBSS that already has other
members).
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/ieee80211_i.h | 3 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 107 | ||||
-rw-r--r-- | net/mac80211/scan.c | 8 |
3 files changed, 60 insertions, 58 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index cbc0b7d647f9..87d63fe61bf9 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -953,9 +953,6 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
953 | struct ieee80211_channel *channel, | 953 | struct ieee80211_channel *channel, |
954 | bool beacon); | 954 | bool beacon); |
955 | struct ieee80211_bss * | 955 | struct ieee80211_bss * |
956 | ieee80211_rx_bss_add(struct ieee80211_local *local, u8 *bssid, int freq, | ||
957 | u8 *ssid, u8 ssid_len); | ||
958 | struct ieee80211_bss * | ||
959 | ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, | 956 | ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, |
960 | u8 *ssid, u8 ssid_len); | 957 | u8 *ssid, u8 ssid_len); |
961 | void ieee80211_rx_bss_put(struct ieee80211_local *local, | 958 | void ieee80211_rx_bss_put(struct ieee80211_local *local, |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 46b4817cdea9..c5991ec047be 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -546,14 +546,15 @@ void ieee80211_send_pspoll(struct ieee80211_local *local, | |||
546 | 546 | ||
547 | /* MLME */ | 547 | /* MLME */ |
548 | static void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | 548 | static void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, |
549 | struct ieee80211_bss *bss) | 549 | const size_t supp_rates_len, |
550 | const u8 *supp_rates) | ||
550 | { | 551 | { |
551 | struct ieee80211_local *local = sdata->local; | 552 | struct ieee80211_local *local = sdata->local; |
552 | int i, have_higher_than_11mbit = 0; | 553 | int i, have_higher_than_11mbit = 0; |
553 | 554 | ||
554 | /* cf. IEEE 802.11 9.2.12 */ | 555 | /* cf. IEEE 802.11 9.2.12 */ |
555 | for (i = 0; i < bss->supp_rates_len; i++) | 556 | for (i = 0; i < supp_rates_len; i++) |
556 | if ((bss->supp_rates[i] & 0x7f) * 5 > 110) | 557 | if ((supp_rates[i] & 0x7f) * 5 > 110) |
557 | have_higher_than_11mbit = 1; | 558 | have_higher_than_11mbit = 1; |
558 | 559 | ||
559 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && | 560 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && |
@@ -1546,9 +1547,13 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1546 | } | 1547 | } |
1547 | 1548 | ||
1548 | 1549 | ||
1549 | static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | 1550 | static int __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, |
1550 | struct ieee80211_if_sta *ifsta, | 1551 | struct ieee80211_if_sta *ifsta, |
1551 | struct ieee80211_bss *bss) | 1552 | const u8 *bssid, const int beacon_int, |
1553 | const int freq, | ||
1554 | const size_t supp_rates_len, | ||
1555 | const u8 *supp_rates, | ||
1556 | const u16 capability) | ||
1552 | { | 1557 | { |
1553 | struct ieee80211_local *local = sdata->local; | 1558 | struct ieee80211_local *local = sdata->local; |
1554 | int res = 0, rates, i, j; | 1559 | int res = 0, rates, i, j; |
@@ -1564,7 +1569,7 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
1564 | } | 1569 | } |
1565 | 1570 | ||
1566 | if ((ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) && | 1571 | if ((ifsta->flags & IEEE80211_STA_PREV_BSSID_SET) && |
1567 | memcmp(ifsta->bssid, bss->bssid, ETH_ALEN) == 0) | 1572 | memcmp(ifsta->bssid, bssid, ETH_ALEN) == 0) |
1568 | return res; | 1573 | return res; |
1569 | 1574 | ||
1570 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 + | 1575 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400 + |
@@ -1575,28 +1580,28 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
1575 | return -ENOMEM; | 1580 | return -ENOMEM; |
1576 | } | 1581 | } |
1577 | 1582 | ||
1578 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
1579 | |||
1580 | if (!(ifsta->flags & IEEE80211_STA_PREV_BSSID_SET)) { | 1583 | if (!(ifsta->flags & IEEE80211_STA_PREV_BSSID_SET)) { |
1581 | /* Remove possible STA entries from other IBSS networks. */ | 1584 | /* Remove possible STA entries from other IBSS networks. */ |
1582 | sta_info_flush_delayed(sdata); | 1585 | sta_info_flush_delayed(sdata); |
1583 | } | 1586 | } |
1584 | 1587 | ||
1585 | memcpy(ifsta->bssid, bss->bssid, ETH_ALEN); | 1588 | memcpy(ifsta->bssid, bssid, ETH_ALEN); |
1586 | res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID); | 1589 | res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID); |
1587 | if (res) | 1590 | if (res) |
1588 | return res; | 1591 | return res; |
1589 | 1592 | ||
1590 | local->hw.conf.beacon_int = bss->beacon_int >= 10 ? bss->beacon_int : 10; | 1593 | local->hw.conf.beacon_int = beacon_int >= 10 ? beacon_int : 10; |
1591 | 1594 | ||
1592 | sdata->drop_unencrypted = bss->capability & | 1595 | sdata->drop_unencrypted = capability & |
1593 | WLAN_CAPABILITY_PRIVACY ? 1 : 0; | 1596 | WLAN_CAPABILITY_PRIVACY ? 1 : 0; |
1594 | 1597 | ||
1595 | res = ieee80211_set_freq(sdata, bss->freq); | 1598 | res = ieee80211_set_freq(sdata, freq); |
1596 | 1599 | ||
1597 | if (res) | 1600 | if (res) |
1598 | return res; | 1601 | return res; |
1599 | 1602 | ||
1603 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
1604 | |||
1600 | /* Build IBSS probe response */ | 1605 | /* Build IBSS probe response */ |
1601 | 1606 | ||
1602 | skb_reserve(skb, local->hw.extra_tx_headroom); | 1607 | skb_reserve(skb, local->hw.extra_tx_headroom); |
@@ -1605,33 +1610,32 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
1605 | skb_put(skb, 24 + sizeof(mgmt->u.beacon)); | 1610 | skb_put(skb, 24 + sizeof(mgmt->u.beacon)); |
1606 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); | 1611 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); |
1607 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 1612 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
1608 | IEEE80211_STYPE_PROBE_RESP); | 1613 | IEEE80211_STYPE_PROBE_RESP); |
1609 | memset(mgmt->da, 0xff, ETH_ALEN); | 1614 | memset(mgmt->da, 0xff, ETH_ALEN); |
1610 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | 1615 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); |
1611 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | 1616 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); |
1612 | mgmt->u.beacon.beacon_int = | 1617 | mgmt->u.beacon.beacon_int = |
1613 | cpu_to_le16(local->hw.conf.beacon_int); | 1618 | cpu_to_le16(local->hw.conf.beacon_int); |
1614 | mgmt->u.beacon.timestamp = cpu_to_le64(bss->timestamp); | 1619 | mgmt->u.beacon.capab_info = cpu_to_le16(capability); |
1615 | mgmt->u.beacon.capab_info = cpu_to_le16(bss->capability); | ||
1616 | 1620 | ||
1617 | pos = skb_put(skb, 2 + ifsta->ssid_len); | 1621 | pos = skb_put(skb, 2 + ifsta->ssid_len); |
1618 | *pos++ = WLAN_EID_SSID; | 1622 | *pos++ = WLAN_EID_SSID; |
1619 | *pos++ = ifsta->ssid_len; | 1623 | *pos++ = ifsta->ssid_len; |
1620 | memcpy(pos, ifsta->ssid, ifsta->ssid_len); | 1624 | memcpy(pos, ifsta->ssid, ifsta->ssid_len); |
1621 | 1625 | ||
1622 | rates = bss->supp_rates_len; | 1626 | rates = supp_rates_len; |
1623 | if (rates > 8) | 1627 | if (rates > 8) |
1624 | rates = 8; | 1628 | rates = 8; |
1625 | pos = skb_put(skb, 2 + rates); | 1629 | pos = skb_put(skb, 2 + rates); |
1626 | *pos++ = WLAN_EID_SUPP_RATES; | 1630 | *pos++ = WLAN_EID_SUPP_RATES; |
1627 | *pos++ = rates; | 1631 | *pos++ = rates; |
1628 | memcpy(pos, bss->supp_rates, rates); | 1632 | memcpy(pos, supp_rates, rates); |
1629 | 1633 | ||
1630 | if (bss->band == IEEE80211_BAND_2GHZ) { | 1634 | if (sband->band == IEEE80211_BAND_2GHZ) { |
1631 | pos = skb_put(skb, 2 + 1); | 1635 | pos = skb_put(skb, 2 + 1); |
1632 | *pos++ = WLAN_EID_DS_PARAMS; | 1636 | *pos++ = WLAN_EID_DS_PARAMS; |
1633 | *pos++ = 1; | 1637 | *pos++ = 1; |
1634 | *pos++ = ieee80211_frequency_to_channel(bss->freq); | 1638 | *pos++ = ieee80211_frequency_to_channel(freq); |
1635 | } | 1639 | } |
1636 | 1640 | ||
1637 | pos = skb_put(skb, 2 + 2); | 1641 | pos = skb_put(skb, 2 + 2); |
@@ -1641,12 +1645,12 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
1641 | *pos++ = 0; | 1645 | *pos++ = 0; |
1642 | *pos++ = 0; | 1646 | *pos++ = 0; |
1643 | 1647 | ||
1644 | if (bss->supp_rates_len > 8) { | 1648 | if (supp_rates_len > 8) { |
1645 | rates = bss->supp_rates_len - 8; | 1649 | rates = supp_rates_len - 8; |
1646 | pos = skb_put(skb, 2 + rates); | 1650 | pos = skb_put(skb, 2 + rates); |
1647 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | 1651 | *pos++ = WLAN_EID_EXT_SUPP_RATES; |
1648 | *pos++ = rates; | 1652 | *pos++ = rates; |
1649 | memcpy(pos, &bss->supp_rates[8], rates); | 1653 | memcpy(pos, &supp_rates[8], rates); |
1650 | } | 1654 | } |
1651 | 1655 | ||
1652 | add_extra_ies(skb, sdata->u.sta.ie_proberesp, | 1656 | add_extra_ies(skb, sdata->u.sta.ie_proberesp, |
@@ -1659,16 +1663,15 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
1659 | 1663 | ||
1660 | 1664 | ||
1661 | rates = 0; | 1665 | rates = 0; |
1662 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 1666 | for (i = 0; i < supp_rates_len; i++) { |
1663 | for (i = 0; i < bss->supp_rates_len; i++) { | 1667 | int bitrate = (supp_rates[i] & 0x7f) * 5; |
1664 | int bitrate = (bss->supp_rates[i] & 0x7f) * 5; | ||
1665 | for (j = 0; j < sband->n_bitrates; j++) | 1668 | for (j = 0; j < sband->n_bitrates; j++) |
1666 | if (sband->bitrates[j].bitrate == bitrate) | 1669 | if (sband->bitrates[j].bitrate == bitrate) |
1667 | rates |= BIT(j); | 1670 | rates |= BIT(j); |
1668 | } | 1671 | } |
1669 | ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates; | 1672 | ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates; |
1670 | 1673 | ||
1671 | ieee80211_sta_def_wmm_params(sdata, bss); | 1674 | ieee80211_sta_def_wmm_params(sdata, supp_rates_len, supp_rates); |
1672 | 1675 | ||
1673 | ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET; | 1676 | ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET; |
1674 | ifsta->state = IEEE80211_STA_MLME_IBSS_JOINED; | 1677 | ifsta->state = IEEE80211_STA_MLME_IBSS_JOINED; |
@@ -1677,12 +1680,23 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
1677 | ieee80211_led_assoc(local, true); | 1680 | ieee80211_led_assoc(local, true); |
1678 | 1681 | ||
1679 | memset(&wrqu, 0, sizeof(wrqu)); | 1682 | memset(&wrqu, 0, sizeof(wrqu)); |
1680 | memcpy(wrqu.ap_addr.sa_data, bss->bssid, ETH_ALEN); | 1683 | memcpy(wrqu.ap_addr.sa_data, bssid, ETH_ALEN); |
1681 | wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL); | 1684 | wireless_send_event(sdata->dev, SIOCGIWAP, &wrqu, NULL); |
1682 | 1685 | ||
1683 | return res; | 1686 | return res; |
1684 | } | 1687 | } |
1685 | 1688 | ||
1689 | static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | ||
1690 | struct ieee80211_if_sta *ifsta, | ||
1691 | struct ieee80211_bss *bss) | ||
1692 | { | ||
1693 | return __ieee80211_sta_join_ibss(sdata, ifsta, | ||
1694 | bss->bssid, bss->beacon_int, | ||
1695 | bss->freq, | ||
1696 | bss->supp_rates_len, bss->supp_rates, | ||
1697 | bss->capability); | ||
1698 | } | ||
1699 | |||
1686 | static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | 1700 | static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, |
1687 | struct ieee80211_mgmt *mgmt, | 1701 | struct ieee80211_mgmt *mgmt, |
1688 | size_t len, | 1702 | size_t len, |
@@ -2251,11 +2265,12 @@ static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata, | |||
2251 | struct ieee80211_if_sta *ifsta) | 2265 | struct ieee80211_if_sta *ifsta) |
2252 | { | 2266 | { |
2253 | struct ieee80211_local *local = sdata->local; | 2267 | struct ieee80211_local *local = sdata->local; |
2254 | struct ieee80211_bss *bss; | ||
2255 | struct ieee80211_supported_band *sband; | 2268 | struct ieee80211_supported_band *sband; |
2256 | u8 bssid[ETH_ALEN], *pos; | 2269 | u8 *pos; |
2270 | u8 bssid[ETH_ALEN]; | ||
2271 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; | ||
2272 | u16 capability; | ||
2257 | int i; | 2273 | int i; |
2258 | int ret; | ||
2259 | 2274 | ||
2260 | if (sdata->u.sta.flags & IEEE80211_STA_BSSID_SET) { | 2275 | if (sdata->u.sta.flags & IEEE80211_STA_BSSID_SET) { |
2261 | memcpy(bssid, ifsta->bssid, ETH_ALEN); | 2276 | memcpy(bssid, ifsta->bssid, ETH_ALEN); |
@@ -2273,36 +2288,29 @@ static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata, | |||
2273 | printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %pM\n", | 2288 | printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %pM\n", |
2274 | sdata->dev->name, bssid); | 2289 | sdata->dev->name, bssid); |
2275 | 2290 | ||
2276 | bss = ieee80211_rx_bss_add(local, bssid, | 2291 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
2277 | local->hw.conf.channel->center_freq, | ||
2278 | sdata->u.sta.ssid, sdata->u.sta.ssid_len); | ||
2279 | if (!bss) | ||
2280 | return -ENOMEM; | ||
2281 | |||
2282 | bss->band = local->hw.conf.channel->band; | ||
2283 | sband = local->hw.wiphy->bands[bss->band]; | ||
2284 | 2292 | ||
2285 | if (local->hw.conf.beacon_int == 0) | 2293 | if (local->hw.conf.beacon_int == 0) |
2286 | local->hw.conf.beacon_int = 100; | 2294 | local->hw.conf.beacon_int = 100; |
2287 | bss->beacon_int = local->hw.conf.beacon_int; | 2295 | |
2288 | bss->last_update = jiffies; | 2296 | capability = WLAN_CAPABILITY_IBSS; |
2289 | bss->capability = WLAN_CAPABILITY_IBSS; | ||
2290 | 2297 | ||
2291 | if (sdata->default_key) | 2298 | if (sdata->default_key) |
2292 | bss->capability |= WLAN_CAPABILITY_PRIVACY; | 2299 | capability |= WLAN_CAPABILITY_PRIVACY; |
2293 | else | 2300 | else |
2294 | sdata->drop_unencrypted = 0; | 2301 | sdata->drop_unencrypted = 0; |
2295 | 2302 | ||
2296 | bss->supp_rates_len = sband->n_bitrates; | 2303 | pos = supp_rates; |
2297 | pos = bss->supp_rates; | ||
2298 | for (i = 0; i < sband->n_bitrates; i++) { | 2304 | for (i = 0; i < sband->n_bitrates; i++) { |
2299 | int rate = sband->bitrates[i].bitrate; | 2305 | int rate = sband->bitrates[i].bitrate; |
2300 | *pos++ = (u8) (rate / 5); | 2306 | *pos++ = (u8) (rate / 5); |
2301 | } | 2307 | } |
2302 | 2308 | ||
2303 | ret = ieee80211_sta_join_ibss(sdata, ifsta, bss); | 2309 | return __ieee80211_sta_join_ibss(sdata, ifsta, |
2304 | ieee80211_rx_bss_put(local, bss); | 2310 | bssid, local->hw.conf.beacon_int, |
2305 | return ret; | 2311 | local->hw.conf.channel->center_freq, |
2312 | sband->n_bitrates, supp_rates, | ||
2313 | capability); | ||
2306 | } | 2314 | } |
2307 | 2315 | ||
2308 | 2316 | ||
@@ -2471,7 +2479,8 @@ static int ieee80211_sta_config_auth(struct ieee80211_sub_if_data *sdata, | |||
2471 | ieee80211_sta_set_ssid(sdata, selected->ssid, | 2479 | ieee80211_sta_set_ssid(sdata, selected->ssid, |
2472 | selected->ssid_len); | 2480 | selected->ssid_len); |
2473 | ieee80211_sta_set_bssid(sdata, selected->bssid); | 2481 | ieee80211_sta_set_bssid(sdata, selected->bssid); |
2474 | ieee80211_sta_def_wmm_params(sdata, selected); | 2482 | ieee80211_sta_def_wmm_params(sdata, selected->supp_rates_len, |
2483 | selected->supp_rates); | ||
2475 | if (sdata->u.sta.mfp == IEEE80211_MFP_REQUIRED) | 2484 | if (sdata->u.sta.mfp == IEEE80211_MFP_REQUIRED) |
2476 | sdata->u.sta.flags |= IEEE80211_STA_MFP_ENABLED; | 2485 | sdata->u.sta.flags |= IEEE80211_STA_MFP_ENABLED; |
2477 | else | 2486 | else |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index c6b275b10cf9..fc88e2e2f923 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -14,11 +14,7 @@ | |||
14 | 14 | ||
15 | /* TODO: | 15 | /* TODO: |
16 | * figure out how to avoid that the "current BSS" expires | 16 | * figure out how to avoid that the "current BSS" expires |
17 | * clean up IBSS code (in MLME), see why it adds a BSS to the list | 17 | * use cfg80211's BSS handling |
18 | * use cfg80211's BSS handling (depends on IBSS TODO above) | ||
19 | * order BSS list by RSSI(?) ("quality of AP") | ||
20 | * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE, | ||
21 | * SSID) | ||
22 | */ | 18 | */ |
23 | 19 | ||
24 | #include <linux/wireless.h> | 20 | #include <linux/wireless.h> |
@@ -107,7 +103,7 @@ static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local, | |||
107 | } | 103 | } |
108 | } | 104 | } |
109 | 105 | ||
110 | struct ieee80211_bss * | 106 | static struct ieee80211_bss * |
111 | ieee80211_rx_bss_add(struct ieee80211_local *local, u8 *bssid, int freq, | 107 | ieee80211_rx_bss_add(struct ieee80211_local *local, u8 *bssid, int freq, |
112 | u8 *ssid, u8 ssid_len) | 108 | u8 *ssid, u8 ssid_len) |
113 | { | 109 | { |