@@ -90,6 +90,7 @@ enum clientmode {
CLIENT_MODESWITCH,
CLIENT_CHANGE_INTERFACE,
CLIENT_CHANGE_BAT_IFACE,
+ CLIENT_SERVER_STATUS,
};
struct interface {
@@ -152,6 +153,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);
@@ -333,3 +333,90 @@ int alfred_client_change_bat_iface(struct globals *globals)
return 0;
}
+
+int alfred_client_server_status(struct globals *globals)
+{
+ unsigned char buf[MAX_PAYLOAD];
+ struct alfred_server_status_req_v0 *status_req;
+ struct alfred_server_status_rep_v0 *status_rep;
+ struct alfred_tlv *packet;
+ int ret, len, headsize, i;
+
+ if (unix_sock_open_client(globals))
+ return -1;
+
+ status_req = (struct alfred_server_status_req_v0 *)buf;
+ len = sizeof(*status_req);
+
+ status_req->header.type = ALFRED_SERVER_STATUS;
+ status_req->header.version = ALFRED_VERSION;
+ status_req->header.length = 0;
+
+ ret = write(globals->unix_sock, buf, 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;
+
+ /* drop too small packets */
+ headsize = sizeof(*packet);
+ if (len < headsize) {
+ perror("unexpected header size received from unix socket");
+ goto err;
+ }
+
+ packet = (struct alfred_tlv *)buf;
+
+ if ((len - headsize) < ((int)ntohs(packet->length))) {
+ perror("unexpected packet size received from unix socket");
+ goto err;
+ }
+
+ if (packet->version != ALFRED_VERSION) {
+ perror("alfred version mismatch");
+ goto err;
+ }
+
+ status_rep = (struct alfred_server_status_rep_v0 *)buf;
+ headsize = ntohs(status_rep->header.length);
+
+ if (headsize < (int)(sizeof(*status_rep) - sizeof(status_rep->header)))
+ goto err;
+
+ fprintf(stdout, "alfred status:\n");
+
+ switch (status_rep->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;
+ }
+
+ fprintf(stderr, "- interfaces:\n");
+
+ for (i = 0; i < 16; i++) {
+ if (strlen(status_rep->ifaces[i].name) == 0)
+ continue;
+
+ fprintf(stderr, "\t- name: %s\n",
+ status_rep->ifaces[i].name);
+ }
+
+ fprintf(stdout, "- batman-adv interface: %s\n", status_rep->bat_iface);
+
+err:
+ unix_sock_close(globals);
+ return 0;
+}
@@ -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;
@@ -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
@@ -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,31 @@ struct alfred_change_interface_v0 {
struct alfred_change_bat_iface_v0 {
struct alfred_tlv header;
char bat_iface[IFNAMSIZ];
+};
+
+/**
+ * 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_req_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;
+ uint8_t mode;
+ struct {
+ char name[IFNAMSIZ];
+ } ifaces[16];
+ char bat_iface[IFNAMSIZ];
} __packed;
/**
@@ -366,6 +366,53 @@ err:
return ret;
}
+static int unix_sock_server_status(struct globals *globals, int client_sock)
+{
+ unsigned char buf[MAX_PAYLOAD];
+ struct alfred_server_status_rep_v0 *status_rep;
+ struct interface *interface;
+ int ret, len, iface_count;
+
+ status_rep = (struct alfred_server_status_rep_v0 *)buf;
+ len = sizeof(*status_rep);
+
+ status_rep->header.type = ALFRED_SERVER_STATUS;
+ status_rep->header.version = ALFRED_VERSION;
+ status_rep->header.length = htons(len - sizeof(status_rep->header));
+
+ switch (globals->opmode) {
+ case OPMODE_SECONDARY:
+ status_rep->mode = ALFRED_MODESWITCH_SECONDARY;
+ break;
+ case OPMODE_PRIMARY:
+ status_rep->mode = ALFRED_MODESWITCH_PRIMARY;
+ break;
+ default:
+ break;
+ }
+
+ iface_count = 0;
+
+ list_for_each_entry(interface, &globals->interfaces, list) {
+ strncpy(status_rep->ifaces[iface_count].name,
+ interface->interface,
+ sizeof(status_rep->ifaces[iface_count].name));
+
+ iface_count++;
+ }
+
+ strncpy(status_rep->bat_iface, globals->mesh_iface,
+ sizeof(status_rep->bat_iface));
+
+ 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 +475,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;