buffers.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. /* Copyright 2001,2002 Roger Dingledine, Matej Pfajfar. */
  2. /* See LICENSE for licensing information */
  3. /* $Id$ */
  4. /* buffers.c */
  5. #include "or.h"
  6. extern or_options_t options; /* command-line and config-file options */
  7. /* Create a new buf of size MAX_BUF_SIZE. Write a pointer to it
  8. * into *buf, write MAX_BUF_SIZE into *buflen, and initialize
  9. * *buf_datalen to 0. Return 0.
  10. */
  11. int buf_new(char **buf, int *buflen, int *buf_datalen) {
  12. assert(buf && buflen && buf_datalen);
  13. *buf = (char *)tor_malloc(MAX_BUF_SIZE);
  14. // memset(*buf,0,MAX_BUF_SIZE);
  15. *buflen = MAX_BUF_SIZE;
  16. *buf_datalen = 0;
  17. return 0;
  18. }
  19. void buf_free(char *buf) {
  20. free(buf);
  21. }
  22. /* read from socket s, writing onto buf+buf_datalen.
  23. * read at most 'at_most' bytes, and in any case don't read more than will fit based on buflen.
  24. * If read() returns 0, set *reached_eof to 1 and return 0. If you want to tear
  25. * down the connection return -1, else return the number of bytes read.
  26. */
  27. int read_to_buf(int s, int at_most, char **buf, int *buflen, int *buf_datalen, int *reached_eof) {
  28. int read_result;
  29. #ifdef MS_WINDOWS
  30. int e;
  31. #endif
  32. assert(buf && *buf && buflen && buf_datalen && reached_eof && (s>=0));
  33. /* this is the point where you would grow the buffer, if you want to */
  34. if(at_most > *buflen - *buf_datalen)
  35. at_most = *buflen - *buf_datalen; /* take the min of the two */
  36. if(at_most == 0)
  37. return 0; /* we shouldn't read anything */
  38. // log_fn(LOG_DEBUG,"reading at most %d bytes.",at_most);
  39. read_result = read(s, *buf+*buf_datalen, at_most);
  40. if (read_result < 0) {
  41. if(!ERRNO_EAGAIN(errno)) { /* it's a real error */
  42. return -1;
  43. }
  44. #ifdef MS_WINDOWS
  45. e = correct_socket_errno(s);
  46. if(!ERRNO_EAGAIN(e)) { /* no, it *is* a real error! */
  47. return -1;
  48. }
  49. #endif
  50. return 0;
  51. } else if (read_result == 0) {
  52. log_fn(LOG_DEBUG,"Encountered eof");
  53. *reached_eof = 1;
  54. return 0;
  55. } else { /* we read some bytes */
  56. *buf_datalen += read_result;
  57. // log_fn(LOG_DEBUG,"Read %d bytes. %d on inbuf.",read_result, *buf_datalen);
  58. return read_result;
  59. }
  60. }
  61. int read_to_buf_tls(tor_tls *tls, int at_most, char **buf, int *buflen, int *buf_datalen) {
  62. int r;
  63. assert(tls && *buf && buflen && buf_datalen);
  64. if (at_most > *buflen - *buf_datalen)
  65. at_most = *buflen - *buf_datalen;
  66. if (at_most == 0)
  67. return 0;
  68. r = tor_tls_read(tls, *buf+*buf_datalen, at_most);
  69. if (r<0)
  70. return r;
  71. *buf_datalen += r;
  72. return r;
  73. }
  74. int flush_buf(int s, char **buf, int *buflen, int *buf_flushlen, int *buf_datalen) {
  75. /* push from buf onto s
  76. * then memmove to front of buf
  77. * return -1 or how many bytes remain to be flushed */
  78. int write_result;
  79. #ifdef MS_WINDOWS
  80. int e;
  81. #endif
  82. assert(buf && *buf && buflen && buf_flushlen && buf_datalen && (s>=0) && (*buf_flushlen <= *buf_datalen));
  83. if(*buf_flushlen == 0) /* nothing to flush */
  84. return 0;
  85. /* this is the point where you would grow the buffer, if you want to */
  86. write_result = write(s, *buf, *buf_flushlen);
  87. if (write_result < 0) {
  88. if(!ERRNO_EAGAIN(errno)) { /* it's a real error */
  89. return -1;
  90. }
  91. #ifdef MS_WINDOWS
  92. e = correct_socket_errno(s);
  93. if(!ERRNO_EAGAIN(e)) { /* no, it *is* a real error! */
  94. return -1;
  95. }
  96. #endif
  97. log_fn(LOG_DEBUG,"write() would block, returning.");
  98. return 0;
  99. } else {
  100. *buf_datalen -= write_result;
  101. *buf_flushlen -= write_result;
  102. memmove(*buf, *buf+write_result, *buf_datalen);
  103. log_fn(LOG_DEBUG,"%d: flushed %d bytes, %d ready to flush, %d remain.",
  104. s,write_result,*buf_flushlen,*buf_datalen);
  105. return *buf_flushlen;
  106. /* XXX USE_TLS should change to return write_result like any sane function would */
  107. }
  108. }
  109. int flush_buf_tls(tor_tls *tls, char **buf, int *buflen, int *buf_flushlen, int *buf_datalen)
  110. {
  111. int r;
  112. assert(tls && *buf && buflen && buf_datalen);
  113. /* we want to let tls write even if flushlen is zero, because it might
  114. * have a partial record pending */
  115. r = tor_tls_write(tls, *buf, *buf_flushlen);
  116. if (r < 0) {
  117. return r;
  118. }
  119. *buf_datalen -= r;
  120. *buf_flushlen -= r;
  121. memmove(*buf, *buf+r, *buf_datalen);
  122. return r;
  123. }
  124. int write_to_buf(char *string, int string_len,
  125. char **buf, int *buflen, int *buf_datalen) {
  126. /* append string to buf (growing as needed, return -1 if "too big")
  127. * return total number of bytes on the buf
  128. */
  129. assert(string && buf && *buf && buflen && buf_datalen);
  130. /* this is the point where you would grow the buffer, if you want to */
  131. if (string_len + *buf_datalen > *buflen) { /* we're out of luck */
  132. log_fn(LOG_DEBUG, "buflen too small. Time to implement growing dynamic bufs.");
  133. return -1;
  134. }
  135. memcpy(*buf+*buf_datalen, string, string_len);
  136. *buf_datalen += string_len;
  137. // log_fn(LOG_DEBUG,"added %d bytes to buf (now %d total).",string_len, *buf_datalen);
  138. return *buf_datalen;
  139. }
  140. int fetch_from_buf(char *string, int string_len,
  141. char **buf, int *buflen, int *buf_datalen) {
  142. /* There must be string_len bytes in buf; write them onto string,
  143. * then memmove buf back (that is, remove them from buf).
  144. *
  145. * Return the number of bytes still on the buffer. */
  146. assert(string && buf && *buf && buflen && buf_datalen);
  147. assert(string_len <= *buf_datalen); /* make sure we don't ask for too much */
  148. memcpy(string,*buf,string_len);
  149. *buf_datalen -= string_len;
  150. memmove(*buf, *buf+string_len, *buf_datalen);
  151. return *buf_datalen;
  152. }
  153. /* There is a (possibly incomplete) http statement on *buf, of the
  154. * form "%s\r\n\r\n%s", headers, body.
  155. * If a) the headers include a Content-Length field and all bytes in
  156. * the body are present, or b) there's no Content-Length field and
  157. * all headers are present, then:
  158. * copy headers and body into the supplied args (and null terminate
  159. * them), remove them from buf, and return 1.
  160. * (If headers or body is NULL, discard that part of the buf.)
  161. * If a headers or body doesn't fit in the arg, return -1.
  162. *
  163. * Else, change nothing and return 0.
  164. */
  165. int fetch_from_buf_http(char *buf, int *buf_datalen,
  166. char *headers_out, int max_headerlen,
  167. char *body_out, int max_bodylen) {
  168. char *headers, *body;
  169. int i;
  170. int headerlen, bodylen, contentlen;
  171. assert(buf && buf_datalen);
  172. headers = buf;
  173. i = find_on_inbuf("\r\n\r\n", 4, buf, *buf_datalen);
  174. if(i < 0) {
  175. log_fn(LOG_DEBUG,"headers not all here yet.");
  176. return 0;
  177. }
  178. body = buf+i;
  179. headerlen = body-headers; /* includes the CRLFCRLF */
  180. bodylen = *buf_datalen - headerlen;
  181. log_fn(LOG_DEBUG,"headerlen %d, bodylen %d.",headerlen,bodylen);
  182. if(headers_out && max_headerlen <= headerlen) {
  183. log_fn(LOG_DEBUG,"headerlen %d larger than %d. Failing.", headerlen, max_headerlen-1);
  184. return -1;
  185. }
  186. if(body_out && max_bodylen <= bodylen) {
  187. log_fn(LOG_DEBUG,"bodylen %d larger than %d. Failing.", bodylen, max_bodylen-1);
  188. return -1;
  189. }
  190. #define CONTENT_LENGTH "Content-Length: "
  191. i = find_on_inbuf(CONTENT_LENGTH, strlen(CONTENT_LENGTH), headers, headerlen);
  192. /* This includes headers like Not-Content-Length. But close enough. */
  193. if(i > 0) {
  194. contentlen = atoi(headers+i);
  195. if(bodylen < contentlen) {
  196. log_fn(LOG_DEBUG,"body not all here yet.");
  197. return 0; /* not all there yet */
  198. }
  199. bodylen = contentlen;
  200. log_fn(LOG_DEBUG,"bodylen reduced to %d.",bodylen);
  201. }
  202. /* all happy. copy into the appropriate places, and return 1 */
  203. if(headers_out) {
  204. memcpy(headers_out,buf,headerlen);
  205. headers_out[headerlen] = 0; /* null terminate it */
  206. }
  207. if(body_out) {
  208. memcpy(body_out,buf+headerlen,bodylen);
  209. body_out[bodylen] = 0; /* null terminate it */
  210. }
  211. *buf_datalen -= (headerlen+bodylen);
  212. memmove(buf, buf+headerlen+bodylen, *buf_datalen);
  213. return 1;
  214. }
  215. /* There is a (possibly incomplete) socks handshake on *buf, of the
  216. * forms
  217. * socks4: "socksheader || username\0".
  218. * socks4a: "socksheader || username\0 || destaddr\0".
  219. * If it's a complete and valid handshake, and destaddr fits in addr_out,
  220. * then pull the handshake off the buf, assign to addr_out and port_out,
  221. * and return 1.
  222. * If it's invalid or too big, return -1.
  223. * Else it's not all there yet, change nothing return 0.
  224. */
  225. int fetch_from_buf_socks(char *buf, int *buf_datalen,
  226. char *addr_out, int max_addrlen,
  227. uint16_t *port_out) {
  228. socks4_t *socks4_info;
  229. char tmpbuf[512];
  230. uint16_t port;
  231. enum {socks4, socks4a } socks_prot = socks4a;
  232. char *next, *startaddr;
  233. if(*buf_datalen < sizeof(socks4_t)) /* basic info available? */
  234. return 0; /* not yet */
  235. socks4_info = (socks4_t *)buf;
  236. if(socks4_info->version != 4) {
  237. log_fn(LOG_NOTICE,"Unrecognized version %d.",socks4_info->version);
  238. return -1;
  239. }
  240. if(socks4_info->command != 1) { /* not a connect? we don't support it. */
  241. log_fn(LOG_NOTICE,"command %d not '1'.",socks4_info->command);
  242. return -1;
  243. }
  244. port = ntohs(*(uint16_t*)&socks4_info->destport);
  245. if(!port) {
  246. log_fn(LOG_NOTICE,"Port is zero.");
  247. return -1;
  248. }
  249. if(socks4_info->destip[0] || socks4_info->destip[1] ||
  250. socks4_info->destip[2] || !socks4_info->destip[3]) { /* not 0.0.0.x */
  251. log_fn(LOG_NOTICE,"destip not in form 0.0.0.x.");
  252. sprintf(tmpbuf, "%d.%d.%d.%d", socks4_info->destip[0],
  253. socks4_info->destip[1], socks4_info->destip[2], socks4_info->destip[3]);
  254. if(max_addrlen <= strlen(tmpbuf)) {
  255. log_fn(LOG_DEBUG,"socks4-addr too long.");
  256. return -1;
  257. }
  258. log_fn(LOG_DEBUG,"Successfully read destip (%s)", tmpbuf);
  259. socks_prot = socks4;
  260. }
  261. next = memchr(buf+sizeof(socks4_t), 0, *buf_datalen);
  262. if(!next) {
  263. log_fn(LOG_DEBUG,"Username not here yet.");
  264. return 0;
  265. }
  266. startaddr = next+1;
  267. if(socks_prot == socks4a) {
  268. next = memchr(startaddr, 0, buf+*buf_datalen-startaddr);
  269. if(!next) {
  270. log_fn(LOG_DEBUG,"Destaddr not here yet.");
  271. return 0;
  272. }
  273. if(max_addrlen <= next-startaddr) {
  274. log_fn(LOG_DEBUG,"Destaddr not here yet.");
  275. return -1;
  276. }
  277. }
  278. log_fn(LOG_DEBUG,"Everything is here. Success.");
  279. *port_out = port;
  280. strcpy(addr_out, socks_prot == socks4 ? tmpbuf : startaddr);
  281. *buf_datalen -= (next-buf+1); /* next points to the final \0 on inbuf */
  282. memmove(buf, next+1, *buf_datalen);
  283. // log_fn(LOG_DEBUG,"buf_datalen is now %d:'%s'",*buf_datalen,buf);
  284. return 1;
  285. }
  286. int find_on_inbuf(char *string, int string_len,
  287. char *buf, int buf_datalen) {
  288. /* find first instance of needle 'string' on haystack 'buf'. return how
  289. * many bytes from the beginning of buf to the end of string.
  290. * If it's not there, return -1.
  291. */
  292. char *location;
  293. char *last_possible = buf + buf_datalen - string_len;
  294. assert(string && string_len > 0 && buf);
  295. if(buf_datalen < string_len)
  296. return -1;
  297. for(location = buf; location <= last_possible; location++)
  298. if((*location == *string) && !memcmp(location+1, string+1, string_len-1))
  299. return location-buf+string_len;
  300. return -1;
  301. }
  302. /*
  303. Local Variables:
  304. mode:c
  305. indent-tabs-mode:nil
  306. c-basic-offset:2
  307. End:
  308. */