fifo_server.c 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623
  1. /*
  2. * Copyright (C) 2001-2003 FhG Fokus
  3. * Copyright (C) 2005 iptelorg GmbH
  4. *
  5. * This file is part of Kamailio, a free SIP server.
  6. *
  7. * Kamailio is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version
  11. *
  12. * Kamailio is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  20. *
  21. */
  22. /*! \file
  23. * \brief ctl module
  24. * \ingroup ctl
  25. *
  26. */
  27. /*! \defgroup ctl Control binrpc socket
  28. *
  29. * Fifo server is a very powerful tool used to access easily
  30. * ser's internals via textual interface, similarly to
  31. * how internals of many operating systems are accessible
  32. * via the proc file system. This might be used for
  33. * making ser do things for you (such as initiating new
  34. * transaction from webpages) or inspect server's health.
  35. *
  36. * FIFO server allows new functionality to be registered
  37. * with it -- thats what register_fifo_cmd is good for.
  38. * Remember, the initialization must take place before
  39. * forking; best in init_module functions. When a function
  40. * is registered, it can be always evoked by sending its
  41. * name prefixed by colon to the FIFO.
  42. *
  43. * There are few commands already implemented in core.
  44. * These are 'uptime' for looking at how long the server
  45. * is alive and 'print' for debugging purposes.
  46. *
  47. * Every command sent to FIFO must be sent atomically to
  48. * avoid intermixing with other commands and MUST be
  49. * terminated by empty line so that the server is to able
  50. * to find its end if it does not understand the command.
  51. *
  52. * File test/transaction.fifo illustrates example of use
  53. * of t_uac command (part of TM module).
  54. *
  55. */
  56. #ifdef USE_FIFO
  57. #include <limits.h>
  58. #include <stdlib.h>
  59. #include <sys/types.h>
  60. #include <unistd.h>
  61. #include <stdio.h>
  62. #include <errno.h>
  63. #include <sys/stat.h>
  64. #include <fcntl.h>
  65. #include <signal.h>
  66. #include <string.h>
  67. #include <time.h>
  68. #include <stdarg.h>
  69. #ifdef USE_TCP
  70. #include <sys/socket.h>
  71. #endif
  72. #include "../../dprint.h"
  73. #include "../../ut.h"
  74. #include "../../error.h"
  75. #include "../../config.h"
  76. #include "../../globals.h"
  77. #include "../../mem/mem.h"
  78. #include "../../mem/shm_mem.h"
  79. #include "../../sr_module.h"
  80. #include "../../pt.h"
  81. #include "../../rpc.h"
  82. #include "../../tsend.h"
  83. #include "fifo_server.h"
  84. #include "io_listener.h"
  85. #include "ctl.h"
  86. #define MAX_FIFO_COMMAND 128 /* Maximum length of a FIFO server command */
  87. #define MAX_CONSUME_BUFFER 1024 /* Buffer dimensions for FIFO server */
  88. #define MAX_LINE_BUFFER 2048 /* Maximum parameter line length */
  89. #define DEFAULT_REPLY_RETRIES 4 /* Default number of reply write attempts */
  90. #define DEFAULT_REPLY_WAIT 80000 /* How long we should wait for the client, in micro seconds */
  91. #define DEFAULT_FIFO_DIR "/tmp/" /* Where reply pipes may be opened */
  92. #define MAX_MSG_CHUNKS 1024 /* maximum message pieces */
  93. #define FIFO_TX_TIMEOUT 200 /* maximum time to block writing to
  94. the fifo */
  95. /* readline from a buffer helper */
  96. struct readline_handle{
  97. char* s; /* buffer start */
  98. char* end; /* end */
  99. char* crt; /* crt. pos */
  100. };
  101. enum text_flags {
  102. CHUNK_SEEN = (1 << 0),
  103. CHUNK_POSITIONAL = (1 << 1), /* Positinal parameter, should be followed by \n */
  104. CHUNK_MEMBER_NAME = (1 << 2), /* Struct member name, should be followed by : */
  105. CHUNK_MEMBER_VALUE = (1 << 3) /* Struct member value, should be followed by , if
  106. * there is another member name and \n if not */
  107. };
  108. /*
  109. * Generit text chunk. Flags attribute contains arbitrary flags
  110. */
  111. struct text_chunk {
  112. unsigned char flags;
  113. str s;
  114. struct text_chunk* next;
  115. void *ctx; /* context, which must be passed along */
  116. };
  117. /*
  118. * This is the parameter if rpc_struct_add
  119. */
  120. struct rpc_struct_out {
  121. struct rpc_context* ctx;
  122. struct text_chunk* line;
  123. };
  124. struct rpc_struct {
  125. struct rpc_context* ctx;
  126. struct text_chunk* names; /* Names of elements */
  127. struct text_chunk* values; /* Element values as strings */
  128. struct rpc_struct* next;
  129. };
  130. /*
  131. * Context structure containing state of processing
  132. */
  133. typedef struct rpc_context {
  134. char* method; /* Request method name */
  135. char* reply_file; /* Full path and name to the reply FIFO file */
  136. int reply_sent; /* This flag ensures that we do not send a reply twice */
  137. int code; /* Reply code */
  138. char* reason; /* Reason phrase */
  139. struct text_chunk* body; /* First line to be appended as reply body */
  140. struct text_chunk* last; /* Last body line */
  141. struct text_chunk* strs; /* Strings to be collected at the end of processing */
  142. struct rpc_struct* structs; /* Structures to be collected at the end of processing */
  143. struct readline_handle read_h;
  144. struct send_handle* send_h;
  145. int line_no;
  146. } rpc_ctx_t;
  147. char* fifo_dir = DEFAULT_FIFO_DIR; /* dir where reply fifos are
  148. allowed */
  149. int fifo_reply_retries = DEFAULT_REPLY_RETRIES;
  150. int fifo_reply_wait = DEFAULT_REPLY_WAIT;
  151. static rpc_t func_param; /* Pointers to implementation of RPC funtions */
  152. static int rpc_send (rpc_ctx_t* ctx); /* Send the reply to the client */
  153. static void rpc_fault (rpc_ctx_t* ctx, int code, char* fmt, ...); /* Signal a failure to the client */
  154. static int rpc_add (rpc_ctx_t* ctx, char* fmt, ...); /* Add a new piece of data to the result */
  155. static int rpc_scan (rpc_ctx_t* ctx, char* fmt, ...); /* Retrieve request parameters */
  156. static int rpc_rpl_printf (rpc_ctx_t* ctx, char* fmt, ...); /* Add printf-like formated data to the result set */
  157. static int rpc_struct_add (struct text_chunk* s, char* fmt, ...); /* Create a new structure */
  158. static int rpc_struct_scan (struct rpc_struct* s, char* fmt, ...); /* Scan attributes of a structure */
  159. static int rpc_struct_printf(struct text_chunk* s, char* name, char* fmt, ...);
  160. /*
  161. * Escape string in buffer 'r' of length len. Write
  162. * the escaped string in buffer dst. The destination
  163. * buffer must exist and must be twice as big as the
  164. * input buffer.
  165. *
  166. * Parameter all controls the set of characters to be
  167. * escaped. If set to 1 then all characters, including
  168. * structure delimiters, will be escaped. If set to
  169. * 0 then only line delimiters, tab and zero will be
  170. * escaped.
  171. */
  172. static void escape(str* dst, char* r, int len, int all)
  173. {
  174. int i;
  175. char* w;
  176. if (!len) {
  177. dst->len = 0;
  178. return;
  179. }
  180. w = dst->s;
  181. for(i = 0; i < len; i++) {
  182. switch(r[i]) {
  183. case '\n': *w++ = '\\'; *w++ = 'n'; break;
  184. case '\r': *w++ = '\\'; *w++ = 'r'; break;
  185. case '\t': *w++ = '\\'; *w++ = 't'; break;
  186. case '\\': *w++ = '\\'; *w++ = '\\'; break;
  187. case '\0': *w++ = '\\'; *w++ = '0'; break;
  188. case ':':
  189. if (all) {
  190. *w++ = '\\';
  191. *w++ = 'o';
  192. } else *w++ = r[i];
  193. break;
  194. case ',':
  195. if (all) {
  196. *w++ = '\\';
  197. *w++ = 'c';
  198. } else *w++ = r[i];
  199. break;
  200. default:
  201. *w++ = r[i];
  202. break;
  203. }
  204. }
  205. dst->len = w - dst->s;
  206. }
  207. /*
  208. * Unescape the string in buffer 'r' of length len.
  209. * The resulting string will be stored in buffer dst
  210. * which must exist and must be at least as big as
  211. * the source buffer. The function will update dst->len
  212. * to the length of the resulting string.
  213. *
  214. * Return value 0 indicates success, -1 indicates
  215. * formatting error.
  216. */
  217. static int unescape(str* dst, char* r, int len)
  218. {
  219. char* w;
  220. int i;
  221. if (!len) {
  222. dst->len = 0;
  223. return 0;
  224. }
  225. w = dst->s;
  226. for(i = 0; i < len; i++) {
  227. switch(*r) {
  228. case '\\':
  229. r++;
  230. i++;
  231. switch(*r++) {
  232. case '\\': *w++ = '\\'; break;
  233. case 'n': *w++ = '\n'; break;
  234. case 'r': *w++ = '\r'; break;
  235. case 't': *w++ = '\t'; break;
  236. case '0': *w++ = '\0'; break;
  237. case 'c': *w++ = ':'; break; /* Structure delimiter */
  238. case 'o': *w++ = ','; break; /* Structure delimiter */
  239. default: return -1;
  240. }
  241. break;
  242. default: *w++ = *r++; break;
  243. }
  244. }
  245. dst->len = w - dst->s;
  246. return 0;
  247. }
  248. /*
  249. * Create a new text chunk, the input text will
  250. * be escaped.
  251. */
  252. struct text_chunk* new_chunk_escape(str* src, int escape_all)
  253. {
  254. struct text_chunk* l;
  255. if (!src) return 0;
  256. l = ctl_malloc(sizeof(struct text_chunk));
  257. if (!l) {
  258. ERR("No Memory Left\n");
  259. return 0;
  260. }
  261. l->s.s = ctl_malloc(src->len * 2 + 1);
  262. if (!l->s.s) {
  263. ERR("No Memory Left\n");
  264. ctl_free(l);
  265. return 0;
  266. }
  267. l->next = 0;
  268. l->flags = 0;
  269. escape(&l->s, src->s, src->len, escape_all);
  270. l->s.s[l->s.len] = '\0';
  271. return l;
  272. }
  273. /*
  274. * Create a new text chunk, the input text
  275. * will not be escaped. The function returns
  276. * 0 on an error
  277. */
  278. struct text_chunk* new_chunk(str* src)
  279. {
  280. struct text_chunk* l;
  281. if (!src) return 0;
  282. l = ctl_malloc(sizeof(struct text_chunk));
  283. if (!l) {
  284. ERR("No Memory Left\n");
  285. return 0;
  286. }
  287. l->s.s = ctl_malloc(src->len + 1);
  288. if (!l->s.s) {
  289. ERR("No Memory Left\n");
  290. ctl_free(l);
  291. return 0;
  292. }
  293. l->next = 0;
  294. l->flags = 0;
  295. memcpy(l->s.s, src->s, src->len);
  296. l->s.len = src->len;
  297. l->s.s[l->s.len] = '\0';
  298. return l;
  299. }
  300. /*
  301. * Create a new text chunk, the input text
  302. * will be unescaped first.
  303. */
  304. struct text_chunk* new_chunk_unescape(str* src)
  305. {
  306. struct text_chunk* l;
  307. if (!src) return 0;
  308. l = ctl_malloc(sizeof(struct text_chunk));
  309. if (!l) {
  310. ERR("No Memory Left\n");
  311. return 0;
  312. }
  313. l->s.s = ctl_malloc(src->len + 1);
  314. if (!l->s.s) {
  315. ERR("No Memory Left\n");
  316. ctl_free(l);
  317. return 0;
  318. }
  319. l->next = 0;
  320. l->flags = 0;
  321. if (unescape(&l->s, src->s, src->len) < 0) {
  322. ctl_free(l->s.s);
  323. ctl_free(l);
  324. return 0;
  325. }
  326. l->s.s[l->s.len] = '\0';
  327. return l;
  328. }
  329. static void free_chunk(struct text_chunk* c)
  330. {
  331. if (c && c->s.s) ctl_free(c->s.s);
  332. if (c) ctl_free(c);
  333. }
  334. static void free_struct(struct rpc_struct* s)
  335. {
  336. struct text_chunk* c;
  337. if (!s) return;
  338. while(s->names) {
  339. c = s->names;
  340. s->names = s->names->next;
  341. free_chunk(c);
  342. }
  343. while(s->values) {
  344. c = s->values;
  345. s->values = s->values->next;
  346. free_chunk(c);
  347. }
  348. ctl_free(s);
  349. }
  350. /*
  351. * Parse a structure
  352. */
  353. static struct rpc_struct* new_struct(rpc_ctx_t* ctx, str* line)
  354. {
  355. char* comma, *colon;
  356. struct rpc_struct* s;
  357. str left, right = STR_NULL, name, value;
  358. struct text_chunk* n, *v;
  359. if (!line->len) {
  360. rpc_fault(ctx, 400, "Line %d Empty - Structure Expected",
  361. ctx->line_no);
  362. return 0;
  363. }
  364. s = (struct rpc_struct*)ctl_malloc(sizeof(struct rpc_struct));
  365. if (!s) {
  366. rpc_fault(ctx, 500, "Internal Server Error (No Memory Left)");
  367. return 0;
  368. }
  369. memset(s, 0, sizeof(struct rpc_struct));
  370. s->ctx = ctx;
  371. left = *line;
  372. do {
  373. comma = q_memchr(left.s, ',', left.len);
  374. if (comma) {
  375. right.s = comma + 1;
  376. right.len = left.len - (comma - left.s) - 1;
  377. left.len = comma - left.s;
  378. }
  379. /* Split the record to name and value */
  380. colon = q_memchr(left.s, ':', left.len);
  381. if (!colon) {
  382. rpc_fault(ctx, 400, "Colon missing in struct on line %d",
  383. ctx->line_no);
  384. goto err;;
  385. }
  386. name.s = left.s;
  387. name.len = colon - name.s;
  388. value.s = colon + 1;
  389. value.len = left.len - (colon - left.s) - 1;
  390. /* Create name chunk */
  391. n = new_chunk_unescape(&name);
  392. if (!n) {
  393. rpc_fault(ctx, 400, "Error while processing struct member '%.*s' "
  394. "on line %d", name.len, ZSW(name.s), ctx->line_no);
  395. goto err;
  396. }
  397. n->next = s->names;
  398. s->names = n;
  399. /* Create value chunk */
  400. v = new_chunk_unescape(&value);
  401. if (!v) {
  402. rpc_fault(ctx, 400, "Error while processing struct membeer '%.*s'"
  403. " on line %d", name.len, ZSW(name.s), ctx->line_no);
  404. goto err;
  405. }
  406. v->next = s->values;
  407. s->values = v;
  408. left = right;
  409. } while(comma);
  410. return s;
  411. err:
  412. if (s) free_struct(s);
  413. return 0;
  414. }
  415. /*
  416. * Read a line from FIFO file and store a pointer to the data in buffer 'b'
  417. * and the legnth of the line in variable 'read'
  418. *
  419. * Returns -1 on error, 0 on success
  420. */
  421. static int read_line(char** b, int* read, struct readline_handle* rh)
  422. {
  423. char* eol;
  424. char* trim;
  425. if (rh->crt>=rh->end){
  426. /* end, nothing more to read */
  427. return -1;
  428. }
  429. for(eol=rh->crt; (eol<rh->end) && (*eol!='\n'); eol++);
  430. *eol=0;
  431. trim=eol;
  432. /* trim spaces at the end */
  433. for(trim=eol;(trim>rh->crt) &&
  434. ((*trim=='\r')||(*trim==' ')||(*trim=='\t')); trim--){
  435. *trim=0;
  436. }
  437. *b=rh->crt;
  438. *read = (int)(trim-rh->crt);
  439. rh->crt=eol+1;
  440. return 0;
  441. }
  442. /*
  443. * Remove directory path from filename and replace it
  444. * with the path configured through a module parameter.
  445. *
  446. * The result is allocated using ctl_malloc and thus
  447. * has to be freed using ctl_free
  448. */
  449. static char *trim_filename(char * file)
  450. {
  451. int prefix_len, fn_len;
  452. char *new_fn;
  453. /* we only allow files in "/tmp" -- any directory
  454. * changes are not welcome
  455. */
  456. if (strchr(file, '.') || strchr(file, '/')
  457. || strchr(file, '\\')) {
  458. ERR("Forbidden filename: %s\n"
  459. , file);
  460. return 0;
  461. }
  462. prefix_len = strlen(fifo_dir); fn_len = strlen(file);
  463. new_fn = ctl_malloc(prefix_len + fn_len + 1);
  464. if (new_fn == 0) {
  465. ERR("No memory left\n");
  466. return 0;
  467. }
  468. memcpy(new_fn, fifo_dir, prefix_len);
  469. memcpy(new_fn + prefix_len, file, fn_len);
  470. new_fn[prefix_len + fn_len] = 0;
  471. return new_fn;
  472. }
  473. /* reply fifo security checks:
  474. * checks if fd is a fifo, is not hardlinked and it's not a softlink
  475. * opened file descriptor + file name (for soft link check)
  476. * returns 0 if ok, <0 if not
  477. */
  478. static int fifo_check(int fd, char* fname)
  479. {
  480. struct stat fst;
  481. struct stat lst;
  482. if (fstat(fd, &fst) < 0) {
  483. ERR("fstat failed: %s\n",
  484. strerror(errno));
  485. return -1;
  486. }
  487. /* check if fifo */
  488. if (!S_ISFIFO(fst.st_mode)){
  489. ERR("%s is not a fifo\n", fname);
  490. return -1;
  491. }
  492. /* check if hard-linked */
  493. if (fst.st_nlink > 1) {
  494. ERR("%s is hard-linked %d times\n",
  495. fname, (unsigned)fst.st_nlink);
  496. return -1;
  497. }
  498. /* lstat to check for soft links */
  499. if (lstat(fname, &lst) < 0) {
  500. ERR("lstat failed: %s\n",
  501. strerror(errno));
  502. return -1;
  503. }
  504. if (S_ISLNK(lst.st_mode)) {
  505. ERR("%s is a soft link\n", fname);
  506. return -1;
  507. }
  508. /* if this is not a symbolic link, check to see if the inode didn't
  509. * change to avoid possible sym.link, rm sym.link & replace w/ fifo race
  510. */
  511. if ((lst.st_dev != fst.st_dev) || (lst.st_ino != fst.st_ino)) {
  512. ERR("inode/dev number differ : %d %d (%s)\n",
  513. (int)fst.st_ino, (int)lst.st_ino, fname);
  514. return -1;
  515. }
  516. /* success */
  517. return 0;
  518. }
  519. /*
  520. * Open the FIFO reply file
  521. * returns fs no on success, -1 on error
  522. */
  523. static int open_reply_pipe(char *pipe_name)
  524. {
  525. int fifofd;
  526. int flags;
  527. int retries = fifo_reply_retries;
  528. fifofd=-1;
  529. if (!pipe_name || *pipe_name == 0) {
  530. DBG("No file to write to about missing cmd\n");
  531. goto error;
  532. }
  533. tryagain:
  534. /* open non-blocking to make sure that a broken client will not
  535. * block the FIFO server forever */
  536. fifofd = open(pipe_name, O_WRONLY | O_NONBLOCK);
  537. if (fifofd == -1) {
  538. /* retry several times if client is not yet ready for getting
  539. * feedback via a reply pipe
  540. */
  541. if (errno == ENXIO) {
  542. /* give up on the client - we can't afford server blocking */
  543. if (retries == 0) {
  544. ERR("No client at %s\n", pipe_name);
  545. goto error;
  546. }
  547. /* don't be noisy on the very first try */
  548. if (retries != fifo_reply_retries) {
  549. DBG("Retry countdown: %d\n", retries);
  550. }
  551. sleep_us(fifo_reply_wait);
  552. retries--;
  553. goto tryagain;
  554. }
  555. /* some other opening error */
  556. ERR("Open error (%s): %s\n",
  557. pipe_name, strerror(errno));
  558. goto error;
  559. }
  560. /* security checks: is this really a fifo?, is
  561. * it hardlinked? is it a soft link? */
  562. if (fifo_check(fifofd, pipe_name) < 0) goto error;
  563. /* we want server blocking for big writes */
  564. if ((flags = fcntl(fifofd, F_GETFL, 0)) < 0) {
  565. ERR("(%s): getfl failed: %s\n", pipe_name, strerror(errno));
  566. goto error;
  567. }
  568. flags &= ~O_NONBLOCK;
  569. if (fcntl(fifofd, F_SETFL, flags) < 0) {
  570. ERR("(%s): setfl cntl failed: %s\n",
  571. pipe_name, strerror(errno));
  572. goto error;
  573. }
  574. return fifofd;
  575. error:
  576. if (fifofd!=-1) close(fifofd);
  577. return -1;
  578. }
  579. /*
  580. * Man FIFO routine running in the FIFO
  581. * processes requests received
  582. * through the FIFO file repeatedly
  583. */
  584. int fifo_process(char* msg_buf, int size, int* bytes_needed, void *sh,
  585. void** saved_state)
  586. {
  587. rpc_export_t* exp;
  588. char* buf;
  589. int line_len;
  590. char *file_sep;
  591. struct text_chunk* p;
  592. struct rpc_struct* s;
  593. int r;
  594. int req_size;
  595. static rpc_ctx_t context;
  596. DBG("process_fifo: called with %d bytes, offset %d: %.*s\n",
  597. size, (int)(long)*saved_state, size, msg_buf);
  598. /* search for the end of the request (\n\r) */
  599. if (size < 6){ /* min fifo request */
  600. *bytes_needed=6-size;
  601. return 0; /* we want more bytes, nothing processed */
  602. }
  603. for (r=1+(int)(long)*saved_state;r<size;r++){
  604. if ((msg_buf[r]=='\n' || msg_buf[r]=='\r') &&
  605. (msg_buf[r-1]=='\n'|| msg_buf[r-1]=='\r')){
  606. /* found double cr, or double lf => end of request */
  607. req_size=r;
  608. goto process;
  609. }
  610. }
  611. /* no end of request found => ask for more bytes */
  612. *bytes_needed=1;
  613. /* save current offset, to optimize search */
  614. *saved_state=(void*)(long)(r-1);
  615. return 0; /* we want again the whole buffer */
  616. process:
  617. DBG("process_fifo %d bytes request: %.*s\n",
  618. req_size, req_size, msg_buf);
  619. file_sep = 0;
  620. context.method = 0;
  621. context.reply_file = 0;
  622. context.body = 0;
  623. context.code = 200;
  624. context.reason = "OK";
  625. context.reply_sent = 0;
  626. context.last = 0;
  627. context.line_no = 0;
  628. context.read_h.s=msg_buf;
  629. context.read_h.end=msg_buf+size;
  630. context.read_h.crt=msg_buf;
  631. context.send_h=(struct send_handle*)sh;
  632. /* commands must look this way ':<command>:[filename]' */
  633. if (read_line(&buf, &line_len, &context.read_h) < 0) {
  634. /* line breaking must have failed -- consume the rest
  635. * and proceed to a new request
  636. */
  637. ERR("Command expected\n");
  638. goto consume;
  639. }
  640. context.line_no++;
  641. if (line_len == 0) {
  642. DBG("Empty command received\n");
  643. goto consume;
  644. }
  645. if (line_len < 3) {
  646. ERR("Command must have at least 3 chars\n");
  647. goto consume;
  648. }
  649. if (*buf != CMD_SEPARATOR) {
  650. ERR("Command must begin with %c: %.*s\n",
  651. CMD_SEPARATOR, line_len, buf);
  652. goto consume;
  653. }
  654. context.method = buf + 1;
  655. file_sep = strchr(context.method, CMD_SEPARATOR);
  656. if (file_sep == NULL) {
  657. ERR("File separator missing\n");
  658. goto consume;
  659. }
  660. if (file_sep == context.method) {
  661. ERR("Empty command\n");
  662. goto consume;
  663. }
  664. if (*(file_sep + 1) == 0) context.reply_file = NULL;
  665. else {
  666. context.reply_file = file_sep + 1;
  667. context.reply_file = trim_filename(context.reply_file);
  668. if (context.reply_file == 0) {
  669. ERR("Trimming filename\n");
  670. goto consume;
  671. }
  672. }
  673. /* make command zero-terminated */
  674. *file_sep = 0;
  675. exp = find_rpc_export(context.method, 0);
  676. if (!exp || !exp->function) {
  677. DBG("Command %s not found\n", context.method);
  678. rpc_fault(&context, 500, "Command '%s' not found", context.method);
  679. goto consume;
  680. }
  681. exp->function(&func_param, &context);
  682. consume:
  683. if (!context.reply_sent) {
  684. rpc_send(&context);
  685. }
  686. if (context.reply_file) {
  687. ctl_free(context.reply_file);
  688. context.reply_file = 0;
  689. }
  690. /* Collect garbage (unescaped strings and structures) */
  691. while(context.strs) {
  692. p = context.strs;
  693. context.strs = context.strs->next;
  694. free_chunk(p);
  695. }
  696. while(context.structs) {
  697. s = context.structs;
  698. context.structs = context.structs->next;
  699. free_struct(s);
  700. }
  701. *bytes_needed=0;
  702. DBG("Command consumed\n");
  703. DBG("process_fifo: returning %d, bytes_needed 0\n", req_size+1);
  704. return req_size+1; /* all was processed (including terminating \n)*/
  705. }
  706. /*
  707. * Initialze the FIFO fd
  708. * Make sure that we can create and open the FIFO file and
  709. * make it secure. This function must be executed from mod_init.
  710. * This ensures that it has sufficient privileges.
  711. */
  712. int init_fifo_fd(char* fifo, int fifo_mode, int fifo_uid, int fifo_gid,
  713. int* fifo_write)
  714. {
  715. struct stat filestat;
  716. int n;
  717. long opt;
  718. int fifo_read;
  719. if (fifo == NULL) {
  720. ERR("null fifo: no fifo will be opened\n");
  721. /* error null fifo */
  722. return -1;
  723. }
  724. if (strlen(fifo) == 0) {
  725. ERR("emtpy fifo: fifo disabled\n");
  726. return -1;
  727. }
  728. DBG("Opening fifo...\n");
  729. n = stat(fifo, &filestat);
  730. if (n == 0) {
  731. /* FIFO exist, delete it (safer) */
  732. if (unlink(fifo) < 0) {
  733. ERR("Cannot delete old fifo (%s):"
  734. " %s\n", fifo, strerror(errno));
  735. return -1;
  736. }
  737. } else if (n < 0 && errno != ENOENT) {
  738. ERR("FIFO stat failed: %s\n",
  739. strerror(errno));
  740. }
  741. /* create FIFO ... */
  742. if ((mkfifo(fifo, fifo_mode) < 0)) {
  743. ERR("Can't create FIFO: "
  744. "%s (mode=%d)\n",
  745. strerror(errno), fifo_mode);
  746. return -1;
  747. }
  748. DBG("FIFO created @ %s\n", fifo );
  749. if ((chmod(fifo, fifo_mode) < 0)) {
  750. ERR("Can't chmod FIFO: %s (mode=%d)\n",
  751. strerror(errno), fifo_mode);
  752. return -1;
  753. }
  754. if ((fifo_uid != -1) || (fifo_gid != -1)) {
  755. if (chown(fifo, fifo_uid, fifo_gid) < 0) {
  756. ERR("Failed to change the owner/group for %s to %d.%d; %s[%d]\n",
  757. fifo, fifo_uid, fifo_gid, strerror(errno), errno);
  758. return -1;
  759. }
  760. }
  761. DBG("fifo %s opened, mode=%d\n", fifo, fifo_mode);
  762. fifo_read = open(fifo, O_RDONLY | O_NONBLOCK, 0);
  763. if (fifo_read < 0) {
  764. ERR("fifo_read did not open: %s\n",
  765. strerror(errno));
  766. return -1;
  767. }
  768. /* make sure the read fifo will not close */
  769. *fifo_write = open(fifo, O_WRONLY | O_NONBLOCK, 0);
  770. if (*fifo_write < 0) {
  771. ERR("fifo_write did not open: %s\n",
  772. strerror(errno));
  773. return -1;
  774. }
  775. /* set read fifo blocking mode */
  776. if ((opt = fcntl(fifo_read, F_GETFL)) == -1) {
  777. ERR("fcntl(F_GETFL) failed: %s [%d]\n",
  778. strerror(errno), errno);
  779. return -1;
  780. }
  781. if (fcntl(fifo_read, F_SETFL, opt & (~O_NONBLOCK)) == -1) {
  782. ERR("fcntl(F_SETFL) failed: %s [%d]\n",
  783. strerror(errno), errno);
  784. return -1;
  785. }
  786. return fifo_read;
  787. }
  788. int fifo_rpc_init()
  789. {
  790. memset(&func_param, 0, sizeof(func_param));
  791. func_param.send = (rpc_send_f)rpc_send;
  792. func_param.fault = (rpc_fault_f)rpc_fault;
  793. func_param.add = (rpc_add_f)rpc_add;
  794. func_param.scan = (rpc_scan_f)rpc_scan;
  795. func_param.rpl_printf = (rpc_rpl_printf_f)rpc_rpl_printf;
  796. func_param.struct_add = (rpc_struct_add_f)rpc_struct_add;
  797. /* use rpc_struct_add for array_add */
  798. func_param.array_add = (rpc_array_add_f)rpc_struct_add;
  799. func_param.struct_scan = (rpc_struct_scan_f)rpc_struct_scan;
  800. func_param.struct_printf = (rpc_struct_printf_f)rpc_struct_printf;
  801. return 0;
  802. }
  803. /*
  804. * Close and unlink the FIFO file
  805. */
  806. void destroy_fifo(int read_fd, int w_fd, char* fname)
  807. {
  808. if (read_fd!=-1)
  809. close(read_fd);
  810. if(w_fd!=-1)
  811. close(w_fd);
  812. /* if FIFO was created, delete it */
  813. if (fname && strlen(fname)) {
  814. if (unlink(fname) < 0) {
  815. WARN("Cannot delete fifo (%s):"
  816. " %s\n", fname, strerror(errno));
  817. }
  818. }
  819. }
  820. #define REASON_BUF_LEN 1024
  821. /*
  822. * An error occurred, signal it to the client
  823. */
  824. static void rpc_fault(rpc_ctx_t* ctx, int code, char* fmt, ...)
  825. {
  826. static char buf[REASON_BUF_LEN];
  827. va_list ap;
  828. ctx->code = code;
  829. va_start(ap, fmt);
  830. vsnprintf(buf, REASON_BUF_LEN, fmt, ap);
  831. va_end(ap);
  832. ctx->reason = buf;
  833. }
  834. static inline int safe_write(FILE* f, char* fmt, ...)
  835. {
  836. va_list ap;
  837. if (!*fmt) return 0;
  838. va_start(ap, fmt);
  839. retry:
  840. /* First line containing code and reason phrase */
  841. if (vfprintf(f, fmt, ap) <= 0) {
  842. ERR("fifo write error: %s\n", strerror(errno));
  843. if ((errno == EINTR) || (errno == EAGAIN) || (errno == EWOULDBLOCK)) {
  844. goto retry;
  845. }
  846. va_end(ap);
  847. return -1;
  848. }
  849. va_end(ap);
  850. return 0;
  851. }
  852. inline static int build_iovec(rpc_ctx_t* ctx, struct iovec* v, int v_size)
  853. {
  854. struct text_chunk* p;
  855. int r_c_len;
  856. int r;
  857. /* reason code */
  858. v[0].iov_base=int2str(ctx->code, &r_c_len);
  859. v[0].iov_len=r_c_len;
  860. v[1].iov_base=" ";
  861. v[1].iov_len=1;
  862. /* reason txt */
  863. v[2].iov_base=ctx->reason;
  864. v[2].iov_len=strlen(ctx->reason);
  865. v[3].iov_base="\n";
  866. v[3].iov_len=1;
  867. r=4;
  868. /* Send the body */
  869. while(ctx->body) {
  870. p = ctx->body;
  871. ctx->body = ctx->body->next;
  872. if (p->s.len){
  873. if (r>=v_size) goto error_overflow;
  874. v[r].iov_base=p->s.s;
  875. v[r].iov_len=p->s.len;
  876. r++;
  877. }
  878. if (p->flags & CHUNK_POSITIONAL) {
  879. if (r>=v_size) goto error_overflow;
  880. v[r].iov_base="\n";
  881. v[r].iov_len=1;
  882. r++;
  883. } else if (p->flags & CHUNK_MEMBER_NAME) {
  884. if (r>=v_size) goto error_overflow;
  885. v[r].iov_base=":";
  886. v[r].iov_len=1;
  887. r++;
  888. } else if (p->flags & CHUNK_MEMBER_VALUE) {
  889. if (p->next && p->next->flags & CHUNK_MEMBER_NAME) {
  890. if (r>=MAX_MSG_CHUNKS) goto error_overflow;
  891. v[r].iov_base=",";
  892. v[r].iov_len=1;
  893. r++;
  894. } else {
  895. if (r>=v_size) goto error_overflow;
  896. v[r].iov_base="\n";
  897. v[r].iov_len=1;
  898. r++;
  899. }
  900. }
  901. free_chunk(p);
  902. }
  903. return r;
  904. error_overflow:
  905. ERR("too many message chunks, iovec buffer overflow: %d/%d\n", r,
  906. MAX_MSG_CHUNKS);
  907. return -1;
  908. }
  909. /*
  910. * Send a reply, either positive or negative, to the client
  911. */
  912. static int rpc_send(rpc_ctx_t* ctx)
  913. {
  914. struct iovec v[MAX_MSG_CHUNKS];
  915. int f;
  916. int n;
  917. int ret;
  918. /* Send the reply only once */
  919. if (ctx->reply_sent) return 1;
  920. else ctx->reply_sent = 1;
  921. if ((n=build_iovec(ctx, v, MAX_MSG_CHUNKS))<0)
  922. goto error;
  923. if (ctx->send_h->type==S_FIFO){
  924. /* Open the reply file */
  925. f = open_reply_pipe(ctx->reply_file);
  926. if (f == -1) {
  927. ERR("No reply pipe %s\n", ctx->reply_file);
  928. return -1;
  929. }
  930. ret=tsend_dgram_ev(f, v, n, FIFO_TX_TIMEOUT);
  931. close(f);
  932. }else{
  933. ret=sock_send_v(ctx->send_h, v, n);
  934. }
  935. return (ret>=0)?0:-1;
  936. error:
  937. ERR("rpc_send fifo error\n");
  938. return -1;
  939. }
  940. /*
  941. * Add a chunk to reply
  942. */
  943. static void append_chunk(rpc_ctx_t* ctx, struct text_chunk* l)
  944. {
  945. if (!ctx->last) {
  946. ctx->body = l;
  947. ctx->last = l;
  948. } else {
  949. ctx->last->next = l;
  950. ctx->last = l;
  951. }
  952. }
  953. /*
  954. * Convert a value to data chunk and add it to reply
  955. */
  956. static int print_value(rpc_ctx_t* ctx, char fmt, va_list* ap)
  957. {
  958. struct text_chunk* l;
  959. str str_val;
  960. str* sp;
  961. char buf[256];
  962. switch(fmt) {
  963. case 'd':
  964. case 't':
  965. str_val.s = int2str(va_arg(*ap, int), &str_val.len);
  966. l = new_chunk(&str_val);
  967. if (!l) {
  968. rpc_fault(ctx, 500, "Internal server error while processing"
  969. " line %d", ctx->line_no);
  970. goto err;
  971. }
  972. break;
  973. case 'f':
  974. str_val.s = buf;
  975. str_val.len = snprintf(buf, 256, "%f", va_arg(*ap, double));
  976. if (str_val.len < 0) {
  977. rpc_fault(ctx, 400, "Error While Converting double");
  978. ERR("Error while converting double\n");
  979. goto err;
  980. }
  981. l = new_chunk(&str_val);
  982. if (!l) {
  983. rpc_fault(ctx, 500, "Internal Server Error, line %d",
  984. ctx->line_no);
  985. goto err;
  986. }
  987. break;
  988. case 'b':
  989. str_val.len = 1;
  990. str_val.s = ((va_arg(*ap, int) == 0) ? "0" : "1");
  991. l = new_chunk(&str_val);
  992. if (!l) {
  993. rpc_fault(ctx, 500, "Internal Server Error, line %d",
  994. ctx->line_no);
  995. goto err;
  996. }
  997. break;
  998. case 's':
  999. str_val.s = va_arg(*ap, char*);
  1000. str_val.len = strlen(str_val.s);
  1001. l = new_chunk_escape(&str_val, 0);
  1002. if (!l) {
  1003. rpc_fault(ctx, 500, "Internal Server Error, line %d",
  1004. ctx->line_no);
  1005. goto err;
  1006. }
  1007. break;
  1008. case 'S':
  1009. sp = va_arg(*ap, str*);
  1010. l = new_chunk_escape(sp, 0);
  1011. if (!l) {
  1012. rpc_fault(ctx, 500, "Internal Server Error, line %d",
  1013. ctx->line_no);
  1014. goto err;
  1015. }
  1016. break;
  1017. default:
  1018. rpc_fault(ctx, 500, "Bug In SER (Invalid formatting character %c)", fmt);
  1019. ERR("Invalid formatting character\n");
  1020. goto err;
  1021. }
  1022. l->flags |= CHUNK_POSITIONAL;
  1023. append_chunk(ctx, l);
  1024. return 0;
  1025. err:
  1026. return -1;
  1027. }
  1028. static int rpc_add(rpc_ctx_t* ctx, char* fmt, ...)
  1029. {
  1030. void** void_ptr;
  1031. va_list ap;
  1032. str s = {"", 0};
  1033. struct text_chunk* l;
  1034. va_start(ap, fmt);
  1035. while(*fmt) {
  1036. if (*fmt == '{' || *fmt == '[') {
  1037. void_ptr = va_arg(ap, void**);
  1038. l = new_chunk(&s);
  1039. if (!l) {
  1040. rpc_fault(ctx, 500, "Internal Server Error");
  1041. goto err;
  1042. }
  1043. l->ctx=ctx;
  1044. append_chunk(ctx, l);
  1045. *void_ptr = l;
  1046. } else {
  1047. if (print_value(ctx, *fmt, &ap) < 0) goto err;
  1048. }
  1049. fmt++;
  1050. }
  1051. va_end(ap);
  1052. return 0;
  1053. err:
  1054. va_end(ap);
  1055. return -1;
  1056. }
  1057. #define RPC_BUF_SIZE 1024
  1058. static int rpc_struct_printf(struct text_chunk* c, char* name, char* fmt, ...)
  1059. {
  1060. int n, buf_size;
  1061. char* buf;
  1062. va_list ap;
  1063. str s, nm;
  1064. struct text_chunk* l, *m;
  1065. rpc_ctx_t* ctx;
  1066. ctx=(rpc_ctx_t*)c->ctx;
  1067. buf = (char*)ctl_malloc(RPC_BUF_SIZE);
  1068. if (!buf) {
  1069. rpc_fault(ctx, 500, "Internal Server Error (No memory left)");
  1070. ERR("No memory left\n");
  1071. return -1;
  1072. }
  1073. buf_size = RPC_BUF_SIZE;
  1074. while (1) {
  1075. /* Try to print in the allocated space. */
  1076. va_start(ap, fmt);
  1077. n = vsnprintf(buf, buf_size, fmt, ap);
  1078. va_end(ap);
  1079. /* If that worked, return the string. */
  1080. if (n > -1 && n < buf_size) {
  1081. nm.s = name;
  1082. nm.len = strlen(name);
  1083. m = new_chunk_escape(&nm, 1); /* Escape all characters, including : and , */
  1084. if (!m) {
  1085. rpc_fault(ctx, 500, "Internal Server Error");
  1086. goto err;
  1087. }
  1088. s.s = buf;
  1089. s.len = n;
  1090. l = new_chunk_escape(&s, 1);
  1091. if (!l) {
  1092. rpc_fault(ctx, 500, "Internal Server Error");
  1093. free_chunk(m);
  1094. ERR("Error while creating text_chunk structure");
  1095. goto err;
  1096. }
  1097. l->flags |= CHUNK_MEMBER_VALUE;
  1098. l->next = c->next;
  1099. c->next = l;
  1100. if (c == ctx->last) ctx->last = l;
  1101. m->flags |= CHUNK_MEMBER_NAME;
  1102. m->next = c->next;
  1103. c->next = m;
  1104. if (c == ctx->last) ctx->last = m;
  1105. return 0;
  1106. }
  1107. /* Else try again with more space. */
  1108. if (n > -1) { /* glibc 2.1 */
  1109. buf_size = n + 1; /* precisely what is needed */
  1110. } else { /* glibc 2.0 */
  1111. buf_size *= 2; /* twice the old size */
  1112. }
  1113. if ((buf = ctl_realloc(buf, buf_size)) == 0) {
  1114. rpc_fault(ctx, 500, "Internal Server Error (No memory left)");
  1115. ERR("No memory left\n");
  1116. goto err;
  1117. }
  1118. }
  1119. return 0;
  1120. err:
  1121. if (buf) ctl_free(buf);
  1122. return -1;
  1123. }
  1124. static int rpc_rpl_printf(rpc_ctx_t* ctx, char* fmt, ...)
  1125. {
  1126. int n, buf_size;
  1127. char* buf;
  1128. va_list ap;
  1129. str s;
  1130. struct text_chunk* l;
  1131. buf = (char*)ctl_malloc(RPC_BUF_SIZE);
  1132. if (!buf) {
  1133. rpc_fault(ctx, 500, "Internal Server Error (No memory left)");
  1134. ERR("No memory left\n");
  1135. return -1;
  1136. }
  1137. buf_size = RPC_BUF_SIZE;
  1138. while (1) {
  1139. /* Try to print in the allocated space. */
  1140. va_start(ap, fmt);
  1141. n = vsnprintf(buf, buf_size, fmt, ap);
  1142. va_end(ap);
  1143. /* If that worked, return the string. */
  1144. if (n > -1 && n < buf_size) {
  1145. s.s = buf;
  1146. s.len = n;
  1147. l = new_chunk_escape(&s, 0);
  1148. if (!l) {
  1149. rpc_fault(ctx, 500, "Internal Server Error");
  1150. ERR("Error while creating text_chunk structure");
  1151. goto err;
  1152. }
  1153. append_chunk(ctx, l);
  1154. ctl_free(buf);
  1155. return 0;
  1156. }
  1157. /* Else try again with more space. */
  1158. if (n > -1) { /* glibc 2.1 */
  1159. buf_size = n + 1; /* precisely what is needed */
  1160. } else { /* glibc 2.0 */
  1161. buf_size *= 2; /* twice the old size */
  1162. }
  1163. if ((buf = ctl_realloc(buf, buf_size)) == 0) {
  1164. rpc_fault(ctx, 500, "Internal Server Error (No memory left)");
  1165. ERR("No memory left\n");
  1166. goto err;
  1167. }
  1168. }
  1169. return 0;
  1170. err:
  1171. if (buf) ctl_free(buf);
  1172. return -1;
  1173. }
  1174. static int rpc_scan(rpc_ctx_t* ctx, char* fmt, ...)
  1175. {
  1176. struct text_chunk* l;
  1177. struct rpc_struct* s;
  1178. int* int_ptr;
  1179. char** char_ptr;
  1180. str* str_ptr;
  1181. double* double_ptr;
  1182. void** void_ptr;
  1183. int read;
  1184. str line;
  1185. int nofault;
  1186. int modifiers;
  1187. va_list ap;
  1188. va_start(ap, fmt);
  1189. nofault = 0;
  1190. read = 0;
  1191. modifiers=0;
  1192. while(*fmt) {
  1193. if (read_line(&line.s, &line.len, &ctx->read_h) < 0) {
  1194. va_end(ap);
  1195. return read;
  1196. }
  1197. ctx->line_no++;
  1198. switch(*fmt) {
  1199. case '*': /* start of optional parameters */
  1200. nofault = 1;
  1201. modifiers++;
  1202. break;
  1203. case 'b': /* Bool */
  1204. case 't': /* Date and time */
  1205. case 'd': /* Integer */
  1206. if (!line.len) {
  1207. if(nofault==0)
  1208. rpc_fault(ctx, 400, "Invalid parameter value on line %d",
  1209. ctx->line_no);
  1210. goto error;
  1211. }
  1212. int_ptr = va_arg(ap, int*);
  1213. *int_ptr = strtol(line.s, 0, 0);
  1214. break;
  1215. case 'f': /* double */
  1216. if (!line.len) {
  1217. if(nofault==0)
  1218. rpc_fault(ctx, 400, "Invalid parameter value on line %d",
  1219. ctx->line_no);
  1220. goto error;
  1221. }
  1222. double_ptr = va_arg(ap, double*);
  1223. *double_ptr = strtod(line.s, 0);
  1224. break;
  1225. case 's': /* zero terminated string */
  1226. case 'S': /* str structure */
  1227. l = new_chunk_unescape(&line);
  1228. if (!l) {
  1229. if(nofault==0) {
  1230. rpc_fault(ctx, 500, "Internal Server Error");
  1231. ERR("Not enough memory\n");
  1232. }
  1233. goto error;
  1234. }
  1235. /* Make sure it gets released at the end */
  1236. l->next = ctx->strs;
  1237. ctx->strs = l;
  1238. if (*fmt == 's') {
  1239. char_ptr = va_arg(ap, char**);
  1240. *char_ptr = l->s.s;
  1241. } else {
  1242. str_ptr = va_arg(ap, str*);
  1243. *str_ptr = l->s;
  1244. }
  1245. break;
  1246. case '{':
  1247. void_ptr = va_arg(ap, void**);
  1248. s = new_struct(ctx, &line);
  1249. if (!s) goto error;
  1250. s->next = ctx->structs;
  1251. ctx->structs = s;
  1252. *void_ptr = s;
  1253. break;
  1254. default:
  1255. ERR("Invalid parameter type in formatting string: %c\n", *fmt);
  1256. rpc_fault(ctx, 500, "Server Internal Error (Invalid Formatting Character '%c')", *fmt);
  1257. goto error;
  1258. }
  1259. fmt++;
  1260. read++;
  1261. }
  1262. va_end(ap);
  1263. return read-modifiers;
  1264. error:
  1265. va_end(ap);
  1266. return -(read-modifiers);
  1267. }
  1268. static int rpc_struct_add(struct text_chunk* s, char* fmt, ...)
  1269. {
  1270. static char buf[MAX_LINE_BUFFER];
  1271. str st, *sp;
  1272. void** void_ptr;
  1273. va_list ap;
  1274. struct text_chunk* m, *c;
  1275. rpc_ctx_t* ctx;
  1276. ctx=(rpc_ctx_t*)s->ctx;
  1277. va_start(ap, fmt);
  1278. while(*fmt) {
  1279. /* Member name escaped */
  1280. st.s = va_arg(ap, char*);
  1281. st.len = strlen(st.s);
  1282. m = new_chunk_escape(&st, 1); /* Escape all characters, including : and , */
  1283. if (!m) {
  1284. rpc_fault(ctx, 500, "Internal Server Error");
  1285. goto err;
  1286. }
  1287. m->flags |= CHUNK_MEMBER_NAME;
  1288. if(*fmt=='{' || *fmt=='[') {
  1289. void_ptr = va_arg(ap, void**);
  1290. m->ctx=ctx;
  1291. append_chunk(ctx, m);
  1292. *void_ptr = m;
  1293. } else {
  1294. switch(*fmt) {
  1295. case 'd':
  1296. case 't':
  1297. st.s = int2str(va_arg(ap, int), &st.len);
  1298. c = new_chunk(&st);
  1299. break;
  1300. case 'f':
  1301. st.s = buf;
  1302. st.len = snprintf(buf, 256, "%f", va_arg(ap, double));
  1303. if (st.len < 0) {
  1304. rpc_fault(ctx, 400, "Error While Converting double");
  1305. ERR("Error while converting double\n");
  1306. goto err;
  1307. }
  1308. c = new_chunk(&st);
  1309. break;
  1310. case 'b':
  1311. st.len = 1;
  1312. st.s = ((va_arg(ap, int) == 0) ? "0" : "1");
  1313. c = new_chunk(&st);
  1314. break;
  1315. case 's':
  1316. st.s = va_arg(ap, char*);
  1317. st.len = strlen(st.s);
  1318. c = new_chunk_escape(&st, 1);
  1319. break;
  1320. case 'S':
  1321. sp = va_arg(ap, str*);
  1322. c = new_chunk_escape(sp, 1);
  1323. break;
  1324. default:
  1325. rpc_fault(ctx, 500, "Bug In SER (Invalid formatting character %c)",
  1326. *fmt);
  1327. ERR("Invalid formatting character\n");
  1328. goto err;
  1329. }
  1330. if (!c) {
  1331. rpc_fault(ctx, 500, "Internal Server Error");
  1332. goto err;
  1333. }
  1334. c->flags |= CHUNK_MEMBER_VALUE;
  1335. c->next = s->next;
  1336. s->next = c;
  1337. if (s == ctx->last) ctx->last = c;
  1338. m->next = s->next;
  1339. s->next = m;
  1340. if (s == ctx->last) ctx->last = m;
  1341. }
  1342. fmt++;
  1343. }
  1344. va_end(ap);
  1345. return 0;
  1346. err:
  1347. if (m) free_chunk(m);
  1348. va_end(ap);
  1349. return -1;
  1350. }
  1351. static int find_member(struct text_chunk** value, struct rpc_struct* s, str* member_name)
  1352. {
  1353. struct text_chunk* n, *v;
  1354. n = s->names;
  1355. v = s->values;
  1356. while(n) {
  1357. if (member_name->len == n->s.len &&
  1358. !strncasecmp(member_name->s, n->s.s, n->s.len)) {
  1359. if (n->flags & CHUNK_SEEN) goto skip;
  1360. else {
  1361. *value = v;
  1362. n->flags |= CHUNK_SEEN;
  1363. return 0;
  1364. }
  1365. }
  1366. skip:
  1367. n = n->next;
  1368. v = v->next;
  1369. }
  1370. return 1;
  1371. }
  1372. static int rpc_struct_scan(struct rpc_struct* s, char* fmt, ...)
  1373. {
  1374. struct text_chunk* val;
  1375. va_list ap;
  1376. int* int_ptr;
  1377. double* double_ptr;
  1378. char** char_ptr;
  1379. str* str_ptr;
  1380. str member_name;
  1381. int ret, read;
  1382. read = 0;
  1383. va_start(ap, fmt);
  1384. while(*fmt) {
  1385. member_name.s = va_arg(ap, char*);
  1386. member_name.len = strlen(member_name.s);
  1387. ret = find_member(&val, s, &member_name);
  1388. if (ret > 0) {
  1389. va_end(ap);
  1390. return read;
  1391. }
  1392. switch(*fmt) {
  1393. case 'b': /* Bool */
  1394. case 't': /* Date and time */
  1395. case 'd': /* Integer */
  1396. int_ptr = va_arg(ap, int*);
  1397. if (!val->s.len) {
  1398. rpc_fault(s->ctx, 400, "Invalid Parameter Value");
  1399. goto error;
  1400. }
  1401. /* String in text_chunk is always zero terminated */
  1402. *int_ptr = strtol(val->s.s, 0, 0);
  1403. break;
  1404. case 'f': /* double */
  1405. double_ptr = va_arg(ap, double*);
  1406. if (!val->s.len) {
  1407. rpc_fault(s->ctx, 400, "Invalid Parameter Value");
  1408. goto error;
  1409. }
  1410. /* String in text_chunk is always zero terminated */
  1411. *double_ptr = strtod(val->s.s, 0);
  1412. break;
  1413. case 's': /* zero terminated string */
  1414. char_ptr = va_arg(ap, char**);
  1415. /* String in text_chunk is always zero terminated */
  1416. *char_ptr = val->s.s;
  1417. break;
  1418. case 'S': /* str structure */
  1419. str_ptr = va_arg(ap, str*);
  1420. str_ptr->len = strlen(str_ptr->s);
  1421. *str_ptr = val->s;
  1422. break;
  1423. default:
  1424. rpc_fault(s->ctx, 500, "Invalid character in formatting string '%c'", *fmt);
  1425. ERR("Invalid parameter type in formatting string: %c\n", *fmt);
  1426. goto error;
  1427. }
  1428. fmt++;
  1429. read++;
  1430. }
  1431. va_end(ap);
  1432. return read;
  1433. error:
  1434. va_end(ap);
  1435. return -read;
  1436. }
  1437. #endif