tor  0.4.2.1-alpha-dev
control_proto.c
Go to the documentation of this file.
1 /* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
2  * Copyright (c) 2007-2019, The Tor Project, Inc. */
3 /* See LICENSE for licensing information */
4 
10 #include "core/or/or.h"
11 
13 #include "core/or/circuitbuild.h"
14 #include "core/or/circuitlist.h"
18 
19 #include "core/or/cpath_build_state_st.h"
20 #include "core/or/entry_connection_st.h"
21 #include "core/or/or_connection_st.h"
22 #include "core/or/origin_circuit_st.h"
23 #include "core/or/socks_request_st.h"
24 #include "feature/control/control_connection_st.h"
25 
29 void
31 {
32  size_t len = strlen(s);
33  connection_buf_add(s, len, TO_CONN(conn));
34 }
35 
38 void
39 connection_printf_to_buf(control_connection_t *conn, const char *format, ...)
40 {
41  va_list ap;
42  char *buf = NULL;
43  int len;
44 
45  va_start(ap,format);
46  len = tor_vasprintf(&buf, format, ap);
47  va_end(ap);
48 
49  if (len < 0) {
50  log_err(LD_BUG, "Unable to format string for controller.");
51  tor_assert(0);
52  }
53 
54  connection_buf_add(buf, (size_t)len, TO_CONN(conn));
55 
56  tor_free(buf);
57 }
58 
68 size_t
69 write_escaped_data(const char *data, size_t len, char **out)
70 {
71  tor_assert(len < SIZE_MAX - 9);
72  size_t sz_out = len+8+1;
73  char *outp;
74  const char *start = data, *end;
75  size_t i;
76  int start_of_line;
77  for (i=0; i < len; ++i) {
78  if (data[i] == '\n') {
79  sz_out += 2; /* Maybe add a CR; maybe add a dot. */
80  if (sz_out >= SIZE_T_CEILING) {
81  log_warn(LD_BUG, "Input to write_escaped_data was too long");
82  *out = tor_strdup(".\r\n");
83  return 3;
84  }
85  }
86  }
87  *out = outp = tor_malloc(sz_out);
88  end = data+len;
89  start_of_line = 1;
90  while (data < end) {
91  if (*data == '\n') {
92  if (data > start && data[-1] != '\r')
93  *outp++ = '\r';
94  start_of_line = 1;
95  } else if (*data == '.') {
96  if (start_of_line) {
97  start_of_line = 0;
98  *outp++ = '.';
99  }
100  } else {
101  start_of_line = 0;
102  }
103  *outp++ = *data++;
104  }
105  if (outp < *out+2 || fast_memcmp(outp-2, "\r\n", 2)) {
106  *outp++ = '\r';
107  *outp++ = '\n';
108  }
109  *outp++ = '.';
110  *outp++ = '\r';
111  *outp++ = '\n';
112  *outp = '\0'; /* NUL-terminate just in case. */
113  tor_assert(outp >= *out);
114  tor_assert((size_t)(outp - *out) <= sz_out);
115  return outp - *out;
116 }
117 
127 size_t
128 read_escaped_data(const char *data, size_t len, char **out)
129 {
130  char *outp;
131  const char *next;
132  const char *end;
133 
134  *out = outp = tor_malloc(len+1);
135 
136  end = data+len;
137 
138  while (data < end) {
139  /* we're at the start of a line. */
140  if (*data == '.')
141  ++data;
142  next = memchr(data, '\n', end-data);
143  if (next) {
144  size_t n_to_copy = next-data;
145  /* Don't copy a CR that precedes this LF. */
146  if (n_to_copy && *(next-1) == '\r')
147  --n_to_copy;
148  memcpy(outp, data, n_to_copy);
149  outp += n_to_copy;
150  data = next+1; /* This will point at the start of the next line,
151  * or the end of the string, or a period. */
152  } else {
153  memcpy(outp, data, end-data);
154  outp += (end-data);
155  *outp = '\0';
156  return outp - *out;
157  }
158  *outp++ = '\n';
159  }
160 
161  *outp = '\0';
162  return outp - *out;
163 }
164 
166 void
168 {
169  control_write_endreply(conn, 250, "OK");
170 }
171 
180 control_write_reply, (control_connection_t *conn, int code, int c,
181  const char *s))
182 {
183  connection_printf_to_buf(conn, "%03d%c%s\r\n", code, c, s);
184 }
185 
194 void
196  const char *fmt, va_list ap)
197 {
198  char *buf = NULL;
199  int len;
200 
201  len = tor_vasprintf(&buf, fmt, ap);
202  if (len < 0) {
203  log_err(LD_BUG, "Unable to format string for controller.");
204  tor_assert(0);
205  }
206  control_write_reply(conn, code, c, buf);
207  tor_free(buf);
208 }
209 
211 void
212 control_write_endreply(control_connection_t *conn, int code, const char *s)
213 {
214  control_write_reply(conn, code, ' ', s);
215 }
216 
218 void
220  const char *fmt, ...)
221 {
222  va_list ap;
223 
224  va_start(ap, fmt);
225  control_vprintf_reply(conn, code, ' ', fmt, ap);
226  va_end(ap);
227 }
228 
230 void
231 control_write_midreply(control_connection_t *conn, int code, const char *s)
232 {
233  control_write_reply(conn, code, '-', s);
234 }
235 
237 void
238 control_printf_midreply(control_connection_t *conn, int code, const char *fmt,
239  ...)
240 {
241  va_list ap;
242 
243  va_start(ap, fmt);
244  control_vprintf_reply(conn, code, '-', fmt, ap);
245  va_end(ap);
246 }
247 
249 void
250 control_write_datareply(control_connection_t *conn, int code, const char *s)
251 {
252  control_write_reply(conn, code, '+', s);
253 }
254 
256 void
257 control_printf_datareply(control_connection_t *conn, int code, const char *fmt,
258  ...)
259 {
260  va_list ap;
261 
262  va_start(ap, fmt);
263  control_vprintf_reply(conn, code, '+', fmt, ap);
264  va_end(ap);
265 }
266 
268 void
269 control_write_data(control_connection_t *conn, const char *data)
270 {
271  char *esc = NULL;
272  size_t esc_len;
273 
274  esc_len = write_escaped_data(data, strlen(data), &esc);
275  connection_buf_add(esc, esc_len, TO_CONN(conn));
276  tor_free(esc);
277 }
MOCK_IMPL(void, control_write_reply,(control_connection_t *conn, int code, int c, const char *s))
#define TO_CONN(c)
Definition: or.h:735
size_t read_escaped_data(const char *data, size_t len, char **out)
Header file for connection.c.
void connection_write_str_to_buf(const char *s, control_connection_t *conn)
Definition: control_proto.c:30
Header file for nodelist.c.
int tor_vasprintf(char **strp, const char *fmt, va_list args)
Definition: printf.c:96
void control_write_datareply(control_connection_t *conn, int code, const char *s)
void send_control_done(control_connection_t *conn)
#define tor_free(p)
Definition: malloc.h:52
void control_printf_datareply(control_connection_t *conn, int code, const char *fmt,...)
void control_vprintf_reply(control_connection_t *conn, int code, int c, const char *fmt, va_list ap)
void control_printf_endreply(control_connection_t *conn, int code, const char *fmt,...)
tor_assert(buffer)
void control_printf_midreply(control_connection_t *conn, int code, const char *fmt,...)
#define SIZE_T_CEILING
Definition: torint.h:126
size_t write_escaped_data(const char *data, size_t len, char **out)
Definition: control_proto.c:69
Master header file for Tor-specific functionality.
Header file for circuitbuild.c.
Header file for circuitlist.c.
Header file for connection_edge.c.
void control_write_data(control_connection_t *conn, const char *data)
void control_write_endreply(control_connection_t *conn, int code, const char *s)
#define fast_memcmp(a, b, c)
Definition: di_ops.h:26
Header file for control_proto.c.
#define LD_BUG
Definition: log.h:84
void control_write_midreply(control_connection_t *conn, int code, const char *s)
void connection_printf_to_buf(control_connection_t *conn, const char *format,...)
Definition: control_proto.c:39