Deleted Added
full compact
ieee80211_ioctl.c (187800) ieee80211_ioctl.c (187801)
1/*-
2 * Copyright (c) 2001 Atsushi Onoe
3 * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 11 unchanged lines hidden (view full) ---

20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2001 Atsushi Onoe
3 * Copyright (c) 2002-2009 Sam Leffler, Errno Consulting
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:

--- 11 unchanged lines hidden (view full) ---

20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_ioctl.c 187800 2009-01-27 23:19:36Z sam $");
28__FBSDID("$FreeBSD: head/sys/net80211/ieee80211_ioctl.c 187801 2009-01-27 23:42:14Z sam $");
29
30/*
31 * IEEE 802.11 ioctl support (FreeBSD-specific)
32 */
33
34#include "opt_inet.h"
35#include "opt_ipx.h"
36#include "opt_wlan.h"

--- 654 unchanged lines hidden (view full) ---

691}
692
693static __noinline int
694ieee80211_ioctl_getdevcaps(struct ieee80211com *ic,
695 const struct ieee80211req *ireq)
696{
697 struct ieee80211_devcaps_req *dc;
698 struct ieee80211req_chaninfo *ci;
29
30/*
31 * IEEE 802.11 ioctl support (FreeBSD-specific)
32 */
33
34#include "opt_inet.h"
35#include "opt_ipx.h"
36#include "opt_wlan.h"

--- 654 unchanged lines hidden (view full) ---

691}
692
693static __noinline int
694ieee80211_ioctl_getdevcaps(struct ieee80211com *ic,
695 const struct ieee80211req *ireq)
696{
697 struct ieee80211_devcaps_req *dc;
698 struct ieee80211req_chaninfo *ci;
699 int error;
699 int maxchans, error;
700
700
701 if (ireq->i_len != sizeof(struct ieee80211_devcaps_req))
701 maxchans = 1 + ((ireq->i_len - sizeof(struct ieee80211_devcaps_req)) /
702 sizeof(struct ieee80211_channel));
703 /* NB: require 1 so we know ic_nchans is accessible */
704 if (maxchans < 1)
702 return EINVAL;
705 return EINVAL;
703 dc = (struct ieee80211_devcaps_req *) malloc(
704 sizeof(struct ieee80211_devcaps_req), M_TEMP, M_NOWAIT | M_ZERO);
706 /* constrain max request size, 2K channels is ~24Kbytes */
707 if (maxchans > 2048)
708 maxchans = 2048;
709 dc = (struct ieee80211_devcaps_req *)
710 malloc(IEEE80211_DEVCAPS_SIZE(maxchans), M_TEMP, M_NOWAIT | M_ZERO);
705 if (dc == NULL)
706 return ENOMEM;
707 dc->dc_drivercaps = ic->ic_caps;
708 dc->dc_cryptocaps = ic->ic_cryptocaps;
709 dc->dc_htcaps = ic->ic_htcaps;
710 ci = &dc->dc_chaninfo;
711 if (dc == NULL)
712 return ENOMEM;
713 dc->dc_drivercaps = ic->ic_caps;
714 dc->dc_cryptocaps = ic->ic_cryptocaps;
715 dc->dc_htcaps = ic->ic_htcaps;
716 ci = &dc->dc_chaninfo;
711 ic->ic_getradiocaps(ic, IEEE80211_CHAN_MAX, &ci->ic_nchans, ci->ic_chans);
717 ic->ic_getradiocaps(ic, maxchans, &ci->ic_nchans, ci->ic_chans);
712 ieee80211_sort_channels(ci->ic_chans, ci->ic_nchans);
718 ieee80211_sort_channels(ci->ic_chans, ci->ic_nchans);
713 error = copyout(dc, ireq->i_data, sizeof(*dc));
719 error = copyout(dc, ireq->i_data, IEEE80211_DEVCAPS_SPACE(dc));
714 free(dc, M_TEMP);
715 return error;
716}
717
718static __noinline int
719ieee80211_ioctl_getstavlan(struct ieee80211vap *vap, struct ieee80211req *ireq)
720{
721 struct ieee80211_node *ni;

--- 839 unchanged lines hidden (view full) ---

1561 }
1562 return 0;
1563}
1564
1565static __noinline int
1566ieee80211_ioctl_setchanlist(struct ieee80211vap *vap, struct ieee80211req *ireq)
1567{
1568 struct ieee80211com *ic = vap->iv_ic;
720 free(dc, M_TEMP);
721 return error;
722}
723
724static __noinline int
725ieee80211_ioctl_getstavlan(struct ieee80211vap *vap, struct ieee80211req *ireq)
726{
727 struct ieee80211_node *ni;

--- 839 unchanged lines hidden (view full) ---

1567 }
1568 return 0;
1569}
1570
1571static __noinline int
1572ieee80211_ioctl_setchanlist(struct ieee80211vap *vap, struct ieee80211req *ireq)
1573{
1574 struct ieee80211com *ic = vap->iv_ic;
1569 struct ieee80211req_chanlist list;
1570 u_char chanlist[IEEE80211_CHAN_BYTES];
1571 int i, nchan, error;
1575 uint8_t *chanlist, *list;
1576 int i, nchan, maxchan, error;
1572
1577
1573 if (ireq->i_len != sizeof(list))
1574 return EINVAL;
1575 error = copyin(ireq->i_data, &list, sizeof(list));
1578 if (ireq->i_len > sizeof(ic->ic_chan_active))
1579 ireq->i_len = sizeof(ic->ic_chan_active);
1580 list = malloc(ireq->i_len + IEEE80211_CHAN_BYTES, M_TEMP,
1581 M_NOWAIT | M_ZERO);
1582 if (list == NULL)
1583 return ENOMEM;
1584 error = copyin(ireq->i_data, list, ireq->i_len);
1576 if (error)
1577 return error;
1585 if (error)
1586 return error;
1578 memset(chanlist, 0, sizeof(chanlist));
1579 nchan = 0;
1587 nchan = 0;
1588 chanlist = list + ireq->i_len; /* NB: zero'd already */
1589 maxchan = ireq->i_len * NBBY;
1580 for (i = 0; i < ic->ic_nchans; i++) {
1581 const struct ieee80211_channel *c = &ic->ic_channels[i];
1582 /*
1583 * Calculate the intersection of the user list and the
1584 * available channels so users can do things like specify
1585 * 1-255 to get all available channels.
1586 */
1590 for (i = 0; i < ic->ic_nchans; i++) {
1591 const struct ieee80211_channel *c = &ic->ic_channels[i];
1592 /*
1593 * Calculate the intersection of the user list and the
1594 * available channels so users can do things like specify
1595 * 1-255 to get all available channels.
1596 */
1587 if (isset(list.ic_channels, c->ic_ieee)) {
1597 if (c->ic_ieee < maxchan && isset(list, c->ic_ieee)) {
1588 setbit(chanlist, c->ic_ieee);
1589 nchan++;
1590 }
1591 }
1592 if (nchan == 0)
1593 return EINVAL;
1594 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && /* XXX */
1595 isclr(chanlist, ic->ic_bsschan->ic_ieee))
1596 ic->ic_bsschan = IEEE80211_CHAN_ANYC;
1598 setbit(chanlist, c->ic_ieee);
1599 nchan++;
1600 }
1601 }
1602 if (nchan == 0)
1603 return EINVAL;
1604 if (ic->ic_bsschan != IEEE80211_CHAN_ANYC && /* XXX */
1605 isclr(chanlist, ic->ic_bsschan->ic_ieee))
1606 ic->ic_bsschan = IEEE80211_CHAN_ANYC;
1597 memcpy(ic->ic_chan_active, chanlist, sizeof(ic->ic_chan_active));
1607 memcpy(ic->ic_chan_active, chanlist, IEEE80211_CHAN_BYTES);
1598 ieee80211_scan_flush(vap);
1608 ieee80211_scan_flush(vap);
1609 free(list, M_TEMP);
1599 return ENETRESET;
1600}
1601
1602static __noinline int
1603ieee80211_ioctl_setstastats(struct ieee80211vap *vap, struct ieee80211req *ireq)
1604{
1605 struct ieee80211_node *ni;
1606 uint8_t macaddr[IEEE80211_ADDR_LEN];

--- 381 unchanged lines hidden (view full) ---

1988 return setcurchan(vap, c);
1989}
1990
1991static __noinline int
1992ieee80211_ioctl_setregdomain(struct ieee80211vap *vap,
1993 const struct ieee80211req *ireq)
1994{
1995 struct ieee80211_regdomain_req *reg;
1610 return ENETRESET;
1611}
1612
1613static __noinline int
1614ieee80211_ioctl_setstastats(struct ieee80211vap *vap, struct ieee80211req *ireq)
1615{
1616 struct ieee80211_node *ni;
1617 uint8_t macaddr[IEEE80211_ADDR_LEN];

--- 381 unchanged lines hidden (view full) ---

1999 return setcurchan(vap, c);
2000}
2001
2002static __noinline int
2003ieee80211_ioctl_setregdomain(struct ieee80211vap *vap,
2004 const struct ieee80211req *ireq)
2005{
2006 struct ieee80211_regdomain_req *reg;
1996 int error;
2007 int nchans, error;
1997
2008
1998 if (ireq->i_len != sizeof(struct ieee80211_regdomain_req))
2009 nchans = 1 + ((ireq->i_len - sizeof(struct ieee80211_regdomain_req)) /
2010 sizeof(struct ieee80211_channel));
2011 if (!(1 <= nchans && nchans <= IEEE80211_CHAN_MAX)) {
2012 IEEE80211_DPRINTF(vap, IEEE80211_MSG_IOCTL,
2013 "%s: bad # chans, i_len %d nchans %d\n", __func__,
2014 ireq->i_len, nchans);
1999 return EINVAL;
2015 return EINVAL;
2000 reg = (struct ieee80211_regdomain_req *) malloc(
2001 sizeof(struct ieee80211_regdomain_req), M_TEMP, M_NOWAIT);
2002 if (reg == NULL)
2016 }
2017 reg = (struct ieee80211_regdomain_req *)
2018 malloc(IEEE80211_REGDOMAIN_SIZE(nchans), M_TEMP, M_NOWAIT);
2019 if (reg == NULL) {
2020 IEEE80211_DPRINTF(vap, IEEE80211_MSG_IOCTL,
2021 "%s: no memory, nchans %d\n", __func__, nchans);
2003 return ENOMEM;
2022 return ENOMEM;
2004 error = copyin(ireq->i_data, reg, sizeof(*reg));
2005 if (error == 0)
2006 error = ieee80211_setregdomain(vap, reg);
2023 }
2024 error = copyin(ireq->i_data, reg, IEEE80211_REGDOMAIN_SIZE(nchans));
2025 if (error == 0) {
2026 /* NB: validate inline channel count against storage size */
2027 if (reg->chaninfo.ic_nchans != nchans) {
2028 IEEE80211_DPRINTF(vap, IEEE80211_MSG_IOCTL,
2029 "%s: chan cnt mismatch, %d != %d\n", __func__,
2030 reg->chaninfo.ic_nchans, nchans);
2031 error = EINVAL;
2032 } else
2033 error = ieee80211_setregdomain(vap, reg);
2034 }
2007 free(reg, M_TEMP);
2008
2009 return (error == 0 ? ENETRESET : error);
2010}
2011
2012static int
2013ieee80211_ioctl_setroam(struct ieee80211vap *vap,
2014 const struct ieee80211req *ireq)

--- 1315 unchanged lines hidden ---
2035 free(reg, M_TEMP);
2036
2037 return (error == 0 ? ENETRESET : error);
2038}
2039
2040static int
2041ieee80211_ioctl_setroam(struct ieee80211vap *vap,
2042 const struct ieee80211req *ireq)

--- 1315 unchanged lines hidden ---