18155e94200606053c02edaa9b5d6a0f7734e039
[tinc] / src / protocol_misc.c
1 /*
2     protocol_misc.c -- handle the meta-protocol, miscellaneous functions
3     Copyright (C) 1999-2002 Ivo Timmermans <ivo@o2w.nl>,
4                   2000-2002 Guus Sliepen <guus@sliepen.eu.org>
5
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
20     $Id: protocol_misc.c,v 1.1.4.9 2003/07/06 23:16:29 guus Exp $
21 */
22
23 #include "config.h"
24
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include <stdarg.h>
29 #include <errno.h>
30
31 #include <utils.h>
32
33 #include "conf.h"
34 #include "net.h"
35 #include "netutl.h"
36 #include "protocol.h"
37 #include "meta.h"
38 #include "connection.h"
39 #include "logger.h"
40
41 #include "system.h"
42
43 /* Status strings */
44
45 static char (*status_text[]) = {
46         "Warning",
47 };
48
49 /* Error strings */
50
51 static char (*error_text[]) = {
52         "Error",
53 };
54
55 /* Status and error notification routines */
56
57 int send_status(connection_t *c, int statusno, char *statusstring)
58 {
59         cp();
60
61         if(!statusstring)
62                 statusstring = status_text[statusno];
63
64         return send_request(c, "%d %d %s", STATUS, statusno, statusstring);
65 }
66
67 int status_h(connection_t *c)
68 {
69         int statusno;
70         char statusstring[MAX_STRING_SIZE];
71
72         cp();
73
74         if(sscanf(c->buffer, "%*d %d " MAX_STRING, &statusno, statusstring) != 2) {
75                 logger(DEBUG_ALWAYS, LOG_ERR, _("Got bad %s from %s (%s)"), "STATUS",
76                            c->name, c->hostname);
77                 return -1;
78         }
79
80         logger(DEBUG_STATUS, LOG_NOTICE, _("Status message from %s (%s): %s: %s"),
81                            c->name, c->hostname, status_text[statusno], statusstring);
82
83         return 0;
84 }
85
86 int send_error(connection_t *c, int err, char *errstring)
87 {
88         cp();
89
90         if(!errstring)
91                 errstring = strerror(err);
92
93         return send_request(c, "%d %d %s", ERROR, err, errstring);
94 }
95
96 int error_h(connection_t *c)
97 {
98         int err;
99         char errorstring[MAX_STRING_SIZE];
100
101         cp();
102
103         if(sscanf(c->buffer, "%*d %d " MAX_STRING, &err, errorstring) != 2) {
104                 logger(DEBUG_ALWAYS, LOG_ERR, _("Got bad %s from %s (%s)"), "ERROR",
105                            c->name, c->hostname);
106                 return -1;
107         }
108
109         logger(DEBUG_ERROR, LOG_NOTICE, _("Error message from %s (%s): %s: %s"),
110                            c->name, c->hostname, strerror(err), errorstring);
111
112         terminate_connection(c, c->status.active);
113
114         return 0;
115 }
116
117 int send_termreq(connection_t *c)
118 {
119         cp();
120
121         return send_request(c, "%d", TERMREQ);
122 }
123
124 int termreq_h(connection_t *c)
125 {
126         cp();
127
128         terminate_connection(c, c->status.active);
129
130         return 0;
131 }
132
133 int send_ping(connection_t *c)
134 {
135         cp();
136
137         c->status.pinged = 1;
138         c->last_ping_time = now;
139
140         return send_request(c, "%d", PING);
141 }
142
143 int ping_h(connection_t *c)
144 {
145         cp();
146
147         return send_pong(c);
148 }
149
150 int send_pong(connection_t *c)
151 {
152         cp();
153
154         return send_request(c, "%d", PONG);
155 }
156
157 int pong_h(connection_t *c)
158 {
159         cp();
160
161         c->status.pinged = 0;
162
163         /* Succesful connection, reset timeout if this is an outgoing connection. */
164
165         if(c->outgoing)
166                 c->outgoing->timeout = 0;
167
168         return 0;
169 }
170
171 /* Sending and receiving packets via TCP */
172
173 int send_tcppacket(connection_t *c, vpn_packet_t *packet)
174 {
175         int x;
176
177         cp();
178
179         /* Evil hack. */
180
181         x = send_request(c, "%d %hd", PACKET, packet->len);
182
183         if(x)
184                 return x;
185
186         return send_meta(c, packet->data, packet->len);
187 }
188
189 int tcppacket_h(connection_t *c)
190 {
191         short int len;
192
193         cp();
194
195         if(sscanf(c->buffer, "%*d %hd", &len) != 1) {
196                 logger(DEBUG_ALWAYS, LOG_ERR, _("Got bad %s from %s (%s)"), "PACKET", c->name,
197                            c->hostname);
198                 return -1;
199         }
200
201         /* Set reqlen to len, this will tell receive_meta() that a tcppacket is coming. */
202
203         c->tcplen = len;
204
205         return 0;
206 }