]> git.ipfire.org Git - thirdparty/iw.git/blobdiff - phy.c
add P2P Device handling primitives
[thirdparty/iw.git] / phy.c
diff --git a/phy.c b/phy.c
index 1c0938a60dc23384d79dc9dce1efff8b1dc09a24..860f29936392830b299694aa755e2d06335793f3 100644 (file)
--- a/phy.c
+++ b/phy.c
@@ -1,6 +1,7 @@
 #include <stdbool.h>
 #include <errno.h>
 #include <net/if.h>
+#include <strings.h>
 
 #include <netlink/genl/genl.h>
 #include <netlink/genl/family.h>
@@ -14,7 +15,8 @@
 static int handle_name(struct nl80211_state *state,
                       struct nl_cb *cb,
                       struct nl_msg *msg,
-                      int argc, char **argv)
+                      int argc, char **argv,
+                      enum id_input id)
 {
        if (argc != 1)
                return 1;
@@ -31,6 +33,7 @@ COMMAND(set, name, "<new name>", NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_name,
 static int handle_freqchan(struct nl_msg *msg, bool chan,
                           int argc, char **argv)
 {
+       char *end;
        static const struct {
                const char *name;
                unsigned int val;
@@ -57,7 +60,12 @@ static int handle_freqchan(struct nl_msg *msg, bool chan,
                        return 1;
        }
 
-       freq = strtoul(argv[0], NULL, 10);
+       if (!*argv[0])
+               return 1;
+       freq = strtoul(argv[0], &end, 10);
+       if (*end)
+               return 1;
+
        if (chan)
                freq = ieee80211_channel_to_frequency(freq);
 
@@ -71,7 +79,8 @@ static int handle_freqchan(struct nl_msg *msg, bool chan,
 
 static int handle_freq(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 handle_freqchan(msg, false, argc, argv);
 }
@@ -84,7 +93,8 @@ COMMAND(set, freq, "<freq> [HT20|HT40+|HT40-]",
 
 static int handle_chan(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 handle_freqchan(msg, true, argc, argv);
 }
@@ -92,3 +102,260 @@ COMMAND(set, channel, "<channel> [HT20|HT40+|HT40-]",
        NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_chan, NULL);
 COMMAND(set, channel, "<channel> [HT20|HT40+|HT40-]",
        NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_chan, NULL);
+
+static int handle_fragmentation(struct nl80211_state *state,
+                               struct nl_cb *cb, struct nl_msg *msg,
+                               int argc, char **argv,
+                               enum id_input id)
+{
+       unsigned int frag;
+
+       if (argc != 1)
+               return 1;
+
+       if (strcmp("off", argv[0]) == 0)
+               frag = -1;
+       else {
+               char *end;
+
+               if (!*argv[0])
+                       return 1;
+               frag = strtoul(argv[0], &end, 10);
+               if (*end != '\0')
+                       return 1;
+       }
+
+       NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_FRAG_THRESHOLD, frag);
+
+       return 0;
+ nla_put_failure:
+       return -ENOBUFS;
+}
+COMMAND(set, frag, "<fragmentation threshold|off>",
+       NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_fragmentation,
+       "Set fragmentation threshold.");
+
+static int handle_rts(struct nl80211_state *state,
+                     struct nl_cb *cb, struct nl_msg *msg,
+                     int argc, char **argv,
+                     enum id_input id)
+{
+       unsigned int rts;
+
+       if (argc != 1)
+               return 1;
+
+       if (strcmp("off", argv[0]) == 0)
+               rts = -1;
+       else {
+               char *end;
+
+               if (!*argv[0])
+                       return 1;
+               rts = strtoul(argv[0], &end, 10);
+               if (*end != '\0')
+                       return 1;
+       }
+
+       NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_RTS_THRESHOLD, rts);
+
+       return 0;
+ nla_put_failure:
+       return -ENOBUFS;
+}
+COMMAND(set, rts, "<rts threshold|off>",
+       NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_rts,
+       "Set rts threshold.");
+
+static int handle_netns(struct nl80211_state *state,
+                       struct nl_cb *cb,
+                       struct nl_msg *msg,
+                       int argc, char **argv,
+                       enum id_input id)
+{
+       char *end;
+
+       if (argc != 1)
+               return 1;
+
+       if (!*argv[0])
+               return 1;
+
+       NLA_PUT_U32(msg, NL80211_ATTR_PID,
+                   strtoul(argv[0], &end, 10));
+
+       if (*end != '\0')
+               return 1;
+
+       return 0;
+ nla_put_failure:
+       return -ENOBUFS;
+}
+COMMAND(set, netns, "<pid>",
+       NL80211_CMD_SET_WIPHY_NETNS, 0, CIB_PHY, handle_netns,
+       "Put this wireless device into a different network namespace");
+
+static int handle_coverage(struct nl80211_state *state,
+                       struct nl_cb *cb,
+                       struct nl_msg *msg,
+                       int argc, char **argv,
+                       enum id_input id)
+{
+       char *end;
+       unsigned int coverage;
+
+       if (argc != 1)
+               return 1;
+
+       if (!*argv[0])
+               return 1;
+       coverage = strtoul(argv[0], &end, 10);
+       if (coverage > 255)
+               return 1;
+
+       if (*end)
+               return 1;
+
+       NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS, coverage);
+
+       return 0;
+ nla_put_failure:
+       return -ENOBUFS;
+}
+COMMAND(set, coverage, "<coverage class>",
+       NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_coverage,
+       "Set coverage class (1 for every 3 usec of air propagation time).\n"
+       "Valid values: 0 - 255.");
+
+static int handle_distance(struct nl80211_state *state,
+                       struct nl_cb *cb,
+                       struct nl_msg *msg,
+                       int argc, char **argv,
+                       enum id_input id)
+{
+       char *end;
+       unsigned int distance, coverage;
+
+       if (argc != 1)
+               return 1;
+
+       if (!*argv[0])
+               return 1;
+
+       distance = strtoul(argv[0], &end, 10);
+
+       if (*end)
+               return 1;
+
+       /*
+        * Divide double the distance by the speed of light in m/usec (300) to
+        * get round-trip time in microseconds and then divide the result by
+        * three to get coverage class as specified in IEEE 802.11-2007 table
+        * 7-27. Values are rounded upwards.
+        */
+       coverage = (distance + 449) / 450;
+       if (coverage > 255)
+               return 1;
+
+       NLA_PUT_U8(msg, NL80211_ATTR_WIPHY_COVERAGE_CLASS, coverage);
+
+       return 0;
+ nla_put_failure:
+       return -ENOBUFS;
+}
+COMMAND(set, distance, "<distance>",
+       NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_distance,
+       "Set appropriate coverage class for given link distance in meters.\n"
+       "Valid values: 0 - 114750");
+
+static int handle_txpower(struct nl80211_state *state,
+                         struct nl_cb *cb,
+                         struct nl_msg *msg,
+                         int argc, char **argv,
+                         enum id_input id)
+{
+       enum nl80211_tx_power_setting type;
+       int mbm;
+
+       /* get the required args */
+       if (argc != 1 && argc != 2)
+               return 1;
+
+       if (!strcmp(argv[0], "auto"))
+               type = NL80211_TX_POWER_AUTOMATIC;
+       else if (!strcmp(argv[0], "fixed"))
+               type = NL80211_TX_POWER_FIXED;
+       else if (!strcmp(argv[0], "limit"))
+               type = NL80211_TX_POWER_LIMITED;
+       else {
+               printf("Invalid parameter: %s\n", argv[0]);
+               return 2;
+       }
+
+       NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_TX_POWER_SETTING, type);
+
+       if (type != NL80211_TX_POWER_AUTOMATIC) {
+               char *endptr;
+               if (argc != 2) {
+                       printf("Missing TX power level argument.\n");
+                       return 2;
+               }
+
+               mbm = strtol(argv[1], &endptr, 10);
+               if (*endptr)
+                       return 2;
+               NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL, mbm);
+       } else if (argc != 1)
+               return 1;
+
+       return 0;
+
+ nla_put_failure:
+       return -ENOBUFS;
+}
+COMMAND(set, txpower, "<auto|fixed|limit> [<tx power in mBm>]",
+       NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_txpower,
+       "Specify transmit power level and setting type.");
+COMMAND(set, txpower, "<auto|fixed|limit> [<tx power in mBm>]",
+       NL80211_CMD_SET_WIPHY, 0, CIB_NETDEV, handle_txpower,
+       "Specify transmit power level and setting type.");
+
+static int handle_antenna(struct nl80211_state *state,
+                         struct nl_cb *cb,
+                         struct nl_msg *msg,
+                         int argc, char **argv,
+                         enum id_input id)
+{
+       char *end;
+       uint32_t tx_ant = 0, rx_ant = 0;
+
+       if (argc == 1 && strcmp(argv[0], "all") == 0) {
+               tx_ant = 0xffffffff;
+               rx_ant = 0xffffffff;
+       } else if (argc == 1) {
+               tx_ant = rx_ant = strtoul(argv[0], &end, 0);
+               if (*end)
+                       return 1;
+       }
+       else if (argc == 2) {
+               tx_ant = strtoul(argv[0], &end, 0);
+               if (*end)
+                       return 1;
+               rx_ant = strtoul(argv[1], &end, 0);
+               if (*end)
+                       return 1;
+       } else
+               return 1;
+
+       NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_ANTENNA_TX, tx_ant);
+       NLA_PUT_U32(msg, NL80211_ATTR_WIPHY_ANTENNA_RX, rx_ant);
+
+       return 0;
+
+ nla_put_failure:
+       return -ENOBUFS;
+}
+COMMAND(set, antenna, "<bitmap> | all | <tx bitmap> <rx bitmap>",
+       NL80211_CMD_SET_WIPHY, 0, CIB_PHY, handle_antenna,
+       "Set a bitmap of allowed antennas to use for TX and RX.\n"
+       "The driver may reject antenna configurations it cannot support.");