@@ -61,7 +61,6 @@ enum {
SKIP_HEADER = 0x100,
UNICAST_ONLY = 0x200,
MULTICAST_ONLY = 0x400,
- PARSE_ONLY = 0x800,
};
#endif
@@ -54,6 +54,9 @@ struct print_opts {
int read_opt;
float orig_timeout;
float watch_interval;
+ nl_recvmsg_msg_cb_t callback;
+ char *remaining_header;
+ const char *static_header;
uint8_t nl_cmd;
};
@@ -139,7 +142,7 @@ static int print_error(struct sockaddr_nl *nla __unused,
fprintf(stderr, "Error received: %s\n",
strerror(-nlerr->error));
- last_err = -nlerr->error;
+ last_err = nlerr->error;
return NL_STOP;
}
@@ -182,6 +185,7 @@ static int info_callback(struct nl_msg *msg, void *arg)
uint8_t ttvn = 0;
uint16_t bla_group_id = 0;
const char *algo_name;
+ const char *extra_header;
int ret;
if (!genlmsg_valid_hdr(nlh, 0)) {
@@ -230,54 +234,64 @@ static int info_callback(struct nl_msg *msg, void *arg)
if (attrs[BATADV_ATTR_BLA_CRC])
bla_group_id = nla_get_u16(attrs[BATADV_ATTR_BLA_CRC]);
- if (!(opts->read_opt & PARSE_ONLY)) {
- switch (opts->nl_cmd) {
- case BATADV_CMD_GET_TRANSTABLE_LOCAL:
- ret = asprintf(&extra_info, ", TTVN: %u", ttvn);
- if (ret < 0)
- extra_info = NULL;
- break;
- case BATADV_CMD_GET_BLA_BACKBONE:
- case BATADV_CMD_GET_BLA_CLAIM:
- ret = asprintf(&extra_info, ", group id: 0x%04x",
- bla_group_id);
- if (ret < 0)
- extra_info = NULL;
- break;
- default:
- extra_info = strdup("");
- break;
- }
-
- printf("[B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%02x:%02x:%02x:%02x:%02x:%02x (%s/%02x:%02x:%02x:%02x:%02x:%02x %s)%s]\n",
+ switch (opts->nl_cmd) {
+ case BATADV_CMD_GET_TRANSTABLE_LOCAL:
+ ret = asprintf(&extra_info, ", TTVN: %u", ttvn);
+ if (ret < 0)
+ extra_info = NULL;
+ break;
+ case BATADV_CMD_GET_BLA_BACKBONE:
+ case BATADV_CMD_GET_BLA_CLAIM:
+ ret = asprintf(&extra_info, ", group id: 0x%04x",
+ bla_group_id);
+ if (ret < 0)
+ extra_info = NULL;
+ break;
+ default:
+ extra_info = strdup("");
+ break;
+ }
+
+ if (opts->static_header)
+ extra_header = opts->static_header;
+ else
+ extra_header = "";
+
+ ret = asprintf(&opts->remaining_header,
+ "[B.A.T.M.A.N. adv %s, MainIF/MAC: %s/%02x:%02x:%02x:%02x:%02x:%02x (%s/%02x:%02x:%02x:%02x:%02x:%02x %s)%s]\n%s",
version, primary_if,
primary_mac[0], primary_mac[1], primary_mac[2],
primary_mac[3], primary_mac[4], primary_mac[5],
mesh_name,
mesh_mac[0], mesh_mac[1], mesh_mac[2],
mesh_mac[3], mesh_mac[4], mesh_mac[5],
- algo_name, extra_info);
+ algo_name, extra_info, extra_header);
+ if (ret < 0)
+ opts->remaining_header = NULL;
- if (extra_info)
- free(extra_info);
- }
+ if (extra_info)
+ free(extra_info);
} else {
- if (!(opts->read_opt & PARSE_ONLY))
- printf("BATMAN mesh %s disabled\n", mesh_name);
+ ret = asprintf(&opts->remaining_header,
+ "BATMAN mesh %s disabled\n", mesh_name);
+ if (ret < 0)
+ opts->remaining_header = NULL;
}
return NL_STOP;
}
-static void netlink_print_info(int ifindex, uint8_t nl_cmd, int read_opt)
+static char *netlink_get_info(int ifindex, uint8_t nl_cmd, const char *header)
{
struct nl_sock *sock;
struct nl_msg *msg;
struct nl_cb *cb;
int family;
struct print_opts opts = {
- .read_opt = read_opt,
+ .read_opt = 0,
.nl_cmd = nl_cmd,
+ .remaining_header = NULL,
+ .static_header = header,
};
sock = nl_socket_alloc();
@@ -285,7 +299,7 @@ static void netlink_print_info(int ifindex, uint8_t nl_cmd, int read_opt)
family = genl_ctrl_resolve(sock, BATADV_NL_NAME);
if (family < 0)
- return;
+ return NULL;
msg = nlmsg_alloc();
genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0, 0,
@@ -304,6 +318,27 @@ static void netlink_print_info(int ifindex, uint8_t nl_cmd, int read_opt)
nl_recvmsgs(sock, cb);
nl_socket_free(sock);
+
+ return opts.remaining_header;
+}
+
+static void netlink_print_remaining_header(struct print_opts *opts)
+{
+ if (!opts->remaining_header)
+ return;
+
+ fputs(opts->remaining_header, stdout);
+ free(opts->remaining_header);
+ opts->remaining_header = NULL;
+}
+
+static int netlink_print_common_cb(struct nl_msg *msg, void *arg)
+{
+ struct print_opts *opts = arg;
+
+ netlink_print_remaining_header(opts);
+
+ return opts->callback(msg, arg);
}
static const int routing_algos_mandatory[] = {
@@ -352,6 +387,9 @@ int netlink_print_routing_algos(void)
struct nl_msg *msg;
struct nl_cb *cb;
int family;
+ struct print_opts opts = {
+ .callback = routing_algos_callback,
+ };
sock = nl_socket_alloc();
genl_connect(sock);
@@ -368,19 +406,21 @@ int netlink_print_routing_algos(void)
nlmsg_free(msg);
+ opts.remaining_header = strdup("Available routing algorithms:\n");
+
cb = nl_cb_alloc(NL_CB_DEFAULT);
- nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, routing_algos_callback,
- NULL);
+ nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, netlink_print_common_cb,
+ &opts);
nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, stop_callback, NULL);
nl_cb_err(cb, NL_CB_CUSTOM, print_error, NULL);
- printf("Available routing algorithms:\n");
-
nl_recvmsgs(sock, cb);
-
nl_socket_free(sock);
- return 0;
+ if (!last_err)
+ netlink_print_remaining_header(&opts);
+
+ return last_err;
}
static const int originators_mandatory[] = {
@@ -1040,7 +1080,9 @@ static int netlink_print_common(char *mesh_iface, char *orig_iface,
struct print_opts opts = {
.read_opt = read_opt,
.orig_timeout = orig_timeout,
- .watch_interval = watch_interval
+ .watch_interval = watch_interval,
+ .remaining_header = NULL,
+ .callback = callback,
};
int hardifindex = 0;
struct nl_sock *sock;
@@ -1074,7 +1116,7 @@ static int netlink_print_common(char *mesh_iface, char *orig_iface,
bat_hosts_init(read_opt);
cb = nl_cb_alloc(NL_CB_DEFAULT);
- nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, callback, &opts);
+ nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, netlink_print_common_cb, &opts);
nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, stop_callback, NULL);
nl_cb_err(cb, NL_CB_CUSTOM, print_error, NULL);
@@ -1083,11 +1125,10 @@ static int netlink_print_common(char *mesh_iface, char *orig_iface,
/* clear screen, set cursor back to 0,0 */
printf("\033[2J\033[0;0f");
- if (!(read_opt & SKIP_HEADER)) {
- netlink_print_info(ifindex, nl_cmd, 0);
- if (header)
- printf("%s", header);
- }
+ if (!(read_opt & SKIP_HEADER))
+ opts.remaining_header = netlink_get_info(ifindex,
+ nl_cmd,
+ header);
msg = nlmsg_alloc();
genlmsg_put(msg, NL_AUTO_PID, NL_AUTO_SEQ, family, 0,
@@ -1104,6 +1145,11 @@ static int netlink_print_common(char *mesh_iface, char *orig_iface,
last_err = 0;
nl_recvmsgs(sock, cb);
+
+ /* the header should still be printed when no entry was received */
+ if (!last_err)
+ netlink_print_remaining_header(&opts);
+
if (!last_err && read_opt & (CONT_READ|CLR_CONT_READ))
usleep(1000000 * watch_interval);
@@ -1120,7 +1166,8 @@ int netlink_print_originators(char *mesh_iface, char *orig_iface,
int read_opts, float orig_timeout,
float watch_interval)
{
- char *header;
+ char *header = NULL;
+ char *info_header;
int ifindex;
ifindex = if_nametoindex(mesh_iface);
@@ -1129,10 +1176,12 @@ int netlink_print_originators(char *mesh_iface, char *orig_iface,
return -ENODEV;
}
- netlink_print_info(ifindex, BATADV_CMD_GET_ORIGINATORS, PARSE_ONLY);
+ /* only parse routing algorithm name */
+ info_header = netlink_get_info(ifindex, BATADV_CMD_GET_ORIGINATORS, NULL);
+ free(info_header);
if (strlen(algo_name_buf) == 0)
- return -EINVAL;
+ return -EOPNOTSUPP;
if (!strcmp("BATMAN_IV", algo_name_buf))
header = " Originator last-seen (#/255) Nexthop [outgoingIF]\n";
@@ -1184,7 +1233,8 @@ int netlink_print_translocal(char *mesh_iface, char *orig_iface, int read_opts,
int netlink_print_gateways(char *mesh_iface, char *orig_iface, int read_opts,
float orig_timeout,
float watch_interval)
-{ char *header;
+{ char *header = NULL;
+ char *info_header;
int ifindex;
ifindex = if_nametoindex(mesh_iface);
@@ -1193,10 +1243,12 @@ int netlink_print_gateways(char *mesh_iface, char *orig_iface, int read_opts,
return -ENODEV;
}
- netlink_print_info(ifindex, BATADV_CMD_GET_ORIGINATORS, PARSE_ONLY);
+ /* only parse routing algorithm name */
+ info_header = netlink_get_info(ifindex, BATADV_CMD_GET_ORIGINATORS, NULL);
+ free(info_header);
if (strlen(algo_name_buf) == 0)
- return -EINVAL;
+ return -EOPNOTSUPP;
if (!strcmp("BATMAN_IV", algo_name_buf))
header = " Router ( TQ) Next Hop [outgoingIf] Bandwidth\n";