X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=connect.c;h=56771249e234bc14bd5234a68b5565f08688eb14;hb=9ae0d10319434efe95ac6939f4f2c1c3edf1c48b;hp=1fb2892c387f618923151e86badb17891a42d0ad;hpb=7b5506229b299a3b7bc4a152688196dbc17ab234;p=thirdparty%2Fiw.git diff --git a/connect.c b/connect.c index 1fb2892..5677124 100644 --- a/connect.c +++ b/connect.c @@ -9,13 +9,12 @@ #include "nl80211.h" #include "iw.h" -static int iw_connect(struct nl80211_state *state, - struct nl_cb *cb, - struct nl_msg *msg, - int argc, char **argv) +static int iw_conn(struct nl80211_state *state, + struct nl_msg *msg, int argc, char **argv, + enum id_input id) { char *end; - unsigned char abssid[6]; + unsigned char bssid[6]; int freq; if (argc < 1) @@ -38,31 +37,181 @@ static int iw_connect(struct nl80211_state *state, /* bssid */ if (argc) { - if (mac_addr_a2n(abssid, argv[0])) - return 1; - NLA_PUT(msg, NL80211_ATTR_MAC, 6, abssid); - argv++; - argc--; + if (mac_addr_a2n(bssid, argv[0]) == 0) { + NLA_PUT(msg, NL80211_ATTR_MAC, 6, bssid); + argv++; + argc--; + } } - if (argc) + if (!argc) + return 0; + + if (strcmp(*argv, "key") != 0 && strcmp(*argv, "keys") != 0) return 1; - return 0; + argv++; + argc--; + + return parse_keys(msg, argv, argc); nla_put_failure: return -ENOSPC; } static int disconnect(struct nl80211_state *state, - struct nl_cb *cb, struct nl_msg *msg, - int argc, char **argv) + int argc, char **argv, + enum id_input id) { return 0; } TOPLEVEL(disconnect, NULL, NL80211_CMD_DISCONNECT, 0, CIB_NETDEV, disconnect, "Disconnect from the current network."); -TOPLEVEL(connect, " [] []", - NL80211_CMD_CONNECT, 0, CIB_NETDEV, iw_connect, - "Join the network with the given SSID (and frequency, BSSID)."); + +static int iw_connect(struct nl80211_state *state, + struct nl_msg *msg, int argc, char **argv, + enum id_input id) +{ + char **conn_argv, *dev = argv[0]; + static const __u32 cmds[] = { + NL80211_CMD_CONNECT, + }; + struct print_event_args printargs = { }; + int conn_argc, err; + bool wait = false; + int i; + + /* strip "wlan0 connect" */ + argc -= 2; + argv += 2; + + /* check -w */ + if (argc && strcmp(argv[0], "-w") == 0) { + wait = true; + argc--; + argv++; + } + + err = __prepare_listen_events(state); + if (err) + return err; + + conn_argc = 3 + argc; + conn_argv = calloc(conn_argc, sizeof(*conn_argv)); + if (!conn_argv) + return -ENOMEM; + + conn_argv[0] = dev; + conn_argv[1] = "connect"; + conn_argv[2] = "establish"; + for (i = 0; i < argc; i++) + conn_argv[i + 3] = argv[i]; + err = handle_cmd(state, id, conn_argc, conn_argv); + free(conn_argv); + if (err) + return err; + + if (!wait) + return 0; + + /* + * WARNING: DO NOT COPY THIS CODE INTO YOUR APPLICATION + * + * This code has a bug: + * + * It is possible for a connect result message from another + * connect attempt to be processed here first, because we + * start listening to the multicast group before starting + * our own connect request, which may succeed but we get a + * fail message from a previous attempt that raced with us, + * or similar. + * + * The only proper way to fix this would be to listen to events + * before sending the command, and for the kernel to send the + * connect request or a cookie along with the event, so that you + * can match up whether the connect _you_ requested was finished + * or aborted. + * + * Alas, the kernel doesn't do that (yet). + */ + + __do_listen_events(state, ARRAY_SIZE(cmds), cmds, &printargs); + return 0; +} +TOPLEVEL(connect, "[-w] [] [] [key 0:abcde d:1:6162636465]", + 0, 0, CIB_NETDEV, iw_connect, + "Join the network with the given SSID (and frequency, BSSID).\n" + "With -w, wait for the connect to finish or fail."); +HIDDEN(connect, establish, "", NL80211_CMD_CONNECT, 0, CIB_NETDEV, iw_conn); + +static int iw_auth(struct nl80211_state *state, + struct nl_msg *msg, int argc, char **argv, + enum id_input id) +{ + char *end; + unsigned char bssid[6]; + int freq; + bool need_key = false; + + if (argc < 4) + return 1; + + /* SSID */ + NLA_PUT(msg, NL80211_ATTR_SSID, strlen(argv[0]), argv[0]); + argv++; + argc--; + + /* bssid */ + if (mac_addr_a2n(bssid, argv[0]) == 0) { + NLA_PUT(msg, NL80211_ATTR_MAC, 6, bssid); + argv++; + argc--; + } else { + return 1; + } + + /* FIXME */ + if (strcmp(argv[0], "open") == 0) { + NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE, + NL80211_AUTHTYPE_OPEN_SYSTEM); + } else if (strcmp(argv[0], "shared") == 0) { + NLA_PUT_U32(msg, NL80211_ATTR_AUTH_TYPE, + NL80211_AUTHTYPE_SHARED_KEY); + need_key = true; + } else { + return 1; + } + argv++; + argc--; + + freq = strtoul(argv[0], &end, 10); + if (*end == '\0') { + NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FREQ, freq); + argv++; + argc--; + } else { + return 1; + } + + if (!argc && need_key) + return 1; + if (argc && !need_key) + return 1; + if (!argc) + return 0; + + if (strcmp(*argv, "key") != 0 && strcmp(*argv, "keys") != 0) + return 1; + + argv++; + argc--; + + return parse_keys(msg, argv, argc); + nla_put_failure: + return -ENOSPC; +} + +TOPLEVEL(auth, " [key 0:abcde d:1:6162636465]", + NL80211_CMD_AUTHENTICATE, 0, CIB_NETDEV, iw_auth, + "Authenticate with the given network.\n");