Running the following program via: ./main 0 5220
gives me an error that my input data is out of range.
sudo ./main 0 5220
-------------------------- BEGIN NETLINK MESSAGE ---------------------------
[NETLINK HEADER] 16 octets
.nlmsg_len = 52
.type = 34 <0x22>
.flags = 5 <REQUEST,ACK>
.seq = 1667899004
.port = 683673755
[GENERIC NETLINK HEADER] 4 octets
.cmd = 102
.version = 0
.unused = 0
[PAYLOAD] 32 octets
08 00 01 00 00 00 00 00 08 00 b7 00 02 00 00 00 ................
08 00 26 00 6c 09 00 00 08 00 9f 00 01 00 00 00 ..&.l...........
--------------------------- END NETLINK MESSAGE ---------------------------
nl_recvmsgs_default() error (Invalid input data or parameter)
error
channel switch works fine with:
sudo hostapd_cli chan_switch 8 5220
iw dev
output of the AP:
phy#0
Interface wlan0
ifindex 3
wdev 0x1
addr 02:00:00:00:00:00
ssid apname
type AP
channel 1 (2412 MHz), width: 20 MHz, center1: 2412 MHz
txpower 20.00 dBm
the AP is running via hwsim, shouldn't matter because chan switch works with hostapd_cli
here is the code, I also tried with and without nla_nest_start() & nla_nest_end()
argv[1]
is the phy#, tried with ifindex 3
but same error
argv[2]
is the frequency to set
#include <linux/nl80211.h>
#include <netlink/genl/ctrl.h>
#include <netlink/genl/genl.h>
typedef struct nl_element {
int id;
struct nl_sock *socket;
struct nl_msg * message;
struct nl_cb * callback;
} nl_el;
int main(int argc, char *argv[])
{
int error = 0;
int retval = 1;
// struct nlattr *chan; // used in nla_nest_start() and nla_nest_end()
nl_el nl = { 0 };
if (argc < 3) {
printf("main <phy#> <freq>");
return -99;
}
nl.message = nlmsg_alloc();
if (nl.message == NULL)
return -1;
nl.socket = nl_socket_alloc();
if (nl.socket == NULL)
return -2;
if (genl_connect(nl.socket))
return -3;
if (nl_socket_set_buffer_size(nl.socket, 8192, 8192))
return -4;
if (setsockopt(nl_socket_get_fd(nl.socket), SOL_NETLINK, NETLINK_EXT_ACK, &retval, sizeof(retval)))
return -5;
nl.id = genl_ctrl_resolve(nl.socket, "nl80211");
if (nl.id < 0)
return -6;
// using NL80211_CMD_SET_WIPHY instead of NL80211_CMD_CHANNEL_SWITCH gives error message:
// nl_recvmsgs_default() error (Object busy)
if (genlmsg_put(nl.message, 0, 0, nl.id, 0, NLM_F_REQUEST, NL80211_CMD_CHANNEL_SWITCH, 0) == NULL)
return -7;
NLA_PUT_S32(nl.message, NL80211_ATTR_WIPHY, atoi(argv[1]));
// chan = nla_nest_start(nl.message, NL80211_PMSR_PEER_ATTR_CHAN);
// NLA_PUT_FLAG(nl.message, NL80211_ATTR_CH_SWITCH_BLOCK_TX); // either this or NL80211_ATTR_CH_SWITCH_COUNT
NLA_PUT_U32(nl.message, NL80211_ATTR_CH_SWITCH_COUNT, 2);
NLA_PUT_S32(nl.message, NL80211_ATTR_WIPHY_FREQ, atoi(argv[2]));
NLA_PUT_U32(nl.message, NL80211_ATTR_CHANNEL_WIDTH, NL80211_CHAN_HT20);
// NLA_PUT_S32(nl.message, NL80211_ATTR_CENTER_FREQ1, 5180);
// NLA_PUT_S32(nl.message, NL80211_ATTR_WIPHY_FREQ_OFFSET, 0);
// NLA_PUT_U32(nl.message, NL80211_ATTR_WIPHY_CHANNEL_TYPE, NL80211_CHAN_NO_HT); // deprecated
// nla_nest_end(nl.message, chan);
if (nl_send_auto(nl.socket, nl.message) < 0)
return -8;
nl_msg_dump(nl.message, stdout);
printf("\n error: %s \n", nl_geterror(nl_recvmsgs_default(nl.socket)));
return 0;
nla_put_failure:
return -10;
}
to build:
gcc main.c $(pkg-config --cflags --libs libnl-3.0 libnl-genl-3.0)
Is the problem maybe the fact that via nl80211 one has to put the interface DOWN
before switching channel?
gathered the information here