]>
Commit | Line | Data |
---|---|---|
14a0380d LR |
1 | #include <linux/nl80211.h> |
2 | #include <net/if.h> | |
3 | #include <errno.h> | |
4 | #include <string.h> | |
5 | ||
6 | #include <netlink/genl/genl.h> | |
7 | #include <netlink/genl/family.h> | |
8 | #include <netlink/genl/ctrl.h> | |
9 | #include <netlink/msg.h> | |
10 | #include <netlink/attr.h> | |
11 | ||
12 | #include "iw.h" | |
13 | ||
14 | static int wait_handler(struct nl_msg *msg, void *arg) | |
15 | { | |
16 | int *finished = arg; | |
17 | ||
18 | *finished = 1; | |
19 | return NL_STOP; | |
20 | } | |
21 | ||
22 | static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err, | |
23 | void *arg) | |
24 | { | |
25 | fprintf(stderr, "nl80211 error %d\n", err->error); | |
26 | exit(err->error); | |
27 | } | |
28 | ||
29 | static int reg_handler(struct nl_msg *msg, void *arg) | |
30 | { | |
31 | return NL_SKIP; | |
32 | } | |
33 | ||
34 | int isalpha_upper(char letter) | |
35 | { | |
36 | if (letter >= 65 && letter <= 90) | |
37 | return 1; | |
38 | return 0; | |
39 | } | |
40 | ||
41 | static int is_alpha2(char *alpha2) | |
42 | { | |
43 | if (isalpha_upper(alpha2[0]) && isalpha_upper(alpha2[1])) | |
44 | return 1; | |
45 | return 0; | |
46 | } | |
47 | ||
48 | static int is_world_regdom(char *alpha2) | |
49 | { | |
50 | /* ASCII 0 */ | |
51 | if (alpha2[0] == 48 && alpha2[1] == 48) | |
52 | return 1; | |
53 | return 0; | |
54 | } | |
55 | ||
56 | static int handle_reg_set(struct nl80211_state *state, | |
1c05c109 JB |
57 | struct nl_msg *msg, |
58 | int argc, char **argv) | |
14a0380d | 59 | { |
14a0380d | 60 | struct nl_cb *cb = NULL; |
1c05c109 | 61 | int ret = 1; |
14a0380d LR |
62 | int err; |
63 | int finished = 0; | |
64 | char alpha2[3]; | |
65 | ||
1c05c109 | 66 | if (argc < 1) |
14a0380d | 67 | return -1; |
14a0380d LR |
68 | |
69 | if (!is_alpha2(argv[0]) && !is_world_regdom(argv[0])) { | |
70 | fprintf(stderr, "not a valid ISO/IEC 3166-1 alpha2\n"); | |
71 | fprintf(stderr, "Special non-alph2 usable entries:\n"); | |
72 | fprintf(stderr, "\t00\tWorld Regulatory domain\n"); | |
1c05c109 | 73 | return 1; |
14a0380d LR |
74 | } |
75 | ||
76 | alpha2[0] = argv[0][0]; | |
77 | alpha2[1] = argv[0][1]; | |
78 | alpha2[2] = '\0'; | |
79 | ||
80 | argc--; | |
81 | argv++; | |
82 | ||
1c05c109 | 83 | if (argc) |
14a0380d | 84 | return -1; |
14a0380d LR |
85 | |
86 | NLA_PUT_STRING(msg, NL80211_ATTR_REG_ALPHA2, alpha2); | |
87 | ||
88 | cb = nl_cb_alloc(NL_CB_CUSTOM); | |
89 | if (!cb) | |
90 | goto out; | |
91 | ||
92 | err = nl_send_auto_complete(state->nl_handle, msg); | |
93 | ||
94 | if (err < 0) { | |
95 | fprintf(stderr, "failed to send reg set command\n"); | |
96 | goto out; | |
97 | } | |
98 | ||
99 | nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, reg_handler, NULL); | |
100 | nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, wait_handler, &finished); | |
101 | nl_cb_err(cb, NL_CB_CUSTOM, error_handler, NULL); | |
102 | ||
103 | err = nl_recvmsgs(state->nl_handle, cb); | |
104 | ||
1c05c109 | 105 | if (!finished) |
14a0380d | 106 | err = nl_wait_for_ack(state->nl_handle); |
14a0380d LR |
107 | |
108 | if (err < 0) | |
109 | goto out; | |
110 | ||
111 | ret = 0; | |
112 | ||
113 | out: | |
114 | nl_cb_put(cb); | |
115 | nla_put_failure: | |
14a0380d LR |
116 | return ret; |
117 | } | |
1c05c109 JB |
118 | COMMAND(reg, set, "<ISO/IEC 3166-1 alpha2>", |
119 | NL80211_CMD_REQ_SET_REG, 0, CIB_NONE, handle_reg_set); |