2 protocol.c -- handle the meta-protocol, basic functions
3 Copyright (C) 2014-2017 Guus Sliepen <guus@meshlink.io>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "connection.h"
25 #include "meshlink_internal.h"
31 /* Jumptable for the request handlers */
33 static bool (*request_handlers[NUM_REQUESTS])(meshlink_handle_t *, connection_t *, const char *) = {
38 [TERMREQ] = termreq_h,
41 [ADD_EDGE] = add_edge_h,
42 [DEL_EDGE] = del_edge_h,
43 [KEY_CHANGED] = key_changed_h,
44 [REQ_KEY] = req_key_h,
45 [ANS_KEY] = ans_key_h,
46 [PACKET] = raw_packet_h,
51 static const char *request_name[NUM_REQUESTS] __attribute__((unused)) = {
56 [TERMREQ] = "TERMREQ",
59 [ADD_EDGE] = "ADD_EDGE",
60 [DEL_EDGE] = "DEL_EDGE",
61 [KEY_CHANGED] = "KEY_CHANGED",
62 [REQ_KEY] = "REQ_KEY",
63 [ANS_KEY] = "ANS_KEY",
67 bool check_id(const char *id) {
73 if(!isalnum(*id) && *id != '_' && *id != '-') {
80 /* Generic request routines - takes care of logging and error
83 bool send_request(meshlink_handle_t *mesh, connection_t *c, const char *format, ...) {
88 logger(mesh, MESHLINK_ERROR, "Trying to send request to non-existing connection");
93 char request[MAXBUFSIZE];
96 /* Use vsnprintf instead of vxasprintf: faster, no memory
97 fragmentation, cleanup is automatic, and there is a limit on the
98 input buffer anyway */
100 va_start(args, format);
101 len = vsnprintf(request, MAXBUFSIZE, format, args);
104 if(len < 0 || len > MAXBUFSIZE - 1) {
105 logger(mesh, MESHLINK_ERROR, "Output buffer overflow while sending request to %s", c->name);
109 logger(mesh, MESHLINK_DEBUG, "Sending %s to %s: %s", request_name[atoi(request)], c->name, request);
111 request[len++] = '\n';
113 if(c == mesh->everyone) {
114 broadcast_meta(mesh, NULL, request, len);
117 return send_meta(mesh, c, request, len);
121 bool receive_request(meshlink_handle_t *mesh, connection_t *c, const char *request) {
124 int reqno = atoi(request);
126 if(reqno || *request == '0') {
127 if((reqno < 0) || (reqno >= NUM_REQUESTS) || !request_handlers[reqno]) {
128 logger(mesh, MESHLINK_DEBUG, "Unknown request from %s: %s", c->name, request);
131 logger(mesh, MESHLINK_DEBUG, "Got %s from %s: %s", request_name[reqno], c->name, request);
134 if((c->allow_request != ALL) && (c->allow_request != reqno) && (reqno != ERROR)) {
135 logger(mesh, MESHLINK_ERROR, "Unauthorized request from %s", c->name);
139 if(!request_handlers[reqno](mesh, c, request)) {
140 /* Something went wrong. Probably scriptkiddies. Terminate. */
142 logger(mesh, MESHLINK_ERROR, "Error while processing %s from %s", request_name[reqno], c->name);
146 logger(mesh, MESHLINK_ERROR, "Bogus data received from %s", c->name);