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>
27 static int print_mpath_handler(struct nl_msg
*msg
, void *arg
)
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
},
35 [NL80211_MPATH_INFO_SN
] = { .type
= NLA_U32
},
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
},
41 [NL80211_MPATH_INFO_HOP_COUNT
] = { .type
= NLA_U8
},
42 [NL80211_MPATH_INFO_PATH_CHANGE
] = { .type
= NLA_U32
},
45 nla_parse(tb
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
46 genlmsg_attrlen(gnlh
, 0), NULL
);
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.
54 if (!tb
[NL80211_ATTR_MPATH_INFO
]) {
55 fprintf(stderr
, "mpath info missing!\n");
58 if (nla_parse_nested(pinfo
, NL80211_MPATH_INFO_MAX
,
59 tb
[NL80211_ATTR_MPATH_INFO
],
61 fprintf(stderr
, "failed to parse nested attributes!\n");
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
);
69 if (pinfo
[NL80211_MPATH_INFO_SN
])
71 nla_get_u32(pinfo
[NL80211_MPATH_INFO_SN
]));
72 if (pinfo
[NL80211_MPATH_INFO_METRIC
])
74 nla_get_u32(pinfo
[NL80211_MPATH_INFO_METRIC
]));
75 if (pinfo
[NL80211_MPATH_INFO_FRAME_QLEN
])
77 nla_get_u32(pinfo
[NL80211_MPATH_INFO_FRAME_QLEN
]));
78 if (pinfo
[NL80211_MPATH_INFO_EXPTIME
])
80 nla_get_u32(pinfo
[NL80211_MPATH_INFO_EXPTIME
]));
81 if (pinfo
[NL80211_MPATH_INFO_DISCOVERY_TIMEOUT
])
83 nla_get_u32(pinfo
[NL80211_MPATH_INFO_DISCOVERY_TIMEOUT
]));
84 if (pinfo
[NL80211_MPATH_INFO_DISCOVERY_RETRIES
])
86 nla_get_u8(pinfo
[NL80211_MPATH_INFO_DISCOVERY_RETRIES
]));
87 if (pinfo
[NL80211_MPATH_INFO_FLAGS
])
89 nla_get_u8(pinfo
[NL80211_MPATH_INFO_FLAGS
]));
90 if (pinfo
[NL80211_MPATH_INFO_HOP_COUNT
])
92 nla_get_u8(pinfo
[NL80211_MPATH_INFO_HOP_COUNT
]));
93 if (pinfo
[NL80211_MPATH_INFO_PATH_CHANGE
])
95 nla_get_u32(pinfo
[NL80211_MPATH_INFO_PATH_CHANGE
]));
101 static int handle_mpath_probe(struct nl80211_state
*state
,
103 int argc
, char **argv
,
106 unsigned char dst
[ETH_ALEN
];
107 unsigned char *frame
;
113 if (mac_addr_a2n(dst
, argv
[0])) {
114 fprintf(stderr
, "invalid mac address\n");
118 if (strcmp("frame", argv
[1]) != 0)
121 frame
= parse_hex(argv
[2], &frame_len
);
123 fprintf(stderr
, "invalid frame pattern: %p\n", frame
);
127 NLA_PUT(msg
, NL80211_ATTR_MAC
, ETH_ALEN
, dst
);
128 NLA_PUT(msg
, NL80211_ATTR_FRAME
, frame_len
, frame
);
134 COMMAND(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");
140 static int handle_mpath_get(struct nl80211_state
*state
,
142 int argc
, char **argv
,
145 unsigned char dst
[ETH_ALEN
];
150 if (mac_addr_a2n(dst
, argv
[0])) {
151 fprintf(stderr
, "invalid mac address\n");
160 NLA_PUT(msg
, NL80211_ATTR_MAC
, ETH_ALEN
, dst
);
162 register_handler(print_mpath_handler
, NULL
);
168 COMMAND(mpath
, get
, "<MAC address>",
169 NL80211_CMD_GET_MPATH
, 0, CIB_NETDEV
, handle_mpath_get
,
170 "Get information on mesh path to the given node.");
171 COMMAND(mpath
, del
, "<MAC address>",
172 NL80211_CMD_DEL_MPATH
, 0, CIB_NETDEV
, handle_mpath_get
,
173 "Remove the mesh path to the given node.");
175 static int handle_mpath_set(struct nl80211_state
*state
,
177 int argc
, char **argv
,
180 unsigned char dst
[ETH_ALEN
];
181 unsigned char next_hop
[ETH_ALEN
];
186 if (mac_addr_a2n(dst
, argv
[0])) {
187 fprintf(stderr
, "invalid destination mac address\n");
193 if (strcmp("next_hop", argv
[0]) != 0)
198 if (mac_addr_a2n(next_hop
, argv
[0])) {
199 fprintf(stderr
, "invalid next hop mac address\n");
208 NLA_PUT(msg
, NL80211_ATTR_MAC
, ETH_ALEN
, dst
);
209 NLA_PUT(msg
, NL80211_ATTR_MPATH_NEXT_HOP
, ETH_ALEN
, next_hop
);
211 register_handler(print_mpath_handler
, NULL
);
216 COMMAND(mpath
, new, "<destination MAC address> next_hop <next hop MAC address>",
217 NL80211_CMD_NEW_MPATH
, 0, CIB_NETDEV
, handle_mpath_set
,
218 "Create a new mesh path (instead of relying on automatic discovery).");
219 COMMAND(mpath
, set
, "<destination MAC address> next_hop <next hop MAC address>",
220 NL80211_CMD_SET_MPATH
, 0, CIB_NETDEV
, handle_mpath_set
,
221 "Set an existing mesh path's next hop.");
223 static int handle_mpath_dump(struct nl80211_state
*state
,
225 int argc
, char **argv
,
228 printf("DEST ADDR NEXT HOP IFACE\tSN\tMETRIC\tQLEN\t"
229 "EXPTIME\t\tDTIM\tDRET\tFLAGS\tHOP_COUNT\tPATH_CHANGE\n");
230 register_handler(print_mpath_handler
, NULL
);
233 COMMAND(mpath
, dump
, NULL
,
234 NL80211_CMD_GET_MPATH
, NLM_F_DUMP
, CIB_NETDEV
, handle_mpath_dump
,
235 "List known mesh paths.");