[PATCH net 00/12] net: iflink and link-netnsid fixes
by Sabrina Dubroca
In a lot of places, we use this kind of comparison to detect if a
device has a lower link:
dev->ifindex != dev_get_iflink(dev)
This seems to be a leftover of the pre-netns days, when the ifindex
was unique over the whole system. Nowadays, with network namespaces,
it's very easy to create a device with the same ifindex as its lower
link:
ip netns add main
ip netns add peer
ip -net main link add dummy0 type dummy
ip -net main link add link dummy0 macvlan0 netns peer type macvlan
ip -net main link show type dummy
9: dummy0: <BROADCAST,NOARP> mtu 1500 qdisc noop ...
ip -net peer link show type macvlan
9: macvlan0@if9: <BROADCAST,MULTICAST> mtu 1500 qdisc noop ...
To detect if a device has a lower link, we can simply check the
existence of the dev->netdev_ops->ndo_get_iflink operation, instead of
checking its return value. In particular, I attempted to fix one of
these checks in commit feadc4b6cf42 ("rtnetlink: always put IFLA_LINK
for links with a link-netnsid"), but this patch isn't correct, since
tunnel devices can export IFLA_LINK_NETNSID without IFLA_LINK. That
patch needs to be reverted.
This series will fix all those bogus comparisons, and export missing
IFLA_LINK_NETNSID attributes in bridge and ipv6 dumps.
ipvlan and geneve are also missing the get_link_net operation, so
userspace can't know when those device are cross-netns. There are a
couple of other device types that have an ndo_get_iflink op but no
get_link_net (virt_wifi, ipoib), and should probably also have a
get_link_net.
Sabrina Dubroca (12):
ipvlan: add get_link_net
geneve: add get_link_net
Revert "rtnetlink: always put IFLA_LINK for links with a link-netnsid"
rtnetlink: always put IFLA_LINK for links with ndo_get_iflink
bridge: always put IFLA_LINK for ports with ndo_get_iflink
bridge: advertise IFLA_LINK_NETNSID when dumping bridge ports
ipv6: always put IFLA_LINK for devices with ndo_get_iflink
ipv6: advertise IFLA_LINK_NETNSID when dumping ipv6 addresses
net: link_watch: fix operstate when the link has the same index as the
device
net: link_watch: fix detection of urgent events
batman-adv: fix iflink detection in batadv_is_on_batman_iface
batman-adv: fix detection of lower link in batadv_get_real_netdevice
drivers/net/can/vxcan.c | 2 +-
drivers/net/geneve.c | 8 ++++++++
drivers/net/ipvlan/ipvlan_main.c | 9 +++++++++
drivers/net/veth.c | 2 +-
include/net/rtnetlink.h | 4 ++++
net/batman-adv/hard-interface.c | 4 ++--
net/bridge/br_netlink.c | 4 +++-
net/core/link_watch.c | 4 ++--
net/core/rtnetlink.c | 25 ++++++++++++-------------
net/ipv6/addrconf.c | 11 ++++++++++-
10 files changed, 52 insertions(+), 21 deletions(-)
--
2.28.0
8 months, 3 weeks
[RFC PATCH 1/4] batman-adv: Request iflink once in batadv-on-batadv check
by Sven Eckelmann
There is no need to call dev_get_iflink multiple times for the same
net_device in batadv_is_on_batman_iface. And since some of the
.ndo_get_iflink callbacks are dynamic (for example via RCUs like in
vxcan_get_iflink), it could easily happen that the returned values are not
stable. The pre-checks before __dev_get_by_index are then of course bogus.
Fixes: 3d48811b27f5 ("batman-adv: prevent using any virtual device created on batman-adv as hard-interface")
Signed-off-by: Sven Eckelmann <sven(a)narfation.org>
---
net/batman-adv/hard-interface.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
index 59d19097..774a26c5 100644
--- a/net/batman-adv/hard-interface.c
+++ b/net/batman-adv/hard-interface.c
@@ -149,22 +149,23 @@ static bool batadv_is_on_batman_iface(const struct net_device *net_dev)
struct net *net = dev_net(net_dev);
struct net_device *parent_dev;
struct net *parent_net;
+ int iflink;
bool ret;
/* check if this is a batman-adv mesh interface */
if (batadv_softif_is_valid(net_dev))
return true;
+ iflink = dev_get_iflink(net_dev);
+
/* no more parents..stop recursion */
- if (dev_get_iflink(net_dev) == 0 ||
- dev_get_iflink(net_dev) == net_dev->ifindex)
+ if (iflink == 0 || iflink == net_dev->ifindex)
return false;
parent_net = batadv_getlink_net(net_dev, net);
/* recurse over the parent device */
- parent_dev = __dev_get_by_index((struct net *)parent_net,
- dev_get_iflink(net_dev));
+ parent_dev = __dev_get_by_index((struct net *)parent_net, iflink);
/* if we got a NULL parent_dev there is something broken.. */
if (!parent_dev) {
pr_err("Cannot find parent device\n");
--
2.30.2
11 months, 1 week
[PATCH v4] alfred: introduce 'server status' IPC call
by Marek Lindner
The 'server status' call exports the 'mode' as well as interface
status via IPC. Both parameters can be modified at runtime via the
IPC and as such, the current configuration is dynamic and not
necessarily obvious.
The server status 'request' and 'reply' packet types are added
to allow the IPC client to initiate the status retrieval. The
server will respond with the 'reply' message.
The information is encapsulated in TLV data chunks allowing for
future backward compatible extension of the server status call.
Signed-off-by: Marek Lindner <mareklindner(a)neomailbox.ch>
---
v4:
- buffer safety checks in server code
- move tlv type definitions into packet header
- version checks for sub tlv
v3:
- close client socket at the end of unix_sock_server_status()
alfred.h | 5 +++
client.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++++++
main.c | 9 +++-
man/alfred.8 | 3 ++
packet.h | 68 +++++++++++++++++++++++++++++
unix_sock.c | 106 +++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 310 insertions(+), 1 deletion(-)
diff --git a/alfred.h b/alfred.h
index 9ab92a2..598d38b 100644
--- a/alfred.h
+++ b/alfred.h
@@ -33,6 +33,9 @@
#define FIXED_TLV_LEN(__tlv_type) \
htons(sizeof(__tlv_type) - sizeof(__tlv_type.header))
+#define FIXED_TLV_LEN_PTR(__tlv_type) \
+ htons(sizeof(*__tlv_type) - sizeof(__tlv_type->header))
+
enum data_source {
SOURCE_LOCAL = 0,
SOURCE_FIRST_HAND = 1,
@@ -93,6 +96,7 @@ enum clientmode {
CLIENT_MODESWITCH,
CLIENT_CHANGE_INTERFACE,
CLIENT_CHANGE_BAT_IFACE,
+ CLIENT_SERVER_STATUS,
};
struct interface {
@@ -155,6 +159,7 @@ int alfred_client_set_data(struct globals *globals);
int alfred_client_modeswitch(struct globals *globals);
int alfred_client_change_interface(struct globals *globals);
int alfred_client_change_bat_iface(struct globals *globals);
+int alfred_client_server_status(struct globals *globals);
/* recv.c */
int recv_alfred_packet(struct globals *globals, struct interface *interface,
int recv_sock);
diff --git a/client.c b/client.c
index b5d8943..ab4bba6 100644
--- a/client.c
+++ b/client.c
@@ -325,3 +325,123 @@ int alfred_client_change_bat_iface(struct globals *globals)
return 0;
}
+
+int alfred_client_server_status(struct globals *globals)
+{
+ struct alfred_server_status_net_iface_v0 *status_net_iface;
+ struct alfred_server_status_bat_iface_v0 *status_bat_iface;
+ struct alfred_server_status_op_mode_v0 *status_op_mode;
+ struct alfred_server_status_req_v0 status_req;
+ struct alfred_server_status_rep_v0 *status_rep;
+ int ret, tlvsize, headsize, len, consumed;
+ struct alfred_tlv *status_tlv;
+ uint8_t buf[MAX_PAYLOAD];
+
+ if (unix_sock_open_client(globals))
+ return -1;
+
+ len = sizeof(status_req);
+ memset(&status_req, 0, len);
+
+ status_req.header.type = ALFRED_SERVER_STATUS;
+ status_req.header.version = ALFRED_VERSION;
+ status_req.header.length = 0;
+
+ ret = write(globals->unix_sock, (unsigned char *)&status_req, len);
+ if (ret != len)
+ fprintf(stderr, "%s: only wrote %d of %d bytes: %s\n",
+ __func__, ret, len, strerror(errno));
+
+ len = read(globals->unix_sock, buf, sizeof(buf));
+ if (len <= 0) {
+ perror("read from unix socket failed");
+ goto err;
+ }
+
+ ret = -1;
+ status_rep = (struct alfred_server_status_rep_v0 *)buf;
+
+ /* drop too small packets */
+ headsize = sizeof(status_rep->header);
+ if (len < headsize) {
+ perror("unexpected header size received from unix socket");
+ goto err;
+ }
+
+ if ((len - headsize) < ((int)ntohs(status_rep->header.length))) {
+ perror("unexpected packet size received from unix socket");
+ goto err;
+ }
+
+ if (status_rep->header.version != ALFRED_VERSION) {
+ perror("alfred version mismatch");
+ goto err;
+ }
+
+ headsize = ntohs(status_rep->header.length);
+
+ if (headsize < (int)(sizeof(*status_rep) - sizeof(status_rep->header)))
+ goto err;
+
+ consumed = sizeof(*status_rep);
+
+ while (len - consumed > 0) {
+ if (len - consumed < (int)sizeof(*status_tlv))
+ break;
+
+ status_tlv = (struct alfred_tlv *)(buf + consumed);
+
+ if (status_tlv->version != ALFRED_VERSION)
+ break;
+
+ tlvsize = ntohs(status_tlv->length);
+ tlvsize += sizeof(*status_tlv);
+
+ if (len - consumed < tlvsize)
+ break;
+
+ switch (status_tlv->type) {
+ case ALFRED_SERVER_OP_MODE:
+ if (tlvsize != sizeof(*status_op_mode))
+ break;
+
+ status_op_mode = (struct alfred_server_status_op_mode_v0 *)(buf + consumed);
+
+ switch (status_op_mode->mode) {
+ case ALFRED_MODESWITCH_SECONDARY:
+ fprintf(stdout, "- mode: secondary\n");
+ break;
+ case ALFRED_MODESWITCH_PRIMARY:
+ fprintf(stdout, "- mode: primary\n");
+ break;
+ default:
+ fprintf(stderr, "- mode: unknown\n");
+ break;
+ }
+
+ break;
+ case ALFRED_SERVER_NET_IFACE:
+ if (tlvsize != sizeof(*status_net_iface))
+ break;
+
+ status_net_iface = (struct alfred_server_status_net_iface_v0 *)(buf + consumed);
+ fprintf(stdout, "- interface: %s\n", status_net_iface->net_iface);
+ fprintf(stdout, "\t- status: %s\n",
+ status_net_iface->active == 1 ? "active" : "inactive");
+ break;
+ case ALFRED_SERVER_BAT_IFACE:
+ if (tlvsize != sizeof(*status_bat_iface))
+ break;
+
+ status_bat_iface = (struct alfred_server_status_bat_iface_v0 *)(buf + consumed);
+ fprintf(stdout, "- batman-adv interface: %s\n", status_bat_iface->bat_iface);
+ break;
+ }
+
+ consumed += tlvsize;
+ }
+
+err:
+ unix_sock_close(globals);
+ return 0;
+}
diff --git a/main.c b/main.c
index d40a0cc..68d6efd 100644
--- a/main.c
+++ b/main.c
@@ -38,6 +38,7 @@ static void alfred_usage(void)
printf(" secondary switch daemon to mode secondary\n");
printf(" -I, --change-interface [interface] change to the specified interface(s)\n");
printf(" -B, --change-bat-iface [interface] change to the specified batman-adv interface\n");
+ printf(" -S, --server-status request server status info such as mode & interfaces\n");
printf("\n");
printf("server mode options:\n");
printf(" -i, --interface specify the interface (or comma separated list of interfaces) to listen on\n");
@@ -162,6 +163,7 @@ static struct globals *alfred_init(int argc, char *argv[])
{"modeswitch", required_argument, NULL, 'M'},
{"change-interface", required_argument, NULL, 'I'},
{"change-bat-iface", required_argument, NULL, 'B'},
+ {"server-status", required_argument, NULL, 'S'},
{"unix-path", required_argument, NULL, 'u'},
{"update-command", required_argument, NULL, 'c'},
{"version", no_argument, NULL, 'v'},
@@ -196,7 +198,7 @@ static struct globals *alfred_init(int argc, char *argv[])
time_random_seed();
- while ((opt = getopt_long(argc, argv, "ms:r:hi:b:vV:M:I:B:u:dc:p:4:f", long_options,
+ while ((opt = getopt_long(argc, argv, "ms:r:hi:b:vV:M:I:B:Su:dc:p:4:f", long_options,
&opt_ind)) != -1) {
switch (opt) {
case 'r':
@@ -258,6 +260,9 @@ static struct globals *alfred_init(int argc, char *argv[])
globals->clientmode = CLIENT_CHANGE_BAT_IFACE;
globals->mesh_iface = strdup(optarg);
break;
+ case 'S':
+ globals->clientmode = CLIENT_SERVER_STATUS;
+ break;
case 'u':
globals->unix_path = optarg;
break;
@@ -321,6 +326,8 @@ int main(int argc, char *argv[])
return alfred_client_change_interface(globals);
case CLIENT_CHANGE_BAT_IFACE:
return alfred_client_change_bat_iface(globals);
+ case CLIENT_SERVER_STATUS:
+ return alfred_client_server_status(globals);
}
return 0;
diff --git a/man/alfred.8 b/man/alfred.8
index 74814e0..cf0eafc 100644
--- a/man/alfred.8
+++ b/man/alfred.8
@@ -94,6 +94,9 @@ Change the alfred server to use the new \fBinterface\fP(s)
.TP
\fB\-B\fP, \fB\-\-change\-bat\-iface\fP \fIinterface\fP
Change the alfred server to use the new \fBbatman-adv interface\fP
+.TP
+\fB\-S\fP, \fB\-\-server\-status\fP
+Request server status information such as mode & interfaces\fP
.
.SH SERVER OPTIONS
.TP
diff --git a/packet.h b/packet.h
index 94c6a77..0c1a2eb 100644
--- a/packet.h
+++ b/packet.h
@@ -69,6 +69,7 @@ enum alfred_packet_type {
ALFRED_MODESWITCH = 5,
ALFRED_CHANGE_INTERFACE = 6,
ALFRED_CHANGE_BAT_IFACE = 7,
+ ALFRED_SERVER_STATUS = 8,
};
/* packets */
@@ -159,6 +160,73 @@ struct alfred_change_interface_v0 {
struct alfred_change_bat_iface_v0 {
struct alfred_tlv header;
char bat_iface[IFNAMSIZ];
+};
+
+/**
+ * enum alfred_packet_type - Types of packet stored in the main alfred_tlv
+ * @ALFRED_SERVER_MODE: Contains alfred mode information*
+ * @ALFRED_SERVER_NET_IFACE: Contains alfred network interface information*
+ * @ALFRED_SERVER_BAT_IFACE: Contains alfred batman interface information*
+ */
+enum alfred_server_status_type {
+ ALFRED_SERVER_OP_MODE = 0,
+ ALFRED_SERVER_NET_IFACE = 1,
+ ALFRED_SERVER_BAT_IFACE = 2,
+};
+
+/**
+ * struct alfred_server_status_req_v0 - server status request
+ * @header: TLV header describing the complete packet
+ *
+ * Sent to the daemon by client
+ */
+struct alfred_server_status_req_v0 {
+ struct alfred_tlv header;
+} __packed;
+
+/**
+ * struct alfred_server_status_op_mode_v0 - server op mode status information
+ * @op_mode: active op mode
+ *
+ * Sent to the client by daemon in response to status request
+ */
+struct alfred_server_status_op_mode_v0 {
+ struct alfred_tlv header;
+ uint8_t mode;
+} __packed;
+
+/**
+ * struct alfred_server_status_net_iface_v0 - server net iface status information
+ * @net_iface: configured network interface
+ * @active: network interface active/inactive status info
+ *
+ * Sent to the client by daemon in response to status request
+ */
+struct alfred_server_status_net_iface_v0 {
+ struct alfred_tlv header;
+ char net_iface[IFNAMSIZ];
+ uint8_t active;
+} __packed;
+
+/**
+ * struct alfred_server_status_bat_iface_v0 - server bat iface status information
+ * @op_mode: configured batman interface
+ *
+ * Sent to the client by daemon in response to status request
+ */
+struct alfred_server_status_bat_iface_v0 {
+ struct alfred_tlv header;
+ char bat_iface[IFNAMSIZ];
+} __packed;
+
+/**
+ * struct alfred_server_status_rep_v0 - server status reply
+ * @header: TLV header describing the complete packet
+ *
+ * Sent by the daemon to client in response to status request
+ */
+struct alfred_server_status_rep_v0 {
+ struct alfred_tlv header;
} __packed;
/**
diff --git a/unix_sock.c b/unix_sock.c
index bc39199..a5a0196 100644
--- a/unix_sock.c
+++ b/unix_sock.c
@@ -366,6 +366,109 @@ err:
return ret;
}
+static int unix_sock_server_status(struct globals *globals, int client_sock)
+{
+ struct alfred_server_status_net_iface_v0 *status_net_iface;
+ struct alfred_server_status_bat_iface_v0 *status_bat_iface;
+ struct alfred_server_status_op_mode_v0 *status_op_mode;
+ struct alfred_server_status_rep_v0 *status_rep;
+ struct interface *interface;
+ uint8_t buf[MAX_PAYLOAD];
+ int ret = -1;
+ int len = 0;
+
+ /* too large? - should never happen */
+ if (sizeof(*status_rep) + len > sizeof(buf)) {
+ fprintf(stderr, "ERROR: send buffer too small for server_status\n");
+ goto err;
+ }
+
+ status_rep = (struct alfred_server_status_rep_v0 *)buf;
+ status_rep->header.type = ALFRED_SERVER_STATUS;
+ status_rep->header.version = ALFRED_VERSION;
+
+ len += sizeof(*status_rep);
+
+ /* too large? - should never happen */
+ if (sizeof(*status_op_mode) + len > sizeof(buf)) {
+ fprintf(stderr, "ERROR: send buffer too small for server_status op_mode\n");
+ goto err;
+ }
+
+ status_op_mode = (struct alfred_server_status_op_mode_v0 *)(buf + len);
+ status_op_mode->header.type = ALFRED_SERVER_OP_MODE;
+ status_op_mode->header.version = ALFRED_VERSION;
+ status_op_mode->header.length = FIXED_TLV_LEN_PTR(status_op_mode);
+
+ switch (globals->opmode) {
+ case OPMODE_SECONDARY:
+ status_op_mode->mode = ALFRED_MODESWITCH_SECONDARY;
+ break;
+ case OPMODE_PRIMARY:
+ status_op_mode->mode = ALFRED_MODESWITCH_PRIMARY;
+ break;
+ default:
+ break;
+ }
+
+ len += sizeof(*status_op_mode);
+
+ list_for_each_entry(interface, &globals->interfaces, list) {
+ /* too large? - should never happen */
+ if (sizeof(*status_net_iface) + len > sizeof(buf)) {
+ fprintf(stderr, "ERROR: send buffer too small for server_status iface\n");
+ goto err;
+ }
+
+ status_net_iface = (struct alfred_server_status_net_iface_v0 *)(buf + len);
+ status_net_iface->header.type = ALFRED_SERVER_NET_IFACE;
+ status_net_iface->header.version = ALFRED_VERSION;
+ status_net_iface->header.length = FIXED_TLV_LEN_PTR(status_net_iface);
+
+ strncpy(status_net_iface->net_iface, interface->interface,
+ sizeof(status_net_iface->net_iface));
+ status_net_iface->net_iface[sizeof(status_net_iface->net_iface) - 1] = '\0';
+ if (interface->netsock > -1)
+ status_net_iface->active = 1;
+ else
+ status_net_iface->active = 0;
+
+ len += sizeof(*status_net_iface);
+ }
+
+ /* too large? - should never happen */
+ if (sizeof(*status_bat_iface) + len > sizeof(buf)) {
+ fprintf(stderr, "ERROR: send buffer too small for server_status bat_iface\n");
+ goto err;
+ }
+
+ status_bat_iface = (struct alfred_server_status_bat_iface_v0 *)(buf + len);
+ status_bat_iface->header.type = ALFRED_SERVER_BAT_IFACE;
+ status_bat_iface->header.version = ALFRED_VERSION;
+ status_bat_iface->header.length = FIXED_TLV_LEN_PTR(status_bat_iface);
+
+ strncpy(status_bat_iface->bat_iface, globals->mesh_iface,
+ sizeof(status_bat_iface->bat_iface));
+ status_bat_iface->bat_iface[sizeof(status_bat_iface->bat_iface) - 1] = '\0';
+
+ len += sizeof(*status_bat_iface);
+ status_rep->header.length = htons(len - sizeof(status_rep->header));
+
+ ret = write(client_sock, buf, len);
+ if (ret != len) {
+ fprintf(stderr, "%s: only wrote %d of %d bytes: %s\n",
+ __func__, ret, len, strerror(errno));
+ ret = -1;
+ goto err;
+ }
+
+ ret = 0;
+
+err:
+ close(client_sock);
+ return ret;
+}
+
int unix_sock_read(struct globals *globals)
{
int client_sock;
@@ -428,6 +531,9 @@ int unix_sock_read(struct globals *globals)
(struct alfred_change_bat_iface_v0 *)packet,
client_sock);
break;
+ case ALFRED_SERVER_STATUS:
+ ret = unix_sock_server_status(globals, client_sock);
+ break;
default:
/* unknown packet type */
ret = -1;
--
2.32.0.rc0
11 months, 2 weeks
[PATCH v3] alfred: introduce 'server status' IPC call
by Marek Lindner
The 'server status' call exports the 'mode' as well as interface
status via IPC. Both parameters can be modified at runtime via the
IPC and as such, the current configuration is dynamic and not
necessarily obvious.
The server status 'request' and 'reply' packet types are added
to allow the IPC client to initiate the status retrieval. The
server will respond with the 'reply' message.
The information is encapsulated in TLV data chunks allowing for
future backward compatible extension of the server status call.
Signed-off-by: Marek Lindner <mareklindner(a)neomailbox.ch>
---
v3:
- close client socket at the end of unix_sock_server_status()
alfred.h | 2 +
client.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++
main.c | 9 +++-
man/alfred.8 | 3 ++
packet.h | 65 +++++++++++++++++++++++++++++
unix_sock.c | 90 +++++++++++++++++++++++++++++++++++++++
6 files changed, 284 insertions(+), 1 deletion(-)
diff --git a/alfred.h b/alfred.h
index 9ab92a2..3d1d72a 100644
--- a/alfred.h
+++ b/alfred.h
@@ -93,6 +93,7 @@ enum clientmode {
CLIENT_MODESWITCH,
CLIENT_CHANGE_INTERFACE,
CLIENT_CHANGE_BAT_IFACE,
+ CLIENT_SERVER_STATUS,
};
struct interface {
@@ -155,6 +156,7 @@ int alfred_client_set_data(struct globals *globals);
int alfred_client_modeswitch(struct globals *globals);
int alfred_client_change_interface(struct globals *globals);
int alfred_client_change_bat_iface(struct globals *globals);
+int alfred_client_server_status(struct globals *globals);
/* recv.c */
int recv_alfred_packet(struct globals *globals, struct interface *interface,
int recv_sock);
diff --git a/client.c b/client.c
index b5d8943..41ee640 100644
--- a/client.c
+++ b/client.c
@@ -325,3 +325,119 @@ int alfred_client_change_bat_iface(struct globals *globals)
return 0;
}
+
+int alfred_client_server_status(struct globals *globals)
+{
+ struct alfred_server_status_net_iface *status_net_iface;
+ struct alfred_server_status_bat_iface *status_bat_iface;
+ struct alfred_server_status_op_mode *status_op_mode;
+ struct alfred_server_status_req_v0 status_req;
+ struct alfred_server_status_rep_v0 *status_rep;
+ int ret, tlvsize, headsize, len, consumed;
+ struct alfred_tlv *status_tlv;
+ uint8_t buf[MAX_PAYLOAD];
+
+ if (unix_sock_open_client(globals))
+ return -1;
+
+ len = sizeof(status_req);
+ memset(&status_req, 0, len);
+
+ status_req.header.type = ALFRED_SERVER_STATUS;
+ status_req.header.version = ALFRED_VERSION;
+ status_req.header.length = 0;
+
+ ret = write(globals->unix_sock, (unsigned char *)&status_req, len);
+ if (ret != len)
+ fprintf(stderr, "%s: only wrote %d of %d bytes: %s\n",
+ __func__, ret, len, strerror(errno));
+
+ len = read(globals->unix_sock, buf, sizeof(buf));
+ if (len <= 0) {
+ perror("read from unix socket failed");
+ goto err;
+ }
+
+ ret = -1;
+ status_rep = (struct alfred_server_status_rep_v0 *)buf;
+
+ /* drop too small packets */
+ headsize = sizeof(status_rep->header);
+ if (len < headsize) {
+ perror("unexpected header size received from unix socket");
+ goto err;
+ }
+
+ if ((len - headsize) < ((int)ntohs(status_rep->header.length))) {
+ perror("unexpected packet size received from unix socket");
+ goto err;
+ }
+
+ if (status_rep->header.version != ALFRED_VERSION) {
+ perror("alfred version mismatch");
+ goto err;
+ }
+
+ headsize = ntohs(status_rep->header.length);
+
+ if (headsize < (int)(sizeof(*status_rep) - sizeof(status_rep->header)))
+ goto err;
+
+ consumed = sizeof(*status_rep);
+
+ while (len - consumed > 0) {
+ if (len - consumed < (int)sizeof(*status_tlv))
+ break;
+
+ status_tlv = (struct alfred_tlv *)(buf + consumed);
+ consumed += sizeof(*status_tlv);
+
+ tlvsize = ntohs(status_tlv->length);
+ if (len - consumed < tlvsize)
+ break;
+
+ switch (status_tlv->type) {
+ case ALFRED_SERVER_OP_MODE:
+ if (tlvsize != sizeof(*status_op_mode))
+ break;
+
+ status_op_mode = (struct alfred_server_status_op_mode *)(buf + consumed);
+
+ switch (status_op_mode->mode) {
+ case ALFRED_MODESWITCH_SECONDARY:
+ fprintf(stdout, "- mode: secondary\n");
+ break;
+ case ALFRED_MODESWITCH_PRIMARY:
+ fprintf(stdout, "- mode: primary\n");
+ break;
+ default:
+ fprintf(stderr, "- mode: unknown\n");
+ break;
+ }
+
+ break;
+ case ALFRED_SERVER_NET_IFACE:
+ if (tlvsize != sizeof(struct alfred_server_status_net_iface))
+ break;
+
+ status_net_iface = (struct alfred_server_status_net_iface *)(buf + consumed);
+ fprintf(stderr, "- interface: %s\n", status_net_iface->net_iface);
+ fprintf(stderr, "\t- status: %s\n",
+ status_net_iface->active == 1 ? "active" : "inactive");
+ break;
+ case ALFRED_SERVER_BAT_IFACE:
+ if (tlvsize != sizeof(struct alfred_server_status_bat_iface))
+ break;
+
+ status_bat_iface = (struct alfred_server_status_bat_iface *)(buf + consumed);
+ fprintf(stdout, "- batman-adv interface: %s\n", status_bat_iface->bat_iface);
+ break;
+ }
+
+ consumed += tlvsize;
+ }
+
+err:
+ unix_sock_close(globals);
+ return 0;
+}
diff --git a/main.c b/main.c
index d40a0cc..68d6efd 100644
--- a/main.c
+++ b/main.c
@@ -38,6 +38,7 @@ static void alfred_usage(void)
printf(" secondary switch daemon to mode secondary\n");
printf(" -I, --change-interface [interface] change to the specified interface(s)\n");
printf(" -B, --change-bat-iface [interface] change to the specified batman-adv interface\n");
+ printf(" -S, --server-status request server status info such as mode & interfaces\n");
printf("\n");
printf("server mode options:\n");
printf(" -i, --interface specify the interface (or comma separated list of interfaces) to listen on\n");
@@ -162,6 +163,7 @@ static struct globals *alfred_init(int argc, char *argv[])
{"modeswitch", required_argument, NULL, 'M'},
{"change-interface", required_argument, NULL, 'I'},
{"change-bat-iface", required_argument, NULL, 'B'},
+ {"server-status", required_argument, NULL, 'S'},
{"unix-path", required_argument, NULL, 'u'},
{"update-command", required_argument, NULL, 'c'},
{"version", no_argument, NULL, 'v'},
@@ -196,7 +198,7 @@ static struct globals *alfred_init(int argc, char *argv[])
time_random_seed();
- while ((opt = getopt_long(argc, argv, "ms:r:hi:b:vV:M:I:B:u:dc:p:4:f", long_options,
+ while ((opt = getopt_long(argc, argv, "ms:r:hi:b:vV:M:I:B:Su:dc:p:4:f", long_options,
&opt_ind)) != -1) {
switch (opt) {
case 'r':
@@ -258,6 +260,9 @@ static struct globals *alfred_init(int argc, char *argv[])
globals->clientmode = CLIENT_CHANGE_BAT_IFACE;
globals->mesh_iface = strdup(optarg);
break;
+ case 'S':
+ globals->clientmode = CLIENT_SERVER_STATUS;
+ break;
case 'u':
globals->unix_path = optarg;
break;
@@ -321,6 +326,8 @@ int main(int argc, char *argv[])
return alfred_client_change_interface(globals);
case CLIENT_CHANGE_BAT_IFACE:
return alfred_client_change_bat_iface(globals);
+ case CLIENT_SERVER_STATUS:
+ return alfred_client_server_status(globals);
}
return 0;
diff --git a/man/alfred.8 b/man/alfred.8
index 74814e0..cf0eafc 100644
--- a/man/alfred.8
+++ b/man/alfred.8
@@ -94,6 +94,9 @@ Change the alfred server to use the new \fBinterface\fP(s)
.TP
\fB\-B\fP, \fB\-\-change\-bat\-iface\fP \fIinterface\fP
Change the alfred server to use the new \fBbatman-adv interface\fP
+.TP
+\fB\-S\fP, \fB\-\-server\-status\fP
+Request server status information such as mode & interfaces\fP
.
.SH SERVER OPTIONS
.TP
diff --git a/packet.h b/packet.h
index 94c6a77..4b6bde5 100644
--- a/packet.h
+++ b/packet.h
@@ -69,6 +69,7 @@ enum alfred_packet_type {
ALFRED_MODESWITCH = 5,
ALFRED_CHANGE_INTERFACE = 6,
ALFRED_CHANGE_BAT_IFACE = 7,
+ ALFRED_SERVER_STATUS = 8,
};
/* packets */
@@ -159,6 +160,70 @@ struct alfred_change_interface_v0 {
struct alfred_change_bat_iface_v0 {
struct alfred_tlv header;
char bat_iface[IFNAMSIZ];
+};
+
+/**
+ * enum alfred_packet_type - Types of packet stored in the main alfred_tlv
+ * @ALFRED_SERVER_MODE: Contains alfred mode information*
+ * @ALFRED_SERVER_NET_IFACE: Contains alfred network interface information*
+ * @ALFRED_SERVER_BAT_IFACE: Contains alfred batman interface information*
+ */
+enum alfred_server_status_type {
+ ALFRED_SERVER_OP_MODE = 0,
+ ALFRED_SERVER_NET_IFACE = 1,
+ ALFRED_SERVER_BAT_IFACE = 2,
+};
+
+/**
+ * struct alfred_server_status_req_v0 - server status request
+ * @header: TLV header describing the complete packet
+ *
+ * Sent to the daemon by client
+ */
+struct alfred_server_status_req_v0 {
+ struct alfred_tlv header;
+} __packed;
+
+/**
+ * struct alfred_server_status_op_mode - server op mode status information
+ * @op_mode: active op mode
+ *
+ * Sent to the client by daemon in response to status request
+ */
+struct alfred_server_status_op_mode {
+ uint8_t mode;
+} __packed;
+
+/**
+ * struct alfred_server_status_net_iface - server net iface status information
+ * @net_iface: configured network interface
+ * @active: network interface active/inactive status info
+ *
+ * Sent to the client by daemon in response to status request
+ */
+struct alfred_server_status_net_iface {
+ char net_iface[IFNAMSIZ];
+ uint8_t active;
+} __packed;
+
+/**
+ * struct alfred_server_status_bat_iface - server bat iface status information
+ * @op_mode: configured batman interface
+ *
+ * Sent to the client by daemon in response to status request
+ */
+struct alfred_server_status_bat_iface {
+ char bat_iface[IFNAMSIZ];
+} __packed;
+
+/**
+ * struct alfred_server_status_rep_v0 - server status reply
+ * @header: TLV header describing the complete packet
+ *
+ * Sent by the daemon to client in response to status request
+ */
+struct alfred_server_status_rep_v0 {
+ struct alfred_tlv header;
} __packed;
/**
diff --git a/unix_sock.c b/unix_sock.c
index bc39199..9d4b1ca 100644
--- a/unix_sock.c
+++ b/unix_sock.c
@@ -366,6 +366,93 @@ err:
return ret;
}
+static int unix_sock_server_status(struct globals *globals, int client_sock)
+{
+ struct alfred_server_status_net_iface *status_net_iface;
+ struct alfred_server_status_bat_iface *status_bat_iface;
+ struct alfred_server_status_op_mode *status_op_mode;
+ struct alfred_server_status_rep_v0 *status_rep;
+ struct alfred_tlv *status_tlv;
+ struct interface *interface;
+ uint8_t buf[MAX_PAYLOAD];
+ int ret, len;
+
+ len = sizeof(*status_rep);
+
+ status_rep = (struct alfred_server_status_rep_v0 *)buf;
+ status_rep->header.type = ALFRED_SERVER_STATUS;
+ status_rep->header.version = ALFRED_VERSION;
+ status_rep->header.length = len;
+
+ status_tlv = (struct alfred_tlv *)(buf + len);
+ status_tlv->type = ALFRED_SERVER_OP_MODE;
+ status_tlv->version = ALFRED_VERSION;
+ status_tlv->length = htons(sizeof(*status_op_mode));
+ len += sizeof(*status_tlv);
+
+ status_op_mode = (struct alfred_server_status_op_mode *)(buf + len);
+
+ switch (globals->opmode) {
+ case OPMODE_SECONDARY:
+ status_op_mode->mode = ALFRED_MODESWITCH_SECONDARY;
+ break;
+ case OPMODE_PRIMARY:
+ status_op_mode->mode = ALFRED_MODESWITCH_PRIMARY;
+ break;
+ default:
+ break;
+ }
+
+ len += sizeof(*status_op_mode);
+
+ list_for_each_entry(interface, &globals->interfaces, list) {
+ status_tlv = (struct alfred_tlv *)(buf + len);
+ status_tlv->type = ALFRED_SERVER_NET_IFACE;
+ status_tlv->version = ALFRED_VERSION;
+ status_tlv->length = htons(sizeof(*status_net_iface));
+ len += sizeof(*status_tlv);
+
+ status_net_iface = (struct alfred_server_status_net_iface *)(buf + len);
+ strncpy(status_net_iface->net_iface, interface->interface,
+ sizeof(status_net_iface->net_iface));
+ status_net_iface->net_iface[sizeof(status_net_iface->net_iface) - 1] = '\0';
+ if (interface->netsock > -1)
+ status_net_iface->active = 1;
+ else
+ status_net_iface->active = 0;
+ len += sizeof(*status_net_iface);
+ }
+
+ status_tlv = (struct alfred_tlv *)(buf + len);
+ status_tlv->type = ALFRED_SERVER_BAT_IFACE;
+ status_tlv->version = ALFRED_VERSION;
+ status_tlv->length = htons(sizeof(*status_bat_iface));
+ len += sizeof(*status_tlv);
+
+ status_bat_iface = (struct alfred_server_status_bat_iface *)(buf + len);
+ strncpy(status_bat_iface->bat_iface, globals->mesh_iface,
+ sizeof(status_bat_iface->bat_iface));
+ status_bat_iface->bat_iface[sizeof(status_bat_iface->bat_iface) - 1] = '\0';
+ len += sizeof(*status_bat_iface);
+
+ status_rep->header.length = htons(len - sizeof(status_rep->header));
+
+ ret = write(client_sock, buf, len);
+
+ if (ret != len) {
+ fprintf(stderr, "%s: only wrote %d of %d bytes: %s\n",
+ __func__, ret, len, strerror(errno));
+ ret = -1;
+ goto err;
+ }
+
+ ret = 0;
+
+err:
+ close(client_sock);
+ return ret;
+}
+
int unix_sock_read(struct globals *globals)
{
int client_sock;
@@ -428,6 +515,9 @@ int unix_sock_read(struct globals *globals)
(struct alfred_change_bat_iface_v0 *)packet,
client_sock);
break;
+ case ALFRED_SERVER_STATUS:
+ ret = unix_sock_server_status(globals, client_sock);
+ break;
default:
/* unknown packet type */
ret = -1;
--
2.32.0.rc0
11 months, 2 weeks
[PATCH] alfred: Ensure processed change_iface packet is 0-terminated
by Sven Eckelmann
A client sending a alfred_change_interface_v0 packet to the alfred server
might have forgotten to 0-terminate the string. In this case, strstr in
unix_sock_change_iface might read outside of the available buffer.
Signed-off-by: Sven Eckelmann <sven(a)narfation.org>
---
unix_sock.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/unix_sock.c b/unix_sock.c
index bc39199..8c2b762 100644
--- a/unix_sock.c
+++ b/unix_sock.c
@@ -329,6 +329,8 @@ unix_sock_change_iface(struct globals *globals,
if (len < (int)(sizeof(*change_iface) - sizeof(change_iface->header)))
goto err;
+ change_iface->ifaces[sizeof(change_iface->ifaces) - 1] = '\0';
+
if (globals->opmode == OPMODE_SECONDARY) {
if (strstr(change_iface->ifaces, ",") != NULL) {
ret = -EINVAL;
--
2.30.2
11 months, 2 weeks
[RFC] batman-adv: make mc_forwarding atomic
by Sven Eckelmann
From: Eric Dumazet <edumazet(a)google.com>
This fixes minor data-races in ip6_mc_input() and
batadv_mcast_mla_rtr_flags_softif_get_ipv6()
Signed-off-by: Eric Dumazet <edumazet(a)google.com>
Signed-off-by: David S. Miller <davem(a)davemloft.net>
---
net-next commit 145c7a793838 ("ipv6: make mc_forwarding atomic")
This still needs compat code - does anyone have ideas?
net/batman-adv/multicast.c | 2 +-
5 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c
index f4004cf0ff6f..9f311fddfaf9 100644
--- a/net/batman-adv/multicast.c
+++ b/net/batman-adv/multicast.c
@@ -134,7 +134,7 @@ static u8 batadv_mcast_mla_rtr_flags_softif_get_ipv6(struct net_device *dev)
{
struct inet6_dev *in6_dev = __in6_dev_get(dev);
- if (in6_dev && in6_dev->cnf.mc_forwarding)
+ if (in6_dev && atomic_read(&in6_dev->cnf.mc_forwarding))
return BATADV_NO_FLAGS;
else
return BATADV_MCAST_WANT_NO_RTR6;
--
2.30.2
11 months, 4 weeks
[PATCH v2] alfred: introduce 'server status' IPC call
by Marek Lindner
The 'server status' call exports the 'mode' as well as interface
status via IPC. Both parameters can be modified at runtime via the
IPC and as such, the current configuration is dynamic and not
necessarily obvious.
The server status 'request' and 'reply' packet types are added
to allow the IPC client to initiate the status retrieval. The
server will respond with the 'reply' message.
The information is encapsulated in TLV data chunks allowing for
future backward compatible extension of the server status call.
Signed-off-by: Marek Lindner <mareklindner(a)neomailbox.ch>
---
alfred.h | 2 +
client.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++
main.c | 9 +++-
man/alfred.8 | 3 ++
packet.h | 65 +++++++++++++++++++++++++++++
unix_sock.c | 83 ++++++++++++++++++++++++++++++++++++
6 files changed, 277 insertions(+), 1 deletion(-)
diff --git a/alfred.h b/alfred.h
index 9ab92a2..3d1d72a 100644
--- a/alfred.h
+++ b/alfred.h
@@ -93,6 +93,7 @@ enum clientmode {
CLIENT_MODESWITCH,
CLIENT_CHANGE_INTERFACE,
CLIENT_CHANGE_BAT_IFACE,
+ CLIENT_SERVER_STATUS,
};
struct interface {
@@ -155,6 +156,7 @@ int alfred_client_set_data(struct globals *globals);
int alfred_client_modeswitch(struct globals *globals);
int alfred_client_change_interface(struct globals *globals);
int alfred_client_change_bat_iface(struct globals *globals);
+int alfred_client_server_status(struct globals *globals);
/* recv.c */
int recv_alfred_packet(struct globals *globals, struct interface *interface,
int recv_sock);
diff --git a/client.c b/client.c
index b5d8943..41ee640 100644
--- a/client.c
+++ b/client.c
@@ -325,3 +325,119 @@ int alfred_client_change_bat_iface(struct globals *globals)
return 0;
}
+
+int alfred_client_server_status(struct globals *globals)
+{
+ struct alfred_server_status_net_iface *status_net_iface;
+ struct alfred_server_status_bat_iface *status_bat_iface;
+ struct alfred_server_status_op_mode *status_op_mode;
+ struct alfred_server_status_req_v0 status_req;
+ struct alfred_server_status_rep_v0 *status_rep;
+ int ret, tlvsize, headsize, len, consumed;
+ struct alfred_tlv *status_tlv;
+ uint8_t buf[MAX_PAYLOAD];
+
+ if (unix_sock_open_client(globals))
+ return -1;
+
+ len = sizeof(status_req);
+ memset(&status_req, 0, len);
+
+ status_req.header.type = ALFRED_SERVER_STATUS;
+ status_req.header.version = ALFRED_VERSION;
+ status_req.header.length = 0;
+
+ ret = write(globals->unix_sock, (unsigned char *)&status_req, len);
+ if (ret != len)
+ fprintf(stderr, "%s: only wrote %d of %d bytes: %s\n",
+ __func__, ret, len, strerror(errno));
+
+ len = read(globals->unix_sock, buf, sizeof(buf));
+ if (len <= 0) {
+ perror("read from unix socket failed");
+ goto err;
+ }
+
+ ret = -1;
+ status_rep = (struct alfred_server_status_rep_v0 *)buf;
+
+ /* drop too small packets */
+ headsize = sizeof(status_rep->header);
+ if (len < headsize) {
+ perror("unexpected header size received from unix socket");
+ goto err;
+ }
+
+ if ((len - headsize) < ((int)ntohs(status_rep->header.length))) {
+ perror("unexpected packet size received from unix socket");
+ goto err;
+ }
+
+ if (status_rep->header.version != ALFRED_VERSION) {
+ perror("alfred version mismatch");
+ goto err;
+ }
+
+ headsize = ntohs(status_rep->header.length);
+
+ if (headsize < (int)(sizeof(*status_rep) - sizeof(status_rep->header)))
+ goto err;
+
+ consumed = sizeof(*status_rep);
+
+ while (len - consumed > 0) {
+ if (len - consumed < (int)sizeof(*status_tlv))
+ break;
+
+ status_tlv = (struct alfred_tlv *)(buf + consumed);
+ consumed += sizeof(*status_tlv);
+
+ tlvsize = ntohs(status_tlv->length);
+ if (len - consumed < tlvsize)
+ break;
+
+ switch (status_tlv->type) {
+ case ALFRED_SERVER_OP_MODE:
+ if (tlvsize != sizeof(*status_op_mode))
+ break;
+
+ status_op_mode = (struct alfred_server_status_op_mode *)(buf + consumed);
+
+ switch (status_op_mode->mode) {
+ case ALFRED_MODESWITCH_SECONDARY:
+ fprintf(stdout, "- mode: secondary\n");
+ break;
+ case ALFRED_MODESWITCH_PRIMARY:
+ fprintf(stdout, "- mode: primary\n");
+ break;
+ default:
+ fprintf(stderr, "- mode: unknown\n");
+ break;
+ }
+
+ break;
+ case ALFRED_SERVER_NET_IFACE:
+ if (tlvsize != sizeof(struct alfred_server_status_net_iface))
+ break;
+
+ status_net_iface = (struct alfred_server_status_net_iface *)(buf + consumed);
+ fprintf(stderr, "- interface: %s\n", status_net_iface->net_iface);
+ fprintf(stderr, "\t- status: %s\n",
+ status_net_iface->active == 1 ? "active" : "inactive");
+ break;
+ case ALFRED_SERVER_BAT_IFACE:
+ if (tlvsize != sizeof(struct alfred_server_status_bat_iface))
+ break;
+
+ status_bat_iface = (struct alfred_server_status_bat_iface *)(buf + consumed);
+ fprintf(stdout, "- batman-adv interface: %s\n", status_bat_iface->bat_iface);
+ break;
+ }
+
+ consumed += tlvsize;
+ }
+
+err:
+ unix_sock_close(globals);
+ return 0;
+}
diff --git a/main.c b/main.c
index d40a0cc..68d6efd 100644
--- a/main.c
+++ b/main.c
@@ -38,6 +38,7 @@ static void alfred_usage(void)
printf(" secondary switch daemon to mode secondary\n");
printf(" -I, --change-interface [interface] change to the specified interface(s)\n");
printf(" -B, --change-bat-iface [interface] change to the specified batman-adv interface\n");
+ printf(" -S, --server-status request server status info such as mode & interfaces\n");
printf("\n");
printf("server mode options:\n");
printf(" -i, --interface specify the interface (or comma separated list of interfaces) to listen on\n");
@@ -162,6 +163,7 @@ static struct globals *alfred_init(int argc, char *argv[])
{"modeswitch", required_argument, NULL, 'M'},
{"change-interface", required_argument, NULL, 'I'},
{"change-bat-iface", required_argument, NULL, 'B'},
+ {"server-status", required_argument, NULL, 'S'},
{"unix-path", required_argument, NULL, 'u'},
{"update-command", required_argument, NULL, 'c'},
{"version", no_argument, NULL, 'v'},
@@ -196,7 +198,7 @@ static struct globals *alfred_init(int argc, char *argv[])
time_random_seed();
- while ((opt = getopt_long(argc, argv, "ms:r:hi:b:vV:M:I:B:u:dc:p:4:f", long_options,
+ while ((opt = getopt_long(argc, argv, "ms:r:hi:b:vV:M:I:B:Su:dc:p:4:f", long_options,
&opt_ind)) != -1) {
switch (opt) {
case 'r':
@@ -258,6 +260,9 @@ static struct globals *alfred_init(int argc, char *argv[])
globals->clientmode = CLIENT_CHANGE_BAT_IFACE;
globals->mesh_iface = strdup(optarg);
break;
+ case 'S':
+ globals->clientmode = CLIENT_SERVER_STATUS;
+ break;
case 'u':
globals->unix_path = optarg;
break;
@@ -321,6 +326,8 @@ int main(int argc, char *argv[])
return alfred_client_change_interface(globals);
case CLIENT_CHANGE_BAT_IFACE:
return alfred_client_change_bat_iface(globals);
+ case CLIENT_SERVER_STATUS:
+ return alfred_client_server_status(globals);
}
return 0;
diff --git a/man/alfred.8 b/man/alfred.8
index 74814e0..cf0eafc 100644
--- a/man/alfred.8
+++ b/man/alfred.8
@@ -94,6 +94,9 @@ Change the alfred server to use the new \fBinterface\fP(s)
.TP
\fB\-B\fP, \fB\-\-change\-bat\-iface\fP \fIinterface\fP
Change the alfred server to use the new \fBbatman-adv interface\fP
+.TP
+\fB\-S\fP, \fB\-\-server\-status\fP
+Request server status information such as mode & interfaces\fP
.
.SH SERVER OPTIONS
.TP
diff --git a/packet.h b/packet.h
index 94c6a77..4b6bde5 100644
--- a/packet.h
+++ b/packet.h
@@ -69,6 +69,7 @@ enum alfred_packet_type {
ALFRED_MODESWITCH = 5,
ALFRED_CHANGE_INTERFACE = 6,
ALFRED_CHANGE_BAT_IFACE = 7,
+ ALFRED_SERVER_STATUS = 8,
};
/* packets */
@@ -159,6 +160,70 @@ struct alfred_change_interface_v0 {
struct alfred_change_bat_iface_v0 {
struct alfred_tlv header;
char bat_iface[IFNAMSIZ];
+};
+
+/**
+ * enum alfred_packet_type - Types of packet stored in the main alfred_tlv
+ * @ALFRED_SERVER_MODE: Contains alfred mode information*
+ * @ALFRED_SERVER_NET_IFACE: Contains alfred network interface information*
+ * @ALFRED_SERVER_BAT_IFACE: Contains alfred batman interface information*
+ */
+enum alfred_server_status_type {
+ ALFRED_SERVER_OP_MODE = 0,
+ ALFRED_SERVER_NET_IFACE = 1,
+ ALFRED_SERVER_BAT_IFACE = 2,
+};
+
+/**
+ * struct alfred_server_status_req_v0 - server status request
+ * @header: TLV header describing the complete packet
+ *
+ * Sent to the daemon by client
+ */
+struct alfred_server_status_req_v0 {
+ struct alfred_tlv header;
+} __packed;
+
+/**
+ * struct alfred_server_status_op_mode - server op mode status information
+ * @op_mode: active op mode
+ *
+ * Sent to the client by daemon in response to status request
+ */
+struct alfred_server_status_op_mode {
+ uint8_t mode;
+} __packed;
+
+/**
+ * struct alfred_server_status_net_iface - server net iface status information
+ * @net_iface: configured network interface
+ * @active: network interface active/inactive status info
+ *
+ * Sent to the client by daemon in response to status request
+ */
+struct alfred_server_status_net_iface {
+ char net_iface[IFNAMSIZ];
+ uint8_t active;
+} __packed;
+
+/**
+ * struct alfred_server_status_bat_iface - server bat iface status information
+ * @op_mode: configured batman interface
+ *
+ * Sent to the client by daemon in response to status request
+ */
+struct alfred_server_status_bat_iface {
+ char bat_iface[IFNAMSIZ];
+} __packed;
+
+/**
+ * struct alfred_server_status_rep_v0 - server status reply
+ * @header: TLV header describing the complete packet
+ *
+ * Sent by the daemon to client in response to status request
+ */
+struct alfred_server_status_rep_v0 {
+ struct alfred_tlv header;
} __packed;
/**
diff --git a/unix_sock.c b/unix_sock.c
index bc39199..2e113df 100644
--- a/unix_sock.c
+++ b/unix_sock.c
@@ -366,6 +366,86 @@ err:
return ret;
}
+static int unix_sock_server_status(struct globals *globals, int client_sock)
+{
+ struct alfred_server_status_net_iface *status_net_iface;
+ struct alfred_server_status_bat_iface *status_bat_iface;
+ struct alfred_server_status_op_mode *status_op_mode;
+ struct alfred_server_status_rep_v0 *status_rep;
+ struct alfred_tlv *status_tlv;
+ struct interface *interface;
+ uint8_t buf[MAX_PAYLOAD];
+ int ret, len;
+
+ len = sizeof(*status_rep);
+
+ status_rep = (struct alfred_server_status_rep_v0 *)buf;
+ status_rep->header.type = ALFRED_SERVER_STATUS;
+ status_rep->header.version = ALFRED_VERSION;
+ status_rep->header.length = len;
+
+ status_tlv = (struct alfred_tlv *)(buf + len);
+ status_tlv->type = ALFRED_SERVER_OP_MODE;
+ status_tlv->version = ALFRED_VERSION;
+ status_tlv->length = htons(sizeof(*status_op_mode));
+ len += sizeof(*status_tlv);
+
+ status_op_mode = (struct alfred_server_status_op_mode *)(buf + len);
+
+ switch (globals->opmode) {
+ case OPMODE_SECONDARY:
+ status_op_mode->mode = ALFRED_MODESWITCH_SECONDARY;
+ break;
+ case OPMODE_PRIMARY:
+ status_op_mode->mode = ALFRED_MODESWITCH_PRIMARY;
+ break;
+ default:
+ break;
+ }
+
+ len += sizeof(*status_op_mode);
+
+ list_for_each_entry(interface, &globals->interfaces, list) {
+ status_tlv = (struct alfred_tlv *)(buf + len);
+ status_tlv->type = ALFRED_SERVER_NET_IFACE;
+ status_tlv->version = ALFRED_VERSION;
+ status_tlv->length = htons(sizeof(*status_net_iface));
+ len += sizeof(*status_tlv);
+
+ status_net_iface = (struct alfred_server_status_net_iface *)(buf + len);
+ strncpy(status_net_iface->net_iface, interface->interface,
+ sizeof(status_net_iface->net_iface));
+ status_net_iface->net_iface[sizeof(status_net_iface->net_iface) - 1] = '\0';
+ if (interface->netsock > -1)
+ status_net_iface->active = 1;
+ else
+ status_net_iface->active = 0;
+ len += sizeof(*status_net_iface);
+ }
+
+ status_tlv = (struct alfred_tlv *)(buf + len);
+ status_tlv->type = ALFRED_SERVER_BAT_IFACE;
+ status_tlv->version = ALFRED_VERSION;
+ status_tlv->length = htons(sizeof(*status_bat_iface));
+ len += sizeof(*status_tlv);
+
+ status_bat_iface = (struct alfred_server_status_bat_iface *)(buf + len);
+ strncpy(status_bat_iface->bat_iface, globals->mesh_iface,
+ sizeof(status_bat_iface->bat_iface));
+ status_bat_iface->bat_iface[sizeof(status_bat_iface->bat_iface) - 1] = '\0';
+ len += sizeof(*status_bat_iface);
+
+ status_rep->header.length = htons(len - sizeof(status_rep->header));
+
+ ret = write(client_sock, buf, len);
+ if (ret == len)
+ return 0;
+
+ fprintf(stderr, "%s: only wrote %d of %d bytes: %s\n",
+ __func__, ret, len, strerror(errno));
+ return -1;
+}
+
int unix_sock_read(struct globals *globals)
{
int client_sock;
@@ -428,6 +508,9 @@ int unix_sock_read(struct globals *globals)
(struct alfred_change_bat_iface_v0 *)packet,
client_sock);
break;
+ case ALFRED_SERVER_STATUS:
+ ret = unix_sock_server_status(globals, client_sock);
+ break;
default:
/* unknown packet type */
ret = -1;
--
2.32.0.rc0
12 months