]> git.ipfire.org Git - thirdparty/iw.git/blame - mpath.c
update nl80211.h
[thirdparty/iw.git] / mpath.c
CommitLineData
2ef1be68 1#include <net/if.h>
3d1e8704 2#include <errno.h>
d5ac8ad3 3#include <string.h>
2ef1be68 4
3d1e8704
LCC
5#include <netlink/genl/genl.h>
6#include <netlink/genl/family.h>
7#include <netlink/genl/ctrl.h>
8#include <netlink/msg.h>
9#include <netlink/attr.h>
3d1e8704 10
f408e01b 11#include "nl80211.h"
3d1e8704
LCC
12#include "iw.h"
13
4698bfc2
JB
14SECTION(mpath);
15
3d1e8704
LCC
16enum plink_state {
17 LISTEN,
18 OPN_SNT,
19 OPN_RCVD,
20 CNF_RCVD,
21 ESTAB,
22 HOLDING,
23 BLOCKED
24};
25
3d1e8704 26
3d1e8704
LCC
27static int print_mpath_handler(struct nl_msg *msg, void *arg)
28{
29 struct nlattr *tb[NL80211_ATTR_MAX + 1];
30 struct genlmsghdr *gnlh = nlmsg_data(nlmsg_hdr(msg));
31 struct nlattr *pinfo[NL80211_MPATH_INFO_MAX + 1];
32 char dst[20], next_hop[20], dev[20];
33 static struct nla_policy mpath_policy[NL80211_MPATH_INFO_MAX + 1] = {
34 [NL80211_MPATH_INFO_FRAME_QLEN] = { .type = NLA_U32 },
456ce438 35 [NL80211_MPATH_INFO_SN] = { .type = NLA_U32 },
3d1e8704
LCC
36 [NL80211_MPATH_INFO_METRIC] = { .type = NLA_U32 },
37 [NL80211_MPATH_INFO_EXPTIME] = { .type = NLA_U32 },
38 [NL80211_MPATH_INFO_DISCOVERY_TIMEOUT] = { .type = NLA_U32 },
39 [NL80211_MPATH_INFO_DISCOVERY_RETRIES] = { .type = NLA_U8 },
40 [NL80211_MPATH_INFO_FLAGS] = { .type = NLA_U8 },
8b159daa
TC
41 [NL80211_MPATH_INFO_HOP_COUNT] = { .type = NLA_U8 },
42 [NL80211_MPATH_INFO_PATH_CHANGE] = { .type = NLA_U32 },
3d1e8704
LCC
43 };
44
45 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
46 genlmsg_attrlen(gnlh, 0), NULL);
47
48 /*
49 * TODO: validate the interface and mac address!
50 * Otherwise, there's a race condition as soon as
51 * the kernel starts sending mpath notifications.
52 */
53
54 if (!tb[NL80211_ATTR_MPATH_INFO]) {
5fe70c0e 55 fprintf(stderr, "mpath info missing!\n");
3d1e8704
LCC
56 return NL_SKIP;
57 }
58 if (nla_parse_nested(pinfo, NL80211_MPATH_INFO_MAX,
59 tb[NL80211_ATTR_MPATH_INFO],
60 mpath_policy)) {
5fe70c0e 61 fprintf(stderr, "failed to parse nested attributes!\n");
3d1e8704
LCC
62 return NL_SKIP;
63 }
64
65 mac_addr_n2a(dst, nla_data(tb[NL80211_ATTR_MAC]));
66 mac_addr_n2a(next_hop, nla_data(tb[NL80211_ATTR_MPATH_NEXT_HOP]));
67 if_indextoname(nla_get_u32(tb[NL80211_ATTR_IFINDEX]), dev);
68 printf("%s %s %s", dst, next_hop, dev);
456ce438 69 if (pinfo[NL80211_MPATH_INFO_SN])
3d1e8704 70 printf("\t%u",
456ce438 71 nla_get_u32(pinfo[NL80211_MPATH_INFO_SN]));
3d1e8704
LCC
72 if (pinfo[NL80211_MPATH_INFO_METRIC])
73 printf("\t%u",
74 nla_get_u32(pinfo[NL80211_MPATH_INFO_METRIC]));
75 if (pinfo[NL80211_MPATH_INFO_FRAME_QLEN])
76 printf("\t%u",
77 nla_get_u32(pinfo[NL80211_MPATH_INFO_FRAME_QLEN]));
78 if (pinfo[NL80211_MPATH_INFO_EXPTIME])
79 printf("\t%u",
80 nla_get_u32(pinfo[NL80211_MPATH_INFO_EXPTIME]));
81 if (pinfo[NL80211_MPATH_INFO_DISCOVERY_TIMEOUT])
82 printf("\t%u",
83 nla_get_u32(pinfo[NL80211_MPATH_INFO_DISCOVERY_TIMEOUT]));
84 if (pinfo[NL80211_MPATH_INFO_DISCOVERY_RETRIES])
85 printf("\t%u",
86 nla_get_u8(pinfo[NL80211_MPATH_INFO_DISCOVERY_RETRIES]));
87 if (pinfo[NL80211_MPATH_INFO_FLAGS])
88 printf("\t0x%x",
89 nla_get_u8(pinfo[NL80211_MPATH_INFO_FLAGS]));
8b159daa
TC
90 if (pinfo[NL80211_MPATH_INFO_HOP_COUNT])
91 printf("\t%u",
92 nla_get_u8(pinfo[NL80211_MPATH_INFO_HOP_COUNT]));
93 if (pinfo[NL80211_MPATH_INFO_PATH_CHANGE])
94 printf("\t%u",
95 nla_get_u32(pinfo[NL80211_MPATH_INFO_PATH_CHANGE]));
3d1e8704
LCC
96
97 printf("\n");
98 return NL_SKIP;
99}
100
24091b7f
PKC
101static int handle_mpath_probe(struct nl80211_state *state,
102 struct nl_msg *msg,
103 int argc, char **argv,
104 enum id_input id)
105{
106 unsigned char dst[ETH_ALEN];
107 unsigned char *frame;
108 size_t frame_len;
109
110 if (argc < 3)
111 return 1;
112
113 if (mac_addr_a2n(dst, argv[0])) {
114 fprintf(stderr, "invalid mac address\n");
115 return 2;
116 }
117
118 if (strcmp("frame", argv[1]) != 0)
119 return 1;
120
121 frame = parse_hex(argv[2], &frame_len);
122 if (!frame) {
123 fprintf(stderr, "invalid frame pattern: %p\n", frame);
124 return 2;
125 }
126
127 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst);
128 NLA_PUT(msg, NL80211_ATTR_FRAME, frame_len, frame);
129
130 return 0;
131 nla_put_failure:
132 return -ENOBUFS;
133}
134COMMAND(mpath, probe, "<destination MAC address> frame <frame>",
135 NL80211_CMD_PROBE_MESH_LINK, 0, CIB_NETDEV, handle_mpath_probe,
136 "Inject ethernet frame to given peer overriding the next hop\n"
137 "lookup from mpath table.\n."
138 "Example: iw dev wlan0 mpath probe xx:xx:xx:xx:xx:xx frame 01:xx:xx:00\n");
139
7c37a24d 140static int handle_mpath_get(struct nl80211_state *state,
f5f937fb 141 struct nl_msg *msg,
05514f95
JB
142 int argc, char **argv,
143 enum id_input id)
3d1e8704 144{
3d1e8704
LCC
145 unsigned char dst[ETH_ALEN];
146
f5f937fb 147 if (argc < 1)
5e75fd04 148 return 1;
3d1e8704
LCC
149
150 if (mac_addr_a2n(dst, argv[0])) {
151 fprintf(stderr, "invalid mac address\n");
5e75fd04 152 return 2;
3d1e8704
LCC
153 }
154 argc--;
155 argv++;
156
f5f937fb 157 if (argc)
5e75fd04 158 return 1;
3d1e8704
LCC
159
160 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst);
3d1e8704 161
34b23014 162 register_handler(print_mpath_handler, NULL);
3d1e8704 163
70391ccf 164 return 0;
3d1e8704 165 nla_put_failure:
70391ccf 166 return -ENOBUFS;
3d1e8704 167}
f5f937fb 168COMMAND(mpath, get, "<MAC address>",
70cf4544
JB
169 NL80211_CMD_GET_MPATH, 0, CIB_NETDEV, handle_mpath_get,
170 "Get information on mesh path to the given node.");
f5f937fb 171COMMAND(mpath, del, "<MAC address>",
70cf4544
JB
172 NL80211_CMD_DEL_MPATH, 0, CIB_NETDEV, handle_mpath_get,
173 "Remove the mesh path to the given node.");
f5f937fb 174
7c37a24d 175static int handle_mpath_set(struct nl80211_state *state,
f5f937fb 176 struct nl_msg *msg,
05514f95
JB
177 int argc, char **argv,
178 enum id_input id)
3d1e8704 179{
3d1e8704
LCC
180 unsigned char dst[ETH_ALEN];
181 unsigned char next_hop[ETH_ALEN];
182
f5f937fb 183 if (argc < 3)
5e75fd04 184 return 1;
3d1e8704
LCC
185
186 if (mac_addr_a2n(dst, argv[0])) {
187 fprintf(stderr, "invalid destination mac address\n");
5e75fd04 188 return 2;
3d1e8704
LCC
189 }
190 argc--;
191 argv++;
192
f5f937fb 193 if (strcmp("next_hop", argv[0]) != 0)
5e75fd04 194 return 1;
3d1e8704
LCC
195 argc--;
196 argv++;
197
198 if (mac_addr_a2n(next_hop, argv[0])) {
199 fprintf(stderr, "invalid next hop mac address\n");
5e75fd04 200 return 2;
3d1e8704
LCC
201 }
202 argc--;
203 argv++;
204
f5f937fb 205 if (argc)
5e75fd04 206 return 1;
3d1e8704 207
3d1e8704 208 NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, dst);
3d1e8704
LCC
209 NLA_PUT(msg, NL80211_ATTR_MPATH_NEXT_HOP, ETH_ALEN, next_hop);
210
34b23014 211 register_handler(print_mpath_handler, NULL);
70391ccf 212 return 0;
3d1e8704 213 nla_put_failure:
70391ccf 214 return -ENOBUFS;
3d1e8704 215}
f5f937fb 216COMMAND(mpath, new, "<destination MAC address> next_hop <next hop MAC address>",
70cf4544
JB
217 NL80211_CMD_NEW_MPATH, 0, CIB_NETDEV, handle_mpath_set,
218 "Create a new mesh path (instead of relying on automatic discovery).");
f5f937fb 219COMMAND(mpath, set, "<destination MAC address> next_hop <next hop MAC address>",
70cf4544
JB
220 NL80211_CMD_SET_MPATH, 0, CIB_NETDEV, handle_mpath_set,
221 "Set an existing mesh path's next hop.");
3d1e8704 222
7c37a24d 223static int handle_mpath_dump(struct nl80211_state *state,
f5f937fb 224 struct nl_msg *msg,
05514f95
JB
225 int argc, char **argv,
226 enum id_input id)
3d1e8704 227{
e1fa918a 228 printf("DEST ADDR NEXT HOP IFACE\tSN\tMETRIC\tQLEN\t"
ff67fb2c 229 "EXPTIME\tDTIM\tDRET\tFLAGS\tHOP_COUNT\tPATH_CHANGE\n");
34b23014 230 register_handler(print_mpath_handler, NULL);
70391ccf 231 return 0;
3d1e8704 232}
f5f937fb 233COMMAND(mpath, dump, NULL,
70cf4544
JB
234 NL80211_CMD_GET_MPATH, NLM_F_DUMP, CIB_NETDEV, handle_mpath_dump,
235 "List known mesh paths.");