blob: 059f13a617415dcf1d03003fe0817b472eb81632 [file] [log] [blame]
#include <linux/nl80211.h>
#include <net/if.h>
#include <errno.h>
#include <string.h>
#include <netlink/genl/genl.h>
#include <netlink/genl/family.h>
#include <netlink/genl/ctrl.h>
#include <netlink/msg.h>
#include <netlink/attr.h>
#include "iw.h"
static int wait_handler(struct nl_msg *msg, void *arg)
{
int *finished = arg;
*finished = 1;
return NL_STOP;
}
static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
void *arg)
{
fprintf(stderr, "nl80211 error %d\n", err->error);
exit(err->error);
}
static int reg_handler(struct nl_msg *msg, void *arg)
{
return NL_SKIP;
}
int isalpha_upper(char letter)
{
if (letter >= 65 && letter <= 90)
return 1;
return 0;
}
static int is_alpha2(char *alpha2)
{
if (isalpha_upper(alpha2[0]) && isalpha_upper(alpha2[1]))
return 1;
return 0;
}
static int is_world_regdom(char *alpha2)
{
/* ASCII 0 */
if (alpha2[0] == 48 && alpha2[1] == 48)
return 1;
return 0;
}
static int handle_reg_set(struct nl80211_state *state,
struct nl_msg *msg,
int argc, char **argv)
{
struct nl_cb *cb = NULL;
int ret = 1;
int err;
int finished = 0;
char alpha2[3];
if (argc < 1)
return -1;
if (!is_alpha2(argv[0]) && !is_world_regdom(argv[0])) {
fprintf(stderr, "not a valid ISO/IEC 3166-1 alpha2\n");
fprintf(stderr, "Special non-alph2 usable entries:\n");
fprintf(stderr, "\t00\tWorld Regulatory domain\n");
return 1;
}
alpha2[0] = argv[0][0];
alpha2[1] = argv[0][1];
alpha2[2] = '\0';
argc--;
argv++;
if (argc)
return -1;
NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, alpha2);
cb = nl_cb_alloc(NL_CB_CUSTOM);
if (!cb)
goto out;
err = nl_send_auto_complete(state->nl_handle, msg);
if (err < 0) {
fprintf(stderr, "failed to send reg set command\n");
goto out;
}
nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, reg_handler, NULL);
nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, wait_handler, &finished);
nl_cb_err(cb, NL_CB_CUSTOM, error_handler, NULL);
err = nl_recvmsgs(state->nl_handle, cb);
if (!finished)
err = nl_wait_for_ack(state->nl_handle);
if (err < 0)
goto out;
ret = 0;
out:
nl_cb_put(cb);
nla_put_failure:
return ret;
}
COMMAND(reg, set, "<ISO/IEC 3166-1 alpha2>",
NL80211_CMD_REQ_SET_REG, 0, CIB_NONE, handle_reg_set);