1 #include <linux/nl80211.h>
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>
24 PLINK_ACTION_UNDEFINED
,
30 static int wait_handler(struct nl_msg
*msg
, void *arg
)
38 static int error_handler(struct sockaddr_nl
*nla
, struct nlmsgerr
*err
,
41 fprintf(stderr
, "nl80211 error %d\n", err
->error
);
45 static int print_mpath_handler(struct nl_msg
*msg
, void *arg
)
47 struct nlattr
*tb
[NL80211_ATTR_MAX
+ 1];
48 struct genlmsghdr
*gnlh
= nlmsg_data(nlmsg_hdr(msg
));
49 struct nlattr
*pinfo
[NL80211_MPATH_INFO_MAX
+ 1];
50 char dst
[20], next_hop
[20], dev
[20];
51 static struct nla_policy mpath_policy
[NL80211_MPATH_INFO_MAX
+ 1] = {
52 [NL80211_MPATH_INFO_FRAME_QLEN
] = { .type
= NLA_U32
},
53 [NL80211_MPATH_INFO_DSN
] = { .type
= NLA_U32
},
54 [NL80211_MPATH_INFO_METRIC
] = { .type
= NLA_U32
},
55 [NL80211_MPATH_INFO_EXPTIME
] = { .type
= NLA_U32
},
56 [NL80211_MPATH_INFO_DISCOVERY_TIMEOUT
] = { .type
= NLA_U32
},
57 [NL80211_MPATH_INFO_DISCOVERY_RETRIES
] = { .type
= NLA_U8
},
58 [NL80211_MPATH_INFO_FLAGS
] = { .type
= NLA_U8
},
61 nla_parse(tb
, NL80211_ATTR_MAX
, genlmsg_attrdata(gnlh
, 0),
62 genlmsg_attrlen(gnlh
, 0), NULL
);
65 * TODO: validate the interface and mac address!
66 * Otherwise, there's a race condition as soon as
67 * the kernel starts sending mpath notifications.
70 if (!tb
[NL80211_ATTR_MPATH_INFO
]) {
71 fprintf(stderr
, "mpath info missing!");
74 if (nla_parse_nested(pinfo
, NL80211_MPATH_INFO_MAX
,
75 tb
[NL80211_ATTR_MPATH_INFO
],
77 fprintf(stderr
, "failed to parse nested attributes!");
81 mac_addr_n2a(dst
, nla_data(tb
[NL80211_ATTR_MAC
]));
82 mac_addr_n2a(next_hop
, nla_data(tb
[NL80211_ATTR_MPATH_NEXT_HOP
]));
83 if_indextoname(nla_get_u32(tb
[NL80211_ATTR_IFINDEX
]), dev
);
84 printf("%s %s %s", dst
, next_hop
, dev
);
85 if (pinfo
[NL80211_MPATH_INFO_DSN
])
87 nla_get_u32(pinfo
[NL80211_MPATH_INFO_DSN
]));
88 if (pinfo
[NL80211_MPATH_INFO_METRIC
])
90 nla_get_u32(pinfo
[NL80211_MPATH_INFO_METRIC
]));
91 if (pinfo
[NL80211_MPATH_INFO_FRAME_QLEN
])
93 nla_get_u32(pinfo
[NL80211_MPATH_INFO_FRAME_QLEN
]));
94 if (pinfo
[NL80211_MPATH_INFO_EXPTIME
])
96 nla_get_u32(pinfo
[NL80211_MPATH_INFO_EXPTIME
]));
97 if (pinfo
[NL80211_MPATH_INFO_DISCOVERY_TIMEOUT
])
99 nla_get_u32(pinfo
[NL80211_MPATH_INFO_DISCOVERY_TIMEOUT
]));
100 if (pinfo
[NL80211_MPATH_INFO_DISCOVERY_RETRIES
])
102 nla_get_u8(pinfo
[NL80211_MPATH_INFO_DISCOVERY_RETRIES
]));
103 if (pinfo
[NL80211_MPATH_INFO_FLAGS
])
105 nla_get_u8(pinfo
[NL80211_MPATH_INFO_FLAGS
]));
111 static int handle_mpath_get(struct nl80211_state
*state
,
112 char *dev
, int argc
, char **argv
)
115 struct nl_cb
*cb
= NULL
;
119 unsigned char dst
[ETH_ALEN
];
122 fprintf(stderr
, "not enough arguments\n");
126 if (mac_addr_a2n(dst
, argv
[0])) {
127 fprintf(stderr
, "invalid mac address\n");
134 fprintf(stderr
, "too many arguments\n");
142 genlmsg_put(msg
, 0, 0, genl_family_get_id(state
->nl80211
), 0,
143 0, NL80211_CMD_GET_MPATH
, 0);
145 NLA_PUT(msg
, NL80211_ATTR_MAC
, ETH_ALEN
, dst
);
146 NLA_PUT_U32(msg
, NL80211_ATTR_IFINDEX
, if_nametoindex(dev
));
148 cb
= nl_cb_alloc(NL_CB_CUSTOM
);
152 if (nl_send_auto_complete(state
->nl_handle
, msg
) < 0)
155 nl_cb_set(cb
, NL_CB_VALID
, NL_CB_CUSTOM
, print_mpath_handler
, NULL
);
156 nl_cb_set(cb
, NL_CB_ACK
, NL_CB_CUSTOM
, wait_handler
, &finished
);
157 nl_cb_err(cb
, NL_CB_CUSTOM
, error_handler
, NULL
);
159 err
= nl_recvmsgs(state
->nl_handle
, cb
);
162 err
= nl_wait_for_ack(state
->nl_handle
);
176 static int handle_mpath_set(struct nl80211_state
*state
, int new,
177 char *dev
, int argc
, char **argv
)
180 struct nl_cb
*cb
= NULL
;
184 unsigned char dst
[ETH_ALEN
];
185 unsigned char next_hop
[ETH_ALEN
];
188 fprintf(stderr
, "not enough arguments\n");
192 if (mac_addr_a2n(dst
, argv
[0])) {
193 fprintf(stderr
, "invalid destination mac address\n");
199 if (strcmp("next_hop", argv
[0]) != 0) {
200 fprintf(stderr
, "parameter not supported\n");
206 if (mac_addr_a2n(next_hop
, argv
[0])) {
207 fprintf(stderr
, "invalid next hop mac address\n");
214 fprintf(stderr
, "too many arguments\n");
222 command
= new ? NL80211_CMD_NEW_MPATH
: NL80211_CMD_SET_MPATH
;
223 genlmsg_put(msg
, 0, 0, genl_family_get_id(state
->nl80211
), 0, 0,
226 NLA_PUT(msg
, NL80211_ATTR_MAC
, ETH_ALEN
, dst
);
227 NLA_PUT_U32(msg
, NL80211_ATTR_IFINDEX
, if_nametoindex(dev
));
228 NLA_PUT(msg
, NL80211_ATTR_MPATH_NEXT_HOP
, ETH_ALEN
, next_hop
);
230 cb
= nl_cb_alloc(NL_CB_CUSTOM
);
234 if (nl_send_auto_complete(state
->nl_handle
, msg
) < 0)
237 nl_cb_set(cb
, NL_CB_VALID
, NL_CB_CUSTOM
, print_mpath_handler
, NULL
);
238 nl_cb_set(cb
, NL_CB_ACK
, NL_CB_CUSTOM
, wait_handler
, &finished
);
239 nl_cb_err(cb
, NL_CB_CUSTOM
, error_handler
, NULL
);
241 err
= nl_recvmsgs(state
->nl_handle
, cb
);
244 err
= nl_wait_for_ack(state
->nl_handle
);
258 static int handle_mpath_del(struct nl80211_state
*state
,
259 char *dev
, int argc
, char **argv
)
262 struct nl_cb
*cb
= NULL
;
266 unsigned char dst
[ETH_ALEN
];
269 fprintf(stderr
, "too many arguments\n");
273 if (argc
&& mac_addr_a2n(dst
, argv
[0])) {
274 fprintf(stderr
, "invalid mac address\n");
282 genlmsg_put(msg
, 0, 0, genl_family_get_id(state
->nl80211
), 0, 0,
283 NL80211_CMD_DEL_MPATH
, 0);
285 NLA_PUT_U32(msg
, NL80211_ATTR_IFINDEX
, if_nametoindex(dev
));
287 NLA_PUT(msg
, NL80211_ATTR_MAC
, ETH_ALEN
, dst
);
289 cb
= nl_cb_alloc(NL_CB_CUSTOM
);
293 if (nl_send_auto_complete(state
->nl_handle
, msg
) < 0)
296 nl_cb_set(cb
, NL_CB_VALID
, NL_CB_CUSTOM
, print_mpath_handler
, NULL
);
297 nl_cb_set(cb
, NL_CB_ACK
, NL_CB_CUSTOM
, wait_handler
, &finished
);
298 nl_cb_err(cb
, NL_CB_CUSTOM
, error_handler
, NULL
);
300 err
= nl_recvmsgs(state
->nl_handle
, cb
);
303 err
= nl_wait_for_ack(state
->nl_handle
);
317 static int handle_mpath_dump(struct nl80211_state
*state
,
318 char *dev
, int argc
, char **argv
)
321 struct nl_cb
*cb
= NULL
;
327 fprintf(stderr
, "too many arguments\n");
335 genlmsg_put(msg
, 0, 0, genl_family_get_id(state
->nl80211
), 0,
336 NLM_F_DUMP
, NL80211_CMD_GET_MPATH
, 0);
338 NLA_PUT_U32(msg
, NL80211_ATTR_IFINDEX
, if_nametoindex(dev
));
340 cb
= nl_cb_alloc(NL_CB_CUSTOM
);
344 if (nl_send_auto_complete(state
->nl_handle
, msg
) < 0)
347 nl_cb_set(cb
, NL_CB_VALID
, NL_CB_CUSTOM
, print_mpath_handler
, NULL
);
348 nl_cb_set(cb
, NL_CB_FINISH
, NL_CB_CUSTOM
, wait_handler
, &finished
);
350 err
= nl_recvmsgs(state
->nl_handle
, cb
);
364 int handle_mpath(struct nl80211_state
*state
,
365 char *dev
, int argc
, char **argv
)
370 fprintf(stderr
, "you must specify an mpath command\n");
377 if (strcmp(cmd
, "new") == 0)
378 return handle_mpath_set(state
, 1, dev
, argc
, argv
);
379 if (strcmp(cmd
, "del") == 0)
380 return handle_mpath_del(state
, dev
, argc
, argv
);
381 if (strcmp(cmd
, "get") == 0)
382 return handle_mpath_get(state
, dev
, argc
, argv
);
383 if (strcmp(cmd
, "set") == 0)
384 return handle_mpath_set(state
, 0, dev
, argc
, argv
);
385 if (strcmp(cmd
, "dump") == 0)
386 return handle_mpath_dump(state
, dev
, argc
, argv
);
388 printf("invalid interface command %s\n", cmd
);