fifo_server.c 38 KB

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