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,
50 static const char *request_name[NUM_REQUESTS] __attribute__((unused)) = {
55 [TERMREQ] = "TERMREQ",
58 [ADD_EDGE] = "ADD_EDGE",
59 [DEL_EDGE] = "DEL_EDGE",
60 [KEY_CHANGED] = "KEY_CHANGED",
61 [REQ_KEY] = "REQ_KEY",
62 [ANS_KEY] = "ANS_KEY",
65 bool check_id(const char *id) {
71 if(!isalnum(*id) && *id != '_' && *id != '-') {
78 /* Generic request routines - takes care of logging and error
81 bool send_request(meshlink_handle_t *mesh, connection_t *c, const char *format, ...) {
86 logger(mesh, MESHLINK_ERROR, "Trying to send request to non-existing connection");
91 char request[MAXBUFSIZE];
94 /* Use vsnprintf instead of vxasprintf: faster, no memory
95 fragmentation, cleanup is automatic, and there is a limit on the
96 input buffer anyway */
98 va_start(args, format);
99 len = vsnprintf(request, MAXBUFSIZE, format, args);
102 if(len < 0 || len > MAXBUFSIZE - 1) {
103 logger(mesh, MESHLINK_ERROR, "Output buffer overflow while sending request to %s", c->name);
107 logger(mesh, MESHLINK_DEBUG, "Sending %s to %s: %s", request_name[atoi(request)], c->name, request);
109 request[len++] = '\n';
111 if(c == mesh->everyone) {
112 broadcast_meta(mesh, NULL, request, len);
115 return send_meta(mesh, c, request, len);
119 bool receive_request(meshlink_handle_t *mesh, connection_t *c, const char *request) {
122 int reqno = atoi(request);
124 if(reqno || *request == '0') {
125 if((reqno < 0) || (reqno >= NUM_REQUESTS) || !request_handlers[reqno]) {
126 logger(mesh, MESHLINK_DEBUG, "Unknown request from %s: %s", c->name, request);
129 logger(mesh, MESHLINK_DEBUG, "Got %s from %s: %s", request_name[reqno], c->name, request);
132 if((c->allow_request != ALL) && (c->allow_request != reqno) && (reqno != ERROR)) {
133 logger(mesh, MESHLINK_ERROR, "Unauthorized request from %s", c->name);
137 if(!request_handlers[reqno](mesh, c, request)) {
138 /* Something went wrong. Probably scriptkiddies. Terminate. */
140 logger(mesh, MESHLINK_ERROR, "Error while processing %s from %s", request_name[reqno], c->name);
144 logger(mesh, MESHLINK_ERROR, "Bogus data received from %s", c->name);