Deleted Added
full compact
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 ---