nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | #include <errno.h> |
2 | |||
3 | #include <netlink/genl/genl.h> |
||
4 | #include <netlink/genl/family.h> |
||
5 | #include <netlink/genl/ctrl.h> |
||
6 | #include <netlink/msg.h> |
||
7 | #include <netlink/attr.h> |
||
8 | |||
9 | #include "nl80211.h" |
||
10 | #include "iw.h" |
||
11 | |||
12 | static int iw_conn(struct nl80211_state *state, struct nl_cb *cb, |
||
13 | struct nl_msg *msg, int argc, char **argv, |
||
14 | enum id_input id) |
||
15 | { |
||
16 | char *end; |
||
17 | unsigned char bssid[6]; |
||
18 | int freq; |
||
19 | |||
20 | if (argc < 1) |
||
21 | return 1; |
||
22 | |||
23 | /* SSID */ |
||
24 | NLA_PUT(msg, NL80211_ATTR_SSID, strlen(argv[0]), argv[0]); |
||
25 | argv++; |
||
26 | argc--; |
||
27 | |||
28 | /* freq */ |
||
29 | if (argc) { |
||
30 | freq = strtoul(argv[0], &end, 10); |
||
31 | if (*end == '\0') { |
||
32 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq); |
||
33 | argv++; |
||
34 | argc--; |
||
35 | } |
||
36 | } |
||
37 | |||
38 | /* bssid */ |
||
39 | if (argc) { |
||
40 | if (mac_addr_a2n(bssid, argv[0]) == 0) { |
||
41 | NLA_PUT(msg, NL80211_ATTR_MAC, 6, bssid); |
||
42 | argv++; |
||
43 | argc--; |
||
44 | } |
||
45 | } |
||
46 | |||
47 | if (!argc) |
||
48 | return 0; |
||
49 | |||
50 | if (strcmp(*argv, "key") != 0 && strcmp(*argv, "keys") != 0) |
||
51 | return 1; |
||
52 | |||
53 | argv++; |
||
54 | argc--; |
||
55 | |||
56 | return parse_keys(msg, argv, argc); |
||
57 | nla_put_failure: |
||
58 | return -ENOSPC; |
||
59 | } |
||
60 | |||
61 | static int disconnect(struct nl80211_state *state, |
||
62 | struct nl_cb *cb, |
||
63 | struct nl_msg *msg, |
||
64 | int argc, char **argv, |
||
65 | enum id_input id) |
||
66 | { |
||
67 | return 0; |
||
68 | } |
||
69 | TOPLEVEL(disconnect, NULL, |
||
70 | NL80211_CMD_DISCONNECT, 0, CIB_NETDEV, disconnect, |
||
71 | "Disconnect from the current network."); |
||
72 | |||
73 | static int iw_connect(struct nl80211_state *state, struct nl_cb *cb, |
||
74 | struct nl_msg *msg, int argc, char **argv, |
||
75 | enum id_input id) |
||
76 | { |
||
77 | char **conn_argv, *dev = argv[0]; |
||
78 | static const __u32 cmds[] = { |
||
79 | NL80211_CMD_CONNECT, |
||
80 | }; |
||
81 | struct print_event_args printargs = { }; |
||
82 | int conn_argc, err; |
||
83 | bool wait = false; |
||
84 | int i; |
||
85 | |||
86 | /* strip "wlan0 connect" */ |
||
87 | argc -= 2; |
||
88 | argv += 2; |
||
89 | |||
90 | /* check -w */ |
||
91 | if (argc && strcmp(argv[0], "-w") == 0) { |
||
92 | wait = true; |
||
93 | argc--; |
||
94 | argv++; |
||
95 | } |
||
96 | |||
97 | err = __prepare_listen_events(state); |
||
98 | if (err) |
||
99 | return err; |
||
100 | |||
101 | conn_argc = 3 + argc; |
||
102 | conn_argv = calloc(conn_argc, sizeof(*conn_argv)); |
||
103 | if (!conn_argv) |
||
104 | return -ENOMEM; |
||
105 | |||
106 | conn_argv[0] = dev; |
||
107 | conn_argv[1] = "connect"; |
||
108 | conn_argv[2] = "establish"; |
||
109 | for (i = 0; i < argc; i++) |
||
110 | conn_argv[i + 3] = argv[i]; |
||
111 | err = handle_cmd(state, id, conn_argc, conn_argv); |
||
112 | free(conn_argv); |
||
113 | if (err) |
||
114 | return err; |
||
115 | |||
116 | if (!wait) |
||
117 | return 0; |
||
118 | |||
119 | /* |
||
120 | * WARNING: DO NOT COPY THIS CODE INTO YOUR APPLICATION |
||
121 | * |
||
122 | * This code has a bug: |
||
123 | * |
||
124 | * It is possible for a connect result message from another |
||
125 | * connect attempt to be processed here first, because we |
||
126 | * start listening to the multicast group before starting |
||
127 | * our own connect request, which may succeed but we get a |
||
128 | * fail message from a previous attempt that raced with us, |
||
129 | * or similar. |
||
130 | * |
||
131 | * The only proper way to fix this would be to listen to events |
||
132 | * before sending the command, and for the kernel to send the |
||
133 | * connect request or a cookie along with the event, so that you |
||
134 | * can match up whether the connect _you_ requested was finished |
||
135 | * or aborted. |
||
136 | * |
||
137 | * Alas, the kernel doesn't do that (yet). |
||
138 | */ |
||
139 | |||
140 | __do_listen_events(state, ARRAY_SIZE(cmds), cmds, &printargs); |
||
141 | return 0; |
||
142 | } |
||
143 | TOPLEVEL(connect, "[-w] <SSID> [<freq in MHz>] [<bssid>] [key 0:abcde d:1:6162636465]", |
||
144 | 0, 0, CIB_NETDEV, iw_connect, |
||
145 | "Join the network with the given SSID (and frequency, BSSID).\n" |
||
146 | "With -w, wait for the connect to finish or fail."); |
||
147 | HIDDEN(connect, establish, "", NL80211_CMD_CONNECT, 0, CIB_NETDEV, iw_conn); |
||
148 | |||
149 | static int iw_auth(struct nl80211_state *state, struct nl_cb *cb, |
||
150 | struct nl_msg *msg, int argc, char **argv, |
||
151 | enum id_input id) |
||
152 | { |
||
153 | char *end; |
||
154 | unsigned char bssid[6]; |
||
155 | int freq; |
||
156 | bool need_key = false; |
||
157 | |||
158 | if (argc < 4) |
||
159 | return 1; |
||
160 | |||
161 | /* SSID */ |
||
162 | NLA_PUT(msg, NL80211_ATTR_SSID, strlen(argv[0]), argv[0]); |
||
163 | argv++; |
||
164 | argc--; |
||
165 | |||
166 | /* bssid */ |
||
167 | if (mac_addr_a2n(bssid, argv[0]) == 0) { |
||
168 | NLA_PUT(msg, NL80211_ATTR_MAC, 6, bssid); |
||
169 | argv++; |
||
170 | argc--; |
||
171 | } else { |
||
172 | return 1; |
||
173 | } |
||
174 | |||
175 | /* FIXME */ |
||
176 | if (strcmp(argv[0], "open") == 0) { |
||
177 | NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE, |
||
178 | NL80211_AUTHTYPE_OPEN_SYSTEM); |
||
179 | } else if (strcmp(argv[0], "shared") == 0) { |
||
180 | NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE, |
||
181 | NL80211_AUTHTYPE_SHARED_KEY); |
||
182 | need_key = true; |
||
183 | } else { |
||
184 | return 1; |
||
185 | } |
||
186 | argv++; |
||
187 | argc--; |
||
188 | |||
189 | freq = strtoul(argv[0], &end, 10); |
||
190 | if (*end == '\0') { |
||
191 | NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq); |
||
192 | argv++; |
||
193 | argc--; |
||
194 | } else { |
||
195 | return 1; |
||
196 | } |
||
197 | |||
198 | if (!argc && need_key) |
||
199 | return 1; |
||
200 | if (argc && !need_key) |
||
201 | return 1; |
||
202 | if (!argc) |
||
203 | return 0; |
||
204 | |||
205 | if (strcmp(*argv, "key") != 0 && strcmp(*argv, "keys") != 0) |
||
206 | return 1; |
||
207 | |||
208 | argv++; |
||
209 | argc--; |
||
210 | |||
211 | return parse_keys(msg, argv, argc); |
||
212 | nla_put_failure: |
||
213 | return -ENOSPC; |
||
214 | } |
||
215 | |||
216 | TOPLEVEL(auth, "<SSID> <bssid> <type:open|shared> <freq in MHz> [key 0:abcde d:1:6162636465]", |
||
217 | NL80211_CMD_AUTHENTICATE, 0, CIB_NETDEV, iw_auth, |
||
218 | "Authenticate with the given network.\n"); |