ifieee80211.c (188038) | ifieee80211.c (188258) |
---|---|
1/* 2 * Copyright 2001 The Aerospace Corporation. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. --- 10 unchanged lines hidden (view full) --- 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * | 1/* 2 * Copyright 2001 The Aerospace Corporation. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. --- 10 unchanged lines hidden (view full) --- 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * |
27 * $FreeBSD: head/sbin/ifconfig/ifieee80211.c 188038 2009-02-03 00:15:19Z delphij $ | 27 * $FreeBSD: head/sbin/ifconfig/ifieee80211.c 188258 2009-02-07 01:12:51Z sam $ |
28 */ 29 30/*- 31 * Copyright (c) 1997, 1998, 2000 The NetBSD Foundation, Inc. 32 * All rights reserved. 33 * 34 * This code is derived from software contributed to The NetBSD Foundation 35 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, --- 58 unchanged lines hidden (view full) --- 94 95#include "ifconfig.h" 96#include "regdomain.h" 97 98#ifndef IEEE80211_FIXED_RATE_NONE 99#define IEEE80211_FIXED_RATE_NONE 0xff 100#endif 101 | 28 */ 29 30/*- 31 * Copyright (c) 1997, 1998, 2000 The NetBSD Foundation, Inc. 32 * All rights reserved. 33 * 34 * This code is derived from software contributed to The NetBSD Foundation 35 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, --- 58 unchanged lines hidden (view full) --- 94 95#include "ifconfig.h" 96#include "regdomain.h" 97 98#ifndef IEEE80211_FIXED_RATE_NONE 99#define IEEE80211_FIXED_RATE_NONE 0xff 100#endif 101 |
102#define REQ_ECM 0x01000000 /* enable if ECM set */ 103#define REQ_OUTDOOR 0x02000000 /* enable for outdoor operation */ 104#define REQ_FLAGS 0xff000000 /* private flags, don't pass to os */ 105 | |
106/* XXX need these publicly defined or similar */ 107#ifndef IEEE80211_NODE_AUTH 108#define IEEE80211_NODE_AUTH 0x0001 /* authorized for data */ 109#define IEEE80211_NODE_QOS 0x0002 /* QoS enabled */ 110#define IEEE80211_NODE_ERP 0x0004 /* ERP enabled */ 111#define IEEE80211_NODE_PWR_MGT 0x0010 /* power save mode enabled */ 112#define IEEE80211_NODE_HT 0x0040 /* HT enabled */ 113#define IEEE80211_NODE_HTCOMPAT 0x0080 /* HT setup w/ vendor OUI's */ --- 1683 unchanged lines hidden (view full) --- 1797 for (i = 0; i < nchans; i++) { 1798 const struct ieee80211_channel *c = &chans[i]; 1799 if ((c->ic_flags & flags) == flags) 1800 return 1; 1801 } 1802 return 0; 1803} 1804 | 102/* XXX need these publicly defined or similar */ 103#ifndef IEEE80211_NODE_AUTH 104#define IEEE80211_NODE_AUTH 0x0001 /* authorized for data */ 105#define IEEE80211_NODE_QOS 0x0002 /* QoS enabled */ 106#define IEEE80211_NODE_ERP 0x0004 /* ERP enabled */ 107#define IEEE80211_NODE_PWR_MGT 0x0010 /* power save mode enabled */ 108#define IEEE80211_NODE_HT 0x0040 /* HT enabled */ 109#define IEEE80211_NODE_HTCOMPAT 0x0080 /* HT setup w/ vendor OUI's */ --- 1683 unchanged lines hidden (view full) --- 1793 for (i = 0; i < nchans; i++) { 1794 const struct ieee80211_channel *c = &chans[i]; 1795 if ((c->ic_flags & flags) == flags) 1796 return 1; 1797 } 1798 return 0; 1799} 1800 |
1801/* 1802 * Check channel compatibility. 1803 */ 1804static int 1805checkchan(const struct ieee80211req_chaninfo *avail, int freq, int flags) 1806{ 1807 flags &= ~REQ_FLAGS; 1808 /* 1809 * Check if exact channel is in the calibration table; 1810 * everything below is to deal with channels that we 1811 * want to include but that are not explicitly listed. 1812 */ 1813 if (flags & IEEE80211_CHAN_HT40) { 1814 /* NB: we use an HT40 channel center that matches HT20 */ 1815 flags = (flags &~ IEEE80211_CHAN_HT40) | IEEE80211_CHAN_HT20; 1816 } 1817 if (chanlookup(avail->ic_chans, avail->ic_nchans, freq, flags) != NULL) 1818 return 1; 1819 if (flags & IEEE80211_CHAN_GSM) { 1820 /* 1821 * XXX GSM frequency mapping is handled in the kernel 1822 * so we cannot find them in the calibration table; 1823 * just accept the channel and the kernel will reject 1824 * the channel list if it's wrong. 1825 */ 1826 return 1; 1827 } 1828 /* 1829 * If this is a 1/2 or 1/4 width channel allow it if a full 1830 * width channel is present for this frequency, and the device 1831 * supports fractional channels on this band. This is a hack 1832 * that avoids bloating the calibration table; it may be better 1833 * by per-band attributes though (we are effectively calculating 1834 * this attribute by scanning the channel list ourself). 1835 */ 1836 if ((flags & (IEEE80211_CHAN_HALF | IEEE80211_CHAN_QUARTER)) == 0) 1837 return 0; 1838 if (chanlookup(avail->ic_chans, avail->ic_nchans, freq, 1839 flags &~ (IEEE80211_CHAN_HALF | IEEE80211_CHAN_QUARTER)) == NULL) 1840 return 0; 1841 if (flags & IEEE80211_CHAN_HALF) { 1842 return chanfind(avail->ic_chans, avail->ic_nchans, 1843 IEEE80211_CHAN_HALF | 1844 (flags & (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ))); 1845 } else { 1846 return chanfind(avail->ic_chans, avail->ic_nchans, 1847 IEEE80211_CHAN_QUARTER | 1848 (flags & (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ))); 1849 } 1850} 1851 |
|
1805static void 1806regdomain_addchans(struct ieee80211req_chaninfo *ci, 1807 const netband_head *bands, 1808 const struct ieee80211_regdomain *reg, 1809 uint32_t chanFlags, 1810 const struct ieee80211req_chaninfo *avail) 1811{ 1812 const struct netband *nb; 1813 const struct freqband *b; 1814 struct ieee80211_channel *c, *prev; | 1852static void 1853regdomain_addchans(struct ieee80211req_chaninfo *ci, 1854 const netband_head *bands, 1855 const struct ieee80211_regdomain *reg, 1856 uint32_t chanFlags, 1857 const struct ieee80211req_chaninfo *avail) 1858{ 1859 const struct netband *nb; 1860 const struct freqband *b; 1861 struct ieee80211_channel *c, *prev; |
1815 int freq, channelSep, hasHalfChans, hasQuarterChans; | 1862 int freq, hi_adj, lo_adj, channelSep; 1863 uint32_t flags; |
1816 | 1864 |
1865 hi_adj = (chanFlags & IEEE80211_CHAN_HT40U) ? -20 : 0; 1866 lo_adj = (chanFlags & IEEE80211_CHAN_HT40D) ? 20 : 0; |
|
1817 channelSep = (chanFlags & IEEE80211_CHAN_2GHZ) ? 0 : 40; | 1867 channelSep = (chanFlags & IEEE80211_CHAN_2GHZ) ? 0 : 40; |
1818 hasHalfChans = chanfind(avail->ic_chans, avail->ic_nchans, 1819 IEEE80211_CHAN_HALF | 1820 (chanFlags & (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ))); 1821 hasQuarterChans = chanfind(avail->ic_chans, avail->ic_nchans, 1822 IEEE80211_CHAN_QUARTER | 1823 (chanFlags & (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ))); | |
1824 LIST_FOREACH(nb, bands, next) { 1825 b = nb->band; 1826 if (verbose) { 1827 printf("%s:", __func__); 1828 printb(" chanFlags", chanFlags, IEEE80211_CHAN_BITS); 1829 printb(" bandFlags", nb->flags | b->flags, 1830 IEEE80211_CHAN_BITS); 1831 putchar('\n'); 1832 } 1833 prev = NULL; | 1868 LIST_FOREACH(nb, bands, next) { 1869 b = nb->band; 1870 if (verbose) { 1871 printf("%s:", __func__); 1872 printb(" chanFlags", chanFlags, IEEE80211_CHAN_BITS); 1873 printb(" bandFlags", nb->flags | b->flags, 1874 IEEE80211_CHAN_BITS); 1875 putchar('\n'); 1876 } 1877 prev = NULL; |
1834 for (freq = b->freqStart; freq <= b->freqEnd; freq += b->chanSep) { 1835 uint32_t flags = nb->flags | b->flags; 1836 1837 /* check if device can operate on this frequency */ | 1878 for (freq = b->freqStart + lo_adj; 1879 freq <= b->freqEnd + hi_adj; freq += b->chanSep) { |
1838 /* | 1880 /* |
1839 * XXX GSM frequency mapping is handled in the kernel 1840 * so we cannot find them in the calibration table; 1841 * just construct the list and the kernel will reject 1842 * if it's wrong. | 1881 * Construct flags for the new channel. We take 1882 * the attributes from the band descriptions except 1883 * for HT40 which is enabled generically (i.e. +/- 1884 * extension channel) in the band description and 1885 * then constrained according by channel separation. |
1843 */ | 1886 */ |
1844 if (chanlookup(avail->ic_chans, avail->ic_nchans, freq, chanFlags) == NULL && 1845 (flags & IEEE80211_CHAN_GSM) == 0) { | 1887 flags = nb->flags | b->flags; 1888 if (flags & IEEE80211_CHAN_HT) { 1889 /* 1890 * HT channels are generated specially; we're 1891 * called to add HT20, HT40+, and HT40- chan's 1892 * so we need to expand only band specs for 1893 * the HT channel type being added. 1894 */ 1895 if ((chanFlags & IEEE80211_CHAN_HT20) && 1896 (flags & IEEE80211_CHAN_HT20) == 0) { 1897 if (verbose) 1898 printf("%u: skip, not an " 1899 "HT20 channel\n", freq); 1900 continue; 1901 } 1902 if ((chanFlags & IEEE80211_CHAN_HT40) && 1903 (flags & IEEE80211_CHAN_HT40) == 0) { 1904 if (verbose) 1905 printf("%u: skip, not an " 1906 "HT40 channel\n", freq); 1907 continue; 1908 } 1909 /* 1910 * DFS and HT40 don't mix. This should be 1911 * expressed in the regdomain database but 1912 * just in case enforce it here. 1913 */ 1914 if ((chanFlags & IEEE80211_CHAN_HT40) && 1915 (flags & IEEE80211_CHAN_DFS)) { 1916 if (verbose) 1917 printf("%u: skip, HT40+DFS " 1918 "not permitted\n", freq); 1919 continue; 1920 } 1921 /* NB: HT attribute comes from caller */ 1922 flags &= ~IEEE80211_CHAN_HT; 1923 flags |= chanFlags & IEEE80211_CHAN_HT; 1924 } 1925 /* 1926 * Check if device can operate on this frequency. 1927 */ 1928 if (!checkchan(avail, freq, flags)) { |
1846 if (verbose) { 1847 printf("%u: skip, ", freq); | 1929 if (verbose) { 1930 printf("%u: skip, ", freq); |
1848 printb("flags", chanFlags, | 1931 printb("flags", flags, |
1849 IEEE80211_CHAN_BITS); 1850 printf(" not available\n"); 1851 } 1852 continue; 1853 } | 1932 IEEE80211_CHAN_BITS); 1933 printf(" not available\n"); 1934 } 1935 continue; 1936 } |
1854 if ((flags & IEEE80211_CHAN_HALF) && !hasHalfChans) { | 1937 if ((flags & REQ_ECM) && !reg->ecm) { |
1855 if (verbose) | 1938 if (verbose) |
1856 printf("%u: skip, device does not " 1857 "support half-rate channel\n", 1858 freq); | 1939 printf("%u: skip, ECM channel\n", freq); |
1859 continue; 1860 } | 1940 continue; 1941 } |
1861 if ((flags & IEEE80211_CHAN_QUARTER) && 1862 !hasQuarterChans) { | 1942 if ((flags & REQ_INDOOR) && reg->location == 'O') { |
1863 if (verbose) | 1943 if (verbose) |
1864 printf("%u: skip, device does not " 1865 "support quarter-rate channel\n", | 1944 printf("%u: skip, indoor channel\n", |
1866 freq); 1867 continue; 1868 } | 1945 freq); 1946 continue; 1947 } |
1869 if ((flags & IEEE80211_CHAN_HT20) && 1870 (chanFlags & IEEE80211_CHAN_HT20) == 0) { 1871 if (verbose) 1872 printf("%u: skip, device does not " 1873 "support HT20 operation\n", freq); 1874 continue; 1875 } 1876 if ((flags & IEEE80211_CHAN_HT40) && 1877 (chanFlags & IEEE80211_CHAN_HT40) == 0) { 1878 if (verbose) 1879 printf("%u: skip, device does not " 1880 "support HT40 operation\n", freq); 1881 continue; 1882 } 1883 if ((flags & REQ_ECM) && !reg->ecm) { 1884 if (verbose) 1885 printf("%u: skip, ECM channel\n", freq); 1886 continue; 1887 } | |
1888 if ((flags & REQ_OUTDOOR) && reg->location == 'I') { 1889 if (verbose) | 1948 if ((flags & REQ_OUTDOOR) && reg->location == 'I') { 1949 if (verbose) |
1890 printf("%u: skip, outdoor channel\n", freq); | 1950 printf("%u: skip, outdoor channel\n", 1951 freq); |
1891 continue; 1892 } 1893 if ((flags & IEEE80211_CHAN_HT40) && 1894 prev != NULL && (freq - prev->ic_freq) < channelSep) { 1895 if (verbose) 1896 printf("%u: skip, only %u channel " 1897 "separation, need %d\n", freq, 1898 freq - prev->ic_freq, channelSep); 1899 continue; 1900 } 1901 if (ci->ic_nchans == IEEE80211_CHAN_MAX) { 1902 if (verbose) 1903 printf("%u: skip, channel table full\n", 1904 freq); 1905 break; 1906 } 1907 c = &ci->ic_chans[ci->ic_nchans++]; 1908 memset(c, 0, sizeof(*c)); 1909 c->ic_freq = freq; | 1952 continue; 1953 } 1954 if ((flags & IEEE80211_CHAN_HT40) && 1955 prev != NULL && (freq - prev->ic_freq) < channelSep) { 1956 if (verbose) 1957 printf("%u: skip, only %u channel " 1958 "separation, need %d\n", freq, 1959 freq - prev->ic_freq, channelSep); 1960 continue; 1961 } 1962 if (ci->ic_nchans == IEEE80211_CHAN_MAX) { 1963 if (verbose) 1964 printf("%u: skip, channel table full\n", 1965 freq); 1966 break; 1967 } 1968 c = &ci->ic_chans[ci->ic_nchans++]; 1969 memset(c, 0, sizeof(*c)); 1970 c->ic_freq = freq; |
1910 c->ic_flags = chanFlags | 1911 (flags &~ (REQ_FLAGS | IEEE80211_CHAN_HT40)); | 1971 c->ic_flags = flags; |
1912 if (c->ic_flags & IEEE80211_CHAN_DFS) 1913 c->ic_maxregpower = nb->maxPowerDFS; 1914 else 1915 c->ic_maxregpower = nb->maxPower; 1916 if (verbose) { 1917 printf("[%3d] add freq %u ", 1918 ci->ic_nchans-1, c->ic_freq); 1919 printb("flags", c->ic_flags, IEEE80211_CHAN_BITS); --- 48 unchanged lines hidden (view full) --- 1968 regdomain_addchans(ci, &rd->bands_11b, reg, 1969 IEEE80211_CHAN_B, &dc->dc_chaninfo); 1970 if (!LIST_EMPTY(&rd->bands_11g)) 1971 regdomain_addchans(ci, &rd->bands_11g, reg, 1972 IEEE80211_CHAN_G, &dc->dc_chaninfo); 1973 if (!LIST_EMPTY(&rd->bands_11a)) 1974 regdomain_addchans(ci, &rd->bands_11a, reg, 1975 IEEE80211_CHAN_A, &dc->dc_chaninfo); | 1972 if (c->ic_flags & IEEE80211_CHAN_DFS) 1973 c->ic_maxregpower = nb->maxPowerDFS; 1974 else 1975 c->ic_maxregpower = nb->maxPower; 1976 if (verbose) { 1977 printf("[%3d] add freq %u ", 1978 ci->ic_nchans-1, c->ic_freq); 1979 printb("flags", c->ic_flags, IEEE80211_CHAN_BITS); --- 48 unchanged lines hidden (view full) --- 2028 regdomain_addchans(ci, &rd->bands_11b, reg, 2029 IEEE80211_CHAN_B, &dc->dc_chaninfo); 2030 if (!LIST_EMPTY(&rd->bands_11g)) 2031 regdomain_addchans(ci, &rd->bands_11g, reg, 2032 IEEE80211_CHAN_G, &dc->dc_chaninfo); 2033 if (!LIST_EMPTY(&rd->bands_11a)) 2034 regdomain_addchans(ci, &rd->bands_11a, reg, 2035 IEEE80211_CHAN_A, &dc->dc_chaninfo); |
1976 if (!LIST_EMPTY(&rd->bands_11na)) { | 2036 if (!LIST_EMPTY(&rd->bands_11na) && dc->dc_htcaps != 0) { |
1977 regdomain_addchans(ci, &rd->bands_11na, reg, 1978 IEEE80211_CHAN_A | IEEE80211_CHAN_HT20, 1979 &dc->dc_chaninfo); | 2037 regdomain_addchans(ci, &rd->bands_11na, reg, 2038 IEEE80211_CHAN_A | IEEE80211_CHAN_HT20, 2039 &dc->dc_chaninfo); |
1980 regdomain_addchans(ci, &rd->bands_11na, reg, 1981 IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U, 1982 &dc->dc_chaninfo); 1983 regdomain_addchans(ci, &rd->bands_11na, reg, 1984 IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D, 1985 &dc->dc_chaninfo); | 2040 if (dc->dc_htcaps & IEEE80211_HTCAP_CHWIDTH40) { 2041 regdomain_addchans(ci, &rd->bands_11na, reg, 2042 IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U, 2043 &dc->dc_chaninfo); 2044 regdomain_addchans(ci, &rd->bands_11na, reg, 2045 IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D, 2046 &dc->dc_chaninfo); 2047 } |
1986 } | 2048 } |
1987 if (!LIST_EMPTY(&rd->bands_11ng)) { | 2049 if (!LIST_EMPTY(&rd->bands_11ng) && dc->dc_htcaps != 0) { |
1988 regdomain_addchans(ci, &rd->bands_11ng, reg, 1989 IEEE80211_CHAN_G | IEEE80211_CHAN_HT20, 1990 &dc->dc_chaninfo); | 2050 regdomain_addchans(ci, &rd->bands_11ng, reg, 2051 IEEE80211_CHAN_G | IEEE80211_CHAN_HT20, 2052 &dc->dc_chaninfo); |
1991 regdomain_addchans(ci, &rd->bands_11ng, reg, 1992 IEEE80211_CHAN_G | IEEE80211_CHAN_HT40U, 1993 &dc->dc_chaninfo); 1994 regdomain_addchans(ci, &rd->bands_11ng, reg, 1995 IEEE80211_CHAN_G | IEEE80211_CHAN_HT40D, 1996 &dc->dc_chaninfo); | 2053 if (dc->dc_htcaps & IEEE80211_HTCAP_CHWIDTH40) { 2054 regdomain_addchans(ci, &rd->bands_11ng, reg, 2055 IEEE80211_CHAN_G | IEEE80211_CHAN_HT40U, 2056 &dc->dc_chaninfo); 2057 regdomain_addchans(ci, &rd->bands_11ng, reg, 2058 IEEE80211_CHAN_G | IEEE80211_CHAN_HT40D, 2059 &dc->dc_chaninfo); 2060 } |
1997 } 1998 qsort(ci->ic_chans, ci->ic_nchans, sizeof(ci->ic_chans[0]), 1999 regdomain_sort); 2000 } else 2001 memcpy(ci, &dc->dc_chaninfo, 2002 IEEE80211_CHANINFO_SPACE(&dc->dc_chaninfo)); 2003} 2004 --- 2856 unchanged lines hidden --- | 2061 } 2062 qsort(ci->ic_chans, ci->ic_nchans, sizeof(ci->ic_chans[0]), 2063 regdomain_sort); 2064 } else 2065 memcpy(ci, &dc->dc_chaninfo, 2066 IEEE80211_CHANINFO_SPACE(&dc->dc_chaninfo)); 2067} 2068 --- 2856 unchanged lines hidden --- |