1 /*
2 * Heartbeat messaging object.
3 *
4 * Copyright (C) 2000 Alan Robertson <alanr@unix.sh>
5 *
6 * This software licensed under the GNU LGPL.
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 *
22 */
23
24 #include <lha_internal.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <time.h>
29 #include <errno.h>
30 #include <sys/utsname.h>
31 #include <ha_msg.h>
32 #include <unistd.h>
33 #include <clplumbing/cl_log.h>
34 #include <clplumbing/ipc.h>
35 #include <clplumbing/base64.h>
36 #include <clplumbing/netstring.h>
37 #include <glib.h>
38 #include <clplumbing/cl_uuid.h>
39 #include <compress.h>
40 #include <clplumbing/timers.h>
41 #include <clplumbing/cl_signal.h>
42
43 #define MAXMSGLINE 512
44 #define MINFIELDS 30
45 #define NEWLINE "\n"
46
47
48 #define NEEDAUTH 1
49 #define NOAUTH 0
50 #define MAX_INT_LEN 64
51 #define MAX_NAME_LEN 255
52 #define UUID_SLEN 64
53 #define MAXCHILDMSGLEN 512
54
55 static int compression_threshold = (128*1024);
56
57 static enum cl_msgfmt msgfmt = MSGFMT_NVPAIR;
58 static gboolean use_traditional_compression = FALSE;
59
60 const char*
61 FT_strings[]={
62 "0",
63 "1",
64 "2",
65 "3",
66 "4",
67 "5",
68 "6",
69 "7",
70 "8",
71 "9"
72 };
73
74 #undef DOAUDITS
75 #define DOAUDITS
76
77 #undef DOPARANOIDAUDITS
78 /* #define DOPARANOIDAUDITS */
79
80 #ifdef DOAUDITS
81 void ha_msg_audit(const struct ha_msg* msg);
82 # define AUDITMSG(msg) ha_msg_audit(msg)
83 # ifdef DOPARANOIDAUDITS
84 # define PARANOIDAUDITMSG(msg) ha_msg_audit(msg)
85 # else
86 # define PARANOIDAUDITMSG(msg) /*nothing*/
87 # endif
88 #else
89 # define AUDITMSG(msg) /*nothing*/
90 # define PARANOIDAUDITMSG(msg) /*nothing*/
91 #endif
92
93
94 static volatile hb_msg_stats_t* msgstats = NULL;
95
96 gboolean cl_msg_quiet_fmterr = FALSE;
97
98 extern int netstring_format;
99
100 static struct ha_msg* wirefmt2msg_ll(const char* s, size_t length, int need_auth);
101
102 struct ha_msg* string2msg_ll(const char * s, size_t length, int need_auth, int depth);
103
104 extern int struct_stringlen(size_t namlen, size_t vallen, const void* value);
105 extern int struct_netstringlen(size_t namlen, size_t vallen, const void* value);
106 extern int process_netstring_nvpair(struct ha_msg* m, const char* nvpair, int nvlen);
107 static char* msg2wirefmt_ll(struct ha_msg*m, size_t* len, gboolean need_compress);
108 extern GHashTable* CompressFuncs;
109
110
111 void
cl_set_traditional_compression(gboolean value)112 cl_set_traditional_compression(gboolean value)
113 {
114 use_traditional_compression = value;
115 if (use_traditional_compression && CompressFuncs) {
116 cl_log(LOG_WARNING
117 , "Traditional compression selected"
118 ". Realtime behavior will likely be impacted(!)");
119 cl_log(LOG_INFO
120 , "See %s for more information."
121 , HAURL("Ha.cf#traditional_compression_-_controls_compression_mode"));
122 }
123 }
124
125 void
cl_set_compression_threshold(size_t threadhold)126 cl_set_compression_threshold(size_t threadhold)
127 {
128 compression_threshold = threadhold;
129
130 }
131
132 void
cl_msg_setstats(volatile hb_msg_stats_t * stats)133 cl_msg_setstats(volatile hb_msg_stats_t* stats)
134 {
135 msgstats = stats;
136 }
137
138 static int msg_stats_fd = -1;
139
140 static int
cl_msg_stats_open(const char * filename)141 cl_msg_stats_open(const char* filename)
142 {
143 if (filename == NULL){
144 cl_log(LOG_ERR, "%s: filename is NULL", __FUNCTION__);
145 return -1;
146 }
147
148 return open(filename, O_WRONLY|O_CREAT|O_APPEND, 0644);
149
150 }
151
152 static int
cl_msg_stats_close(void)153 cl_msg_stats_close(void)
154 {
155 if (msg_stats_fd > 0){
156 close(msg_stats_fd);
157 }
158
159 msg_stats_fd = -1;
160
161 return HA_OK;
162 }
163
164 #define STATSFILE "/var/log/ha_msg_stats"
165 int
cl_msg_stats_add(longclock_t time,int size)166 cl_msg_stats_add(longclock_t time, int size)
167 {
168 char buf[MAXLINE];
169 int len;
170
171 if (msg_stats_fd < 0){
172 msg_stats_fd = cl_msg_stats_open(STATSFILE);
173 if (msg_stats_fd < 0){
174 cl_log(LOG_ERR, "%s:opening file failed",
175 __FUNCTION__);
176 return HA_FAIL;
177 }
178 }
179
180
181 sprintf(buf, "%lld %d\n", (long long)time, size);
182 len = strnlen(buf, MAXLINE);
183 if (write(msg_stats_fd, buf, len) == len){
184 cl_msg_stats_close();
185 return HA_OK;
186 }
187
188 cl_msg_stats_close();
189
190 return HA_FAIL;;
191
192 }
193
194
195 /* Set default messaging format */
196 void
cl_set_msg_format(enum cl_msgfmt mfmt)197 cl_set_msg_format(enum cl_msgfmt mfmt)
198 {
199 msgfmt = mfmt;
200 }
201
202 void
cl_dump_msgstats(void)203 cl_dump_msgstats(void)
204 {
205 if (msgstats){
206 cl_log(LOG_INFO, "dumping msg stats: "
207 "allocmsgs=%lu",
208 msgstats->allocmsgs);
209 }
210 return;
211 }
212 void
list_cleanup(GList * list)213 list_cleanup(GList* list)
214 {
215 size_t i;
216 for (i = 0; i < g_list_length(list); i++){
217 char* element = g_list_nth_data(list, i);
218 if (element == NULL){
219 cl_log(LOG_WARNING, "list_cleanup:"
220 "element is NULL");
221 continue;
222 }
223 free(element);
224 }
225 g_list_free(list);
226 }
227
228
229
230 /* Create a new (empty) message */
231 struct ha_msg *
ha_msg_new(int nfields)232 ha_msg_new(int nfields)
233 {
234 struct ha_msg * ret;
235 int nalloc;
236
237 ret = MALLOCT(struct ha_msg);
238 if (ret) {
239 ret->nfields = 0;
240
241 if (nfields > MINFIELDS) {
242 nalloc = nfields;
243 } else {
244 nalloc = MINFIELDS;
245 }
246
247 ret->nalloc = nalloc;
248 ret->names = (char **)calloc(sizeof(char *), nalloc);
249 ret->nlens = (size_t *)calloc(sizeof(size_t), nalloc);
250 ret->values = (void **)calloc(sizeof(void *), nalloc);
251 ret->vlens = (size_t *)calloc(sizeof(size_t), nalloc);
252 ret->types = (int*)calloc(sizeof(int), nalloc);
253
254 if (ret->names == NULL || ret->values == NULL
255 || ret->nlens == NULL || ret->vlens == NULL
256 || ret->types == NULL) {
257
258 cl_log(LOG_ERR, "%s"
259 , "ha_msg_new: out of memory for ha_msg");
260 /* It is safe to give this to ha_msg_del() */
261 /* at this point. It's well-enough-formed */
262 ha_msg_del(ret); /*violated property*/
263 ret = NULL;
264 }else if (msgstats) {
265 msgstats->allocmsgs++;
266 msgstats->totalmsgs++;
267 msgstats->lastmsg = time_longclock();
268 }
269 }
270 return(ret);
271 }
272
273 /* Delete (destroy) a message */
274 void
ha_msg_del(struct ha_msg * msg)275 ha_msg_del(struct ha_msg *msg)
276 {
277 if (msg) {
278 int j;
279 PARANOIDAUDITMSG(msg);
280 if (msgstats) {
281 msgstats->allocmsgs--;
282 }
283 if (msg->names) {
284 for (j=0; j < msg->nfields; ++j) {
285 if (msg->names[j]) {
286 free(msg->names[j]);
287 msg->names[j] = NULL;
288 }
289 }
290 free(msg->names);
291 msg->names = NULL;
292 }
293 if (msg->values) {
294 for (j=0; j < msg->nfields; ++j) {
295
296 if (msg->values[j] == NULL){
297 continue;
298 }
299
300 if(msg->types[j] < DIMOF(fieldtypefuncs)){
301 fieldtypefuncs[msg->types[j]].memfree(msg->values[j]);
302 }
303 }
304 free(msg->values);
305 msg->values = NULL;
306 }
307 if (msg->nlens) {
308 free(msg->nlens);
309 msg->nlens = NULL;
310 }
311 if (msg->vlens) {
312 free(msg->vlens);
313 msg->vlens = NULL;
314 }
315 if (msg->types){
316 free(msg->types);
317 msg->types = NULL;
318 }
319 msg->nfields = -1;
320 msg->nalloc = -1;
321 free(msg);
322 }
323 }
324 struct ha_msg*
ha_msg_copy(const struct ha_msg * msg)325 ha_msg_copy(const struct ha_msg *msg)
326 {
327 struct ha_msg* ret;
328 int j;
329
330
331 PARANOIDAUDITMSG(msg);
332 if (msg == NULL || (ret = ha_msg_new(msg->nalloc)) == NULL) {
333 return NULL;
334 }
335
336 ret->nfields = msg->nfields;
337
338 memcpy(ret->nlens, msg->nlens, sizeof(msg->nlens[0])*msg->nfields);
339 memcpy(ret->vlens, msg->vlens, sizeof(msg->vlens[0])*msg->nfields);
340 memcpy(ret->types, msg->types, sizeof(msg->types[0])*msg->nfields);
341
342 for (j=0; j < msg->nfields; ++j) {
343
344 if ((ret->names[j] = malloc(msg->nlens[j]+1)) == NULL) {
345 goto freeandleave;
346 }
347 memcpy(ret->names[j], msg->names[j], msg->nlens[j]+1);
348
349
350 if(msg->types[j] < DIMOF(fieldtypefuncs)){
351 ret->values[j] = fieldtypefuncs[msg->types[j]].dup(msg->values[j],
352 msg->vlens[j]);
353 if (!ret->values[j]){
354 cl_log(LOG_ERR,"duplicating the message field failed");
355 goto freeandleave;
356 }
357 }
358 }
359 return ret;
360
361 freeandleave:
362 /*
363 * ha_msg_del nicely handles partially constructed ha_msgs
364 * so, there's not really a memory leak here at all, but BEAM
365 * thinks there is.
366 */
367 ha_msg_del(ret);/* memory leak */ ret=NULL;
368 return ret;
369 }
370
371 #ifdef DOAUDITS
372 void
ha_msg_audit(const struct ha_msg * msg)373 ha_msg_audit(const struct ha_msg* msg)
374 {
375 int doabort = FALSE;
376 int j;
377
378 if (!msg) {
379 return;
380 }
381 if (!msg) {
382 cl_log(LOG_CRIT, "Message @ %p is not allocated"
383 , msg);
384 abort();
385 }
386 if (msg->nfields < 0) {
387 cl_log(LOG_CRIT, "Message @ %p has negative fields (%d)"
388 , msg, msg->nfields);
389 doabort = TRUE;
390 }
391 if (msg->nalloc < 0) {
392 cl_log(LOG_CRIT, "Message @ %p has negative nalloc (%d)"
393 , msg, msg->nalloc);
394 doabort = TRUE;
395 }
396
397 if (!msg->names) {
398 cl_log(LOG_CRIT
399 , "Message names @ %p is not allocated"
400 , msg->names);
401 doabort = TRUE;
402 }
403 if (!msg->values) {
404 cl_log(LOG_CRIT
405 , "Message values @ %p is not allocated"
406 , msg->values);
407 doabort = TRUE;
408 }
409 if (!msg->nlens) {
410 cl_log(LOG_CRIT
411 , "Message nlens @ %p is not allocated"
412 , msg->nlens);
413 doabort = TRUE;
414 }
415 if (!msg->vlens) {
416 cl_log(LOG_CRIT
417 , "Message vlens @ %p is not allocated"
418 , msg->vlens);
419 doabort = TRUE;
420 }
421 if (doabort) {
422 cl_log_message(LOG_INFO,msg);
423 abort();
424 }
425 for (j=0; j < msg->nfields; ++j) {
426
427 if (msg->nlens[j] == 0){
428 cl_log(LOG_ERR, "zero namelen found in msg");
429 abort();
430 }
431
432 if (msg->types[j] == FT_STRING){
433 if (msg->vlens[j] != strlen(msg->values[j])){
434 cl_log(LOG_ERR, "stringlen does not match");
435 cl_log_message(LOG_INFO,msg);
436 abort();
437 }
438 }
439
440 if (!msg->names[j]) {
441 cl_log(LOG_CRIT, "Message name[%d] @ 0x%p"
442 " is not allocated." ,
443 j, msg->names[j]);
444 abort();
445 }
446 if (msg->types[j] != FT_LIST && !msg->values[j]) {
447 cl_log(LOG_CRIT, "Message value [%d] @ 0x%p"
448 " is not allocated.", j, msg->values[j]);
449 cl_log_message(LOG_INFO, msg);
450 abort();
451 }
452 }
453 }
454 #endif
455
456
457
458 int
ha_msg_expand(struct ha_msg * msg)459 ha_msg_expand(struct ha_msg* msg )
460 {
461 char ** names ;
462 size_t *nlens ;
463 void ** values ;
464 size_t* vlens ;
465 int * types ;
466 int nalloc;
467
468 if(!msg){
469 cl_log(LOG_ERR, "ha_msg_expand:"
470 "input msg is null");
471 return HA_FAIL;
472 }
473
474 names = msg->names;
475 nlens = msg->nlens;
476 values = msg->values;
477 vlens = msg->vlens;
478 types = msg->types;
479
480 nalloc = msg->nalloc + MINFIELDS;
481 msg->names = (char **)calloc(sizeof(char *), nalloc);
482 msg->nlens = (size_t *)calloc(sizeof(size_t), nalloc);
483 msg->values = (void **)calloc(sizeof(void *), nalloc);
484 msg->vlens = (size_t *)calloc(sizeof(size_t), nalloc);
485 msg->types= (int*)calloc(sizeof(int), nalloc);
486
487 if (msg->names == NULL || msg->values == NULL
488 || msg->nlens == NULL || msg->vlens == NULL
489 || msg->types == NULL) {
490
491 cl_log(LOG_ERR, "%s"
492 , " out of memory for ha_msg");
493 return(HA_FAIL);
494 }
495
496 memcpy(msg->names, names, msg->nalloc*sizeof(char *));
497 memcpy(msg->nlens, nlens, msg->nalloc*sizeof(size_t));
498 memcpy(msg->values, values, msg->nalloc*sizeof(void *));
499 memcpy(msg->vlens, vlens, msg->nalloc*sizeof(size_t));
500 memcpy(msg->types, types, msg->nalloc*sizeof(int));
501
502 free(names);
503 free(nlens);
504 free(values);
505 free(vlens);
506 free(types);
507
508 msg->nalloc = nalloc;
509
510 return HA_OK;
511 }
512
513 int
cl_msg_remove_value(struct ha_msg * msg,const void * value)514 cl_msg_remove_value(struct ha_msg* msg, const void* value)
515 {
516 int j;
517
518 if (msg == NULL || value == NULL){
519 cl_log(LOG_ERR, "cl_msg_remove: invalid argument");
520 return HA_FAIL;
521 }
522
523 for (j = 0; j < msg->nfields; ++j){
524 if (value == msg->values[j]){
525 break;
526 }
527 }
528 if (j == msg->nfields){
529 cl_log(LOG_ERR, "cl_msg_remove: field %p not found", value);
530 return HA_FAIL;
531 }
532 return cl_msg_remove_offset(msg, j);
533
534 }
535
536
537 int
cl_msg_remove(struct ha_msg * msg,const char * name)538 cl_msg_remove(struct ha_msg* msg, const char* name)
539 {
540 int j;
541
542 if (msg == NULL || name == NULL){
543 cl_log(LOG_ERR, "cl_msg_remove: invalid argument");
544 return HA_FAIL;
545 }
546
547 for (j = 0; j < msg->nfields; ++j){
548 if (strcmp(name, msg->names[j]) == 0){
549 break;
550 }
551 }
552
553 if (j == msg->nfields){
554 cl_log(LOG_ERR, "cl_msg_remove: field %s not found", name);
555 return HA_FAIL;
556 }
557 return cl_msg_remove_offset(msg, j);
558 }
559
560 int
cl_msg_remove_offset(struct ha_msg * msg,int offset)561 cl_msg_remove_offset(struct ha_msg* msg, int offset)
562 {
563 int j = offset;
564 int i;
565
566 if (j == msg->nfields){
567 cl_log(LOG_ERR, "cl_msg_remove: field %d not found", j);
568 return HA_FAIL;
569 }
570
571 free(msg->names[j]);
572 fieldtypefuncs[msg->types[j]].memfree(msg->values[j]);
573
574 for (i= j + 1; i < msg->nfields ; i++){
575 msg->names[i -1] = msg->names[i];
576 msg->nlens[i -1] = msg->nlens[i];
577 msg->values[i -1] = msg->values[i];
578 msg->vlens[i-1] = msg->vlens[i];
579 msg->types[i-1] = msg->types[i];
580 }
581 msg->nfields--;
582
583
584 return HA_OK;
585 }
586
587
588
589 /* low level implementation for ha_msg_add
590 the caller is responsible to allocate/free memories
591 for @name and @value.
592
593 */
594
595 static int
ha_msg_addraw_ll(struct ha_msg * msg,char * name,size_t namelen,void * value,size_t vallen,int type,int depth)596 ha_msg_addraw_ll(struct ha_msg * msg, char * name, size_t namelen,
597 void * value, size_t vallen, int type, int depth)
598 {
599
600 size_t startlen = sizeof(MSG_START)-1;
601
602
603 int (*addfield) (struct ha_msg* msg, char* name, size_t namelen,
604 void* value, size_t vallen, int depth);
605
606 if (!msg || msg->names == NULL || (msg->values == NULL) ) {
607 cl_log(LOG_ERR, "ha_msg_addraw_ll: cannot add field to ha_msg");
608 return(HA_FAIL);
609 }
610
611 if (msg->nfields >= msg->nalloc) {
612 if( ha_msg_expand(msg) != HA_OK){
613 cl_log(LOG_ERR, "message expanding failed");
614 return(HA_FAIL);
615 }
616
617 }
618
619 if (namelen >= startlen
620 && name[0] == '>'
621 && strncmp(name, MSG_START, startlen) == 0) {
622 if(!cl_msg_quiet_fmterr) {
623 cl_log(LOG_ERR, "ha_msg_addraw_ll: illegal field");
624 }
625 return(HA_FAIL);
626 }
627
628 if (name == NULL || (value == NULL)
629 || namelen <= 0 || vallen < 0) {
630 cl_log(LOG_ERR, "ha_msg_addraw_ll: "
631 "cannot add name/value to ha_msg");
632 return(HA_FAIL);
633 }
634
635 HA_MSG_ASSERT(type < DIMOF(fieldtypefuncs));
636
637 addfield = fieldtypefuncs[type].addfield;
638 if (!addfield ||
639 addfield(msg, name, namelen, value, vallen,depth) != HA_OK){
640 cl_log(LOG_ERR, "ha_msg_addraw_ll: addfield failed");
641 return(HA_FAIL);
642 }
643
644 PARANOIDAUDITMSG(msg);
645
646 return(HA_OK);
647
648
649 }
650
651 static int
ha_msg_addraw(struct ha_msg * msg,const char * name,size_t namelen,const void * value,size_t vallen,int type,int depth)652 ha_msg_addraw(struct ha_msg * msg, const char * name, size_t namelen,
653 const void * value, size_t vallen, int type, int depth)
654 {
655
656 char *cpvalue = NULL;
657 char *cpname = NULL;
658 int ret;
659
660
661 if (namelen == 0){
662 cl_log(LOG_ERR, "%s: Adding a field with 0 name length", __FUNCTION__);
663 return HA_FAIL;
664 }
665
666 if ((cpname = malloc(namelen+1)) == NULL) {
667 cl_log(LOG_ERR, "ha_msg_addraw: no memory for string (name)");
668 return(HA_FAIL);
669 }
670 strncpy(cpname, name, namelen);
671 cpname[namelen] = EOS;
672
673 HA_MSG_ASSERT(type < DIMOF(fieldtypefuncs));
674
675 if (fieldtypefuncs[type].dup){
676 cpvalue = fieldtypefuncs[type].dup(value, vallen);
677 }
678 if (cpvalue == NULL){
679 cl_log(LOG_ERR, "ha_msg_addraw: copying message failed");
680 free(cpname);
681 return(HA_FAIL);
682 }
683
684 ret = ha_msg_addraw_ll(msg, cpname, namelen, cpvalue, vallen
685 , type, depth);
686
687 if (ret != HA_OK){
688 cl_log(LOG_ERR, "ha_msg_addraw(): ha_msg_addraw_ll failed");
689 free(cpname);
690 fieldtypefuncs[type].memfree(cpvalue);
691 }
692
693 return(ret);
694
695 }
696
697 /*Add a null-terminated name and binary value to a message*/
698 int
ha_msg_addbin(struct ha_msg * msg,const char * name,const void * value,size_t vallen)699 ha_msg_addbin(struct ha_msg * msg, const char * name,
700 const void * value, size_t vallen)
701 {
702
703 return(ha_msg_addraw(msg, name, strlen(name),
704 value, vallen, FT_BINARY, 0));
705
706 }
707
708 int
ha_msg_adduuid(struct ha_msg * msg,const char * name,const cl_uuid_t * u)709 ha_msg_adduuid(struct ha_msg* msg, const char *name, const cl_uuid_t* u)
710 {
711 return(ha_msg_addraw(msg, name, strlen(name),
712 u, sizeof(cl_uuid_t), FT_BINARY, 0));
713 }
714
715 /*Add a null-terminated name and struct value to a message*/
716 int
ha_msg_addstruct(struct ha_msg * msg,const char * name,const void * value)717 ha_msg_addstruct(struct ha_msg * msg, const char * name, const void * value)
718 {
719 const struct ha_msg* childmsg = (const struct ha_msg*) value;
720
721 if (get_netstringlen(childmsg) > MAXCHILDMSGLEN
722 || get_stringlen(childmsg) > MAXCHILDMSGLEN) {
723 /*cl_log(LOG_WARNING,
724 "%s: childmsg too big (name=%s, nslen=%d, len=%d)."
725 " Use ha_msg_addstruct_compress() instead.",
726 __FUNCTION__, name, get_netstringlen(childmsg),
727 get_stringlen(childmsg));
728 */
729 }
730
731 return ha_msg_addraw(msg, name, strlen(name), value,
732 sizeof(struct ha_msg), FT_STRUCT, 0);
733 }
734
735 int
ha_msg_addstruct_compress(struct ha_msg * msg,const char * name,const void * value)736 ha_msg_addstruct_compress(struct ha_msg * msg, const char * name, const void * value)
737 {
738
739 if (use_traditional_compression){
740 return ha_msg_addraw(msg, name, strlen(name), value,
741 sizeof(struct ha_msg), FT_STRUCT, 0);
742 }else{
743 return ha_msg_addraw(msg, name, strlen(name), value,
744 sizeof(struct ha_msg), FT_UNCOMPRESS, 0);
745 }
746 }
747
748 int
ha_msg_add_int(struct ha_msg * msg,const char * name,int value)749 ha_msg_add_int(struct ha_msg * msg, const char * name, int value)
750 {
751 char buf[MAX_INT_LEN];
752 snprintf(buf, MAX_INT_LEN, "%d", value);
753 return (ha_msg_add(msg, name, buf));
754 }
755
756 int
ha_msg_mod_int(struct ha_msg * msg,const char * name,int value)757 ha_msg_mod_int(struct ha_msg * msg, const char * name, int value)
758 {
759 char buf[MAX_INT_LEN];
760 snprintf(buf, MAX_INT_LEN, "%d", value);
761 return (cl_msg_modstring(msg, name, buf));
762 }
763
764 int
ha_msg_value_int(const struct ha_msg * msg,const char * name,int * value)765 ha_msg_value_int(const struct ha_msg * msg, const char * name, int* value)
766 {
767 const char* svalue = ha_msg_value(msg, name);
768 if(NULL == svalue) {
769 return HA_FAIL;
770 }
771 *value = atoi(svalue);
772 return HA_OK;
773 }
774
775 int
ha_msg_add_ul(struct ha_msg * msg,const char * name,unsigned long value)776 ha_msg_add_ul(struct ha_msg * msg, const char * name, unsigned long value)
777 {
778 char buf[MAX_INT_LEN];
779 snprintf(buf, MAX_INT_LEN, "%lu", value);
780 return (ha_msg_add(msg, name, buf));
781 }
782
783 int
ha_msg_mod_ul(struct ha_msg * msg,const char * name,unsigned long value)784 ha_msg_mod_ul(struct ha_msg * msg, const char * name, unsigned long value)
785 {
786 char buf[MAX_INT_LEN];
787 snprintf(buf, MAX_INT_LEN, "%lu", value);
788 return (cl_msg_modstring(msg, name, buf));
789 }
790
791 int
ha_msg_value_ul(const struct ha_msg * msg,const char * name,unsigned long * value)792 ha_msg_value_ul(const struct ha_msg * msg, const char * name, unsigned long* value)
793 {
794 const char* svalue = ha_msg_value(msg, name);
795 if(NULL == svalue) {
796 return HA_FAIL;
797 }
798 *value = strtoul(svalue, NULL, 10);
799 return HA_OK;
800 }
801
802 /*
803 * ha_msg_value_str_list()/ha_msg_add_str_list():
804 * transform a string list suitable for putting into an ha_msg is by a convention
805 * of naming the fields into the following format:
806 * listname1=foo
807 * listname2=bar
808 * listname3=stuff
809 * etc.
810 */
811
812 GList*
ha_msg_value_str_list(struct ha_msg * msg,const char * name)813 ha_msg_value_str_list(struct ha_msg * msg, const char * name)
814 {
815
816 int i = 1;
817 int len = 0;
818 const char* value;
819 char* element;
820 GList* list = NULL;
821
822
823 if( NULL==msg||NULL==name||strnlen(name, MAX_NAME_LEN)>=MAX_NAME_LEN ){
824 return NULL;
825 }
826 len = cl_msg_list_length(msg,name);
827 for(i=0; i<len; i++) {
828 value = cl_msg_list_nth_data(msg,name,i);
829 if (NULL == value) {
830 break;
831 }
832 element = g_strdup(value);
833 list = g_list_append(list, element);
834 }
835 return list;
836 }
837
838
839
840 static void
pair_to_msg(gpointer key,gpointer value,gpointer user_data)841 pair_to_msg(gpointer key, gpointer value, gpointer user_data)
842 {
843 struct ha_msg* msg = (struct ha_msg*)user_data;
844 if( HA_OK != ha_msg_add(msg, key, value)) {
845 cl_log(LOG_ERR, "ha_msg_add in pair_to_msg failed");
846 }
847 }
848
849
850 static struct ha_msg*
str_table_to_msg(GHashTable * hash_table)851 str_table_to_msg(GHashTable* hash_table)
852 {
853 struct ha_msg* hash_msg;
854
855 if ( NULL == hash_table) {
856 return NULL;
857 }
858
859 hash_msg = ha_msg_new(5);
860 g_hash_table_foreach(hash_table, pair_to_msg, hash_msg);
861 return hash_msg;
862 }
863
864
865 static GHashTable*
msg_to_str_table(struct ha_msg * msg)866 msg_to_str_table(struct ha_msg * msg)
867 {
868 int i;
869 GHashTable* hash_table;
870
871 if ( NULL == msg) {
872 return NULL;
873 }
874
875 hash_table = g_hash_table_new(g_str_hash, g_str_equal);
876
877 for (i = 0; i < msg->nfields; i++) {
878 if( FT_STRING != msg->types[i] ) {
879 continue;
880 }
881 g_hash_table_insert(hash_table,
882 g_strndup(msg->names[i],msg->nlens[i]),
883 g_strndup(msg->values[i],msg->vlens[i]));
884 }
885 return hash_table;
886 }
887
888 GHashTable*
ha_msg_value_str_table(struct ha_msg * msg,const char * name)889 ha_msg_value_str_table(struct ha_msg * msg, const char * name)
890 {
891 struct ha_msg* hash_msg;
892 GHashTable * hash_table = NULL;
893
894 if (NULL == msg || NULL == name) {
895 return NULL;
896 }
897
898 hash_msg = cl_get_struct(msg, name);
899 if (NULL == hash_msg) {
900 return NULL;
901 }
902 hash_table = msg_to_str_table(hash_msg);
903 return hash_table;
904 }
905
906 int
ha_msg_add_str_table(struct ha_msg * msg,const char * name,GHashTable * hash_table)907 ha_msg_add_str_table(struct ha_msg * msg, const char * name,
908 GHashTable* hash_table)
909 {
910 struct ha_msg* hash_msg;
911 if (NULL == msg || NULL == name || NULL == hash_table) {
912 return HA_FAIL;
913 }
914
915 hash_msg = str_table_to_msg(hash_table);
916 if( HA_OK != ha_msg_addstruct(msg, name, hash_msg)) {
917 ha_msg_del(hash_msg);
918 cl_log(LOG_ERR
919 , "ha_msg_addstruct in ha_msg_add_str_table failed");
920 return HA_FAIL;
921 }
922 ha_msg_del(hash_msg);
923 return HA_OK;
924 }
925
926 int
ha_msg_mod_str_table(struct ha_msg * msg,const char * name,GHashTable * hash_table)927 ha_msg_mod_str_table(struct ha_msg * msg, const char * name,
928 GHashTable* hash_table)
929 {
930 struct ha_msg* hash_msg;
931 if (NULL == msg || NULL == name || NULL == hash_table) {
932 return HA_FAIL;
933 }
934
935 hash_msg = str_table_to_msg(hash_table);
936 if( HA_OK != cl_msg_modstruct(msg, name, hash_msg)) {
937 ha_msg_del(hash_msg);
938 cl_log(LOG_ERR
939 , "ha_msg_modstruct in ha_msg_mod_str_table failed");
940 return HA_FAIL;
941 }
942 ha_msg_del(hash_msg);
943 return HA_OK;
944 }
945
946 int
cl_msg_list_add_string(struct ha_msg * msg,const char * name,const char * value)947 cl_msg_list_add_string(struct ha_msg* msg, const char* name, const char* value)
948 {
949 GList* list = NULL;
950 int ret;
951
952 if(!msg || !name || !value){
953 cl_log(LOG_ERR, "cl_msg_list_add_string: input invalid");
954 return HA_FAIL;
955 }
956
957
958 list = g_list_append(list, UNCONST_CAST_POINTER(gpointer, value));
959 if (!list){
960 cl_log(LOG_ERR, "cl_msg_list_add_string: append element to"
961 "a glist failed");
962 return HA_FAIL;
963 }
964
965 ret = ha_msg_addraw(msg, name, strlen(name), list,
966 string_list_pack_length(list),
967 FT_LIST, 0);
968
969 g_list_free(list);
970
971 return ret;
972
973 }
974
975 /* Add a null-terminated name and value to a message */
976 int
ha_msg_add(struct ha_msg * msg,const char * name,const char * value)977 ha_msg_add(struct ha_msg * msg, const char * name, const char * value)
978 {
979 if(name == NULL || value == NULL) {
980 return HA_FAIL;
981 }
982 return(ha_msg_nadd(msg, name, strlen(name), value, strlen(value)));
983 }
984
985 /* Add a name/value pair to a message (with sizes for name and value) */
986 int
ha_msg_nadd(struct ha_msg * msg,const char * name,int namelen,const char * value,int vallen)987 ha_msg_nadd(struct ha_msg * msg, const char * name, int namelen
988 , const char * value, int vallen)
989 {
990 return(ha_msg_addraw(msg, name, namelen, value, vallen, FT_STRING, 0));
991
992 }
993
994 /* Add a name/value/type to a message (with sizes for name and value) */
995 int
ha_msg_nadd_type(struct ha_msg * msg,const char * name,int namelen,const char * value,int vallen,int type)996 ha_msg_nadd_type(struct ha_msg * msg, const char * name, int namelen
997 , const char * value, int vallen, int type)
998 {
999 return(ha_msg_addraw(msg, name, namelen, value, vallen, type, 0));
1000
1001 }
1002
1003
1004
1005 /* Add a "name=value" line to the name, value pairs in a message */
1006 static int
ha_msg_add_nv_depth(struct ha_msg * msg,const char * nvline,const char * bufmax,int depth)1007 ha_msg_add_nv_depth(struct ha_msg* msg, const char * nvline,
1008 const char * bufmax, int depth)
1009 {
1010 int namelen;
1011 const char * valp;
1012 int vallen;
1013
1014 if (!nvline) {
1015 cl_log(LOG_ERR, "ha_msg_add_nv: NULL nvline");
1016 return(HA_FAIL);
1017 }
1018 /* How many characters before the '='? */
1019 if ((namelen = strcspn(nvline, EQUAL)) <= 0
1020 || nvline[namelen] != '=') {
1021 if (!cl_msg_quiet_fmterr) {
1022 cl_log(LOG_WARNING
1023 , "ha_msg_add_nv_depth: line doesn't contain '='");
1024 cl_log(LOG_INFO, "%s", nvline);
1025 }
1026 return(HA_FAIL);
1027 }
1028 valp = nvline + namelen +1; /* Point just *past* the '=' */
1029 if (valp >= bufmax){
1030 return HA_FAIL;
1031 }
1032 vallen = strcspn(valp, NEWLINE);
1033 if ((valp + vallen) >= bufmax){
1034 return HA_FAIL;
1035 }
1036
1037 if (vallen == 0){
1038 valp = NULL;
1039 }
1040 /* Call ha_msg_nadd to actually add the name/value pair */
1041 return(ha_msg_addraw(msg, nvline, namelen, valp, vallen
1042 , FT_STRING, depth));
1043
1044 }
1045
1046 int
ha_msg_add_nv(struct ha_msg * msg,const char * nvline,const char * bufmax)1047 ha_msg_add_nv(struct ha_msg* msg, const char * nvline,
1048 const char * bufmax)
1049 {
1050
1051 return(ha_msg_add_nv_depth(msg, nvline, bufmax, 0));
1052
1053 }
1054
1055
1056 static void *
cl_get_value(const struct ha_msg * msg,const char * name,size_t * vallen,int * type)1057 cl_get_value(const struct ha_msg * msg, const char * name,
1058 size_t * vallen, int *type)
1059 {
1060
1061 int j;
1062 if (!msg || !msg->names || !msg->values) {
1063 cl_log(LOG_ERR, "%s: wrong argument (%s)",
1064 __FUNCTION__, name);
1065 return(NULL);
1066 }
1067
1068 PARANOIDAUDITMSG(msg);
1069 for (j=0; j < msg->nfields; ++j) {
1070 const char *local_name = msg->names[j];
1071 if (name[0] == local_name[0]
1072 && strcmp(name, local_name) == 0) {
1073 if (vallen){
1074 *vallen = msg->vlens[j];
1075 }
1076 if (type){
1077 *type = msg->types[j];
1078 }
1079 return(msg->values[j]);
1080 }
1081 }
1082 return(NULL);
1083 }
1084
1085 static void *
cl_get_value_mutate(struct ha_msg * msg,const char * name,size_t * vallen,int * type)1086 cl_get_value_mutate(struct ha_msg * msg, const char * name,
1087 size_t * vallen, int *type)
1088 {
1089
1090 int j;
1091 if (!msg || !msg->names || !msg->values) {
1092 cl_log(LOG_ERR, "%s: wrong argument",
1093 __FUNCTION__);
1094 return(NULL);
1095 }
1096
1097 AUDITMSG(msg);
1098 for (j=0; j < msg->nfields; ++j) {
1099 if (strcmp(name, msg->names[j]) == 0) {
1100 int tp = msg->types[j];
1101 if (fieldtypefuncs[tp].pregetaction){
1102 fieldtypefuncs[tp].pregetaction(msg, j);
1103 }
1104
1105 if (vallen){
1106 *vallen = msg->vlens[j];
1107 }
1108 if (type){
1109 *type = msg->types[j];
1110 }
1111 return(msg->values[j]);
1112 }
1113 }
1114 return(NULL);
1115 }
1116
1117
1118 const void *
cl_get_binary(const struct ha_msg * msg,const char * name,size_t * vallen)1119 cl_get_binary(const struct ha_msg *msg,
1120 const char * name, size_t * vallen)
1121 {
1122
1123 const void *ret;
1124 int type;
1125
1126 ret = cl_get_value( msg, name, vallen, &type);
1127
1128 if (ret == NULL){
1129 /*
1130 cl_log(LOG_WARNING, "field %s not found", name);
1131 cl_log_message(msg);
1132 */
1133 return(NULL);
1134 }
1135 if ( type != FT_BINARY){
1136 cl_log(LOG_WARNING, "field %s is not binary", name);
1137 cl_log_message(LOG_WARNING, msg);
1138 return(NULL);
1139 }
1140
1141 return(ret);
1142 }
1143
1144 /* UUIDs are stored with a machine-independent byte ordering (even though it's binary) */
1145 int
cl_get_uuid(const struct ha_msg * msg,const char * name,cl_uuid_t * retval)1146 cl_get_uuid(const struct ha_msg *msg, const char * name, cl_uuid_t* retval)
1147 {
1148 const void * vret;
1149 size_t vretsize;
1150
1151 cl_uuid_clear(retval);
1152
1153 if ((vret = cl_get_binary(msg, name, &vretsize)/*discouraged function*/) == NULL) {
1154 /* But perfectly portable in this case */
1155 return HA_FAIL;
1156 }
1157 if (vretsize != sizeof(cl_uuid_t)) {
1158 cl_log(LOG_WARNING, "Binary field %s is not a uuid.", name);
1159 cl_log(LOG_INFO, "expecting %d bytes, got %d bytes",
1160 (int)sizeof(cl_uuid_t), (int)vretsize);
1161 cl_log_message(LOG_INFO, msg);
1162 return HA_FAIL;
1163 }
1164 memcpy(retval, vret, sizeof(cl_uuid_t));
1165 return HA_OK;
1166 }
1167
1168 const char *
cl_get_string(const struct ha_msg * msg,const char * name)1169 cl_get_string(const struct ha_msg *msg, const char *name)
1170 {
1171
1172 const void *ret;
1173 int type;
1174 ret = cl_get_value( msg, name, NULL, &type);
1175
1176 if (ret == NULL || type != FT_STRING){
1177 return(NULL);
1178 }
1179
1180 return(ret);
1181
1182 }
1183
1184 int
cl_get_type(const struct ha_msg * msg,const char * name)1185 cl_get_type(const struct ha_msg *msg, const char *name)
1186 {
1187
1188 const void *ret;
1189 int type;
1190
1191 ret = cl_get_value( msg, name, NULL, &type);
1192
1193 if (ret == NULL) {
1194 return -1;
1195 }
1196 if (type < 0){
1197 cl_log(LOG_WARNING, "field %s not a valid type"
1198 , name);
1199 return(-1);
1200 }
1201
1202 return(type);
1203
1204 }
1205
1206 /*
1207 struct ha_msg *
1208 cl_get_struct(const struct ha_msg *msg, const char* name)
1209 {
1210 struct ha_msg* ret;
1211 int type;
1212 size_t vallen;
1213
1214 ret = cl_get_value(msg, name, &vallen, &type);
1215
1216 if (ret == NULL ){
1217 return(NULL);
1218 }
1219
1220 switch(type){
1221
1222 case FT_STRUCT:
1223 break;
1224
1225 default:
1226 cl_log(LOG_ERR, "%s: field %s is not a struct (%d)",
1227 __FUNCTION__, name, type);
1228 return NULL;
1229 }
1230
1231 return ret;
1232 }
1233 */
1234
1235
1236 struct ha_msg *
cl_get_struct(struct ha_msg * msg,const char * name)1237 cl_get_struct(struct ha_msg *msg, const char* name)
1238 {
1239 struct ha_msg* ret;
1240 int type = -1;
1241 size_t vallen;
1242
1243 ret = cl_get_value_mutate(msg, name, &vallen, &type);
1244
1245 if (ret == NULL ){
1246 return(NULL);
1247 }
1248
1249 switch(type){
1250
1251 case FT_UNCOMPRESS:
1252 case FT_STRUCT:
1253 break;
1254
1255 default:
1256 cl_log(LOG_ERR, "%s: field %s is not a struct (%d)",
1257 __FUNCTION__, name, type);
1258 return NULL;
1259 }
1260
1261 return ret;
1262 }
1263
1264
1265 int
cl_msg_list_length(struct ha_msg * msg,const char * name)1266 cl_msg_list_length(struct ha_msg* msg, const char* name)
1267 {
1268 GList* ret;
1269 int type;
1270
1271 ret = cl_get_value( msg, name, NULL, &type);
1272
1273 if ( ret == NULL || type != FT_LIST){
1274 return -1;
1275 }
1276
1277 return g_list_length(ret);
1278
1279 }
1280
1281
1282 void*
cl_msg_list_nth_data(struct ha_msg * msg,const char * name,int n)1283 cl_msg_list_nth_data(struct ha_msg* msg, const char* name, int n)
1284 {
1285 GList* ret;
1286 int type;
1287
1288 ret = cl_get_value( msg, name, NULL, &type);
1289
1290 if ( ret == NULL || type != FT_LIST){
1291 cl_log(LOG_WARNING, "field %s not found "
1292 " or type mismatch", name);
1293 return NULL;
1294 }
1295
1296 return g_list_nth_data(ret, n);
1297
1298 }
1299
1300 int
cl_msg_add_list(struct ha_msg * msg,const char * name,GList * list)1301 cl_msg_add_list(struct ha_msg* msg, const char* name, GList* list)
1302 {
1303 int ret;
1304
1305 if(msg == NULL|| name ==NULL || list == NULL){
1306 cl_log(LOG_ERR, "cl_msg_add_list:"
1307 "invalid arguments");
1308 return HA_FAIL;
1309 }
1310
1311 ret = ha_msg_addraw(msg, name, strlen(name), list,
1312 string_list_pack_length(list),
1313 FT_LIST, 0);
1314
1315 return ret;
1316 }
1317
1318 GList*
cl_msg_get_list(struct ha_msg * msg,const char * name)1319 cl_msg_get_list(struct ha_msg* msg, const char* name)
1320 {
1321 GList* ret;
1322 int type;
1323
1324 ret = cl_get_value( msg, name, NULL, &type);
1325
1326 if ( ret == NULL || type != FT_LIST){
1327 cl_log(LOG_WARNING, "field %s not found "
1328 " or type mismatch", name);
1329 return NULL;
1330 }
1331
1332 return ret;
1333 }
1334
1335
1336 int
cl_msg_add_list_str(struct ha_msg * msg,const char * name,char ** buf,size_t n)1337 cl_msg_add_list_str(struct ha_msg* msg, const char* name,
1338 char** buf, size_t n)
1339 {
1340 GList* list = NULL;
1341 int i;
1342 int ret = HA_FAIL;
1343
1344 if (n <= 0 || buf == NULL|| name ==NULL ||msg == NULL){
1345 cl_log(LOG_ERR, "%s:"
1346 "invalid parameter(%s)",
1347 !n <= 0?"n is negative or zero":
1348 !buf?"buf is NULL":
1349 !name?"name is NULL":
1350 "msg is NULL",__FUNCTION__);
1351 return HA_FAIL;
1352 }
1353
1354 for ( i = 0; i < n; i++){
1355 if (buf[i] == NULL){
1356 cl_log(LOG_ERR, "%s: %dth element in buf is null",
1357 __FUNCTION__, i);
1358 goto free_and_out;
1359 }
1360 list = g_list_append(list, buf[i]);
1361 if (list == NULL){
1362 cl_log(LOG_ERR, "%s:adding integer to list failed",
1363 __FUNCTION__);
1364 goto free_and_out;
1365 }
1366 }
1367
1368 ret = ha_msg_addraw(msg, name, strlen(name), list,
1369 string_list_pack_length(list),
1370 FT_LIST, 0);
1371
1372 free_and_out:
1373 if (list){
1374 g_list_free(list);
1375 list = NULL;
1376 }
1377 return ret;
1378 }
1379
1380 static void
list_element_free(gpointer data,gpointer userdata)1381 list_element_free(gpointer data, gpointer userdata)
1382 {
1383 if (data){
1384 g_free(data);
1385 }
1386 }
1387
1388 int
cl_msg_add_list_int(struct ha_msg * msg,const char * name,int * buf,size_t n)1389 cl_msg_add_list_int(struct ha_msg* msg, const char* name,
1390 int* buf, size_t n)
1391 {
1392
1393 GList* list = NULL;
1394 size_t i;
1395 int ret = HA_FAIL;
1396
1397 if (n <= 0 || buf == NULL|| name ==NULL ||msg == NULL){
1398 cl_log(LOG_ERR, "cl_msg_add_list_int:"
1399 "invalid parameter(%s)",
1400 !n <= 0?"n is negative or zero":
1401 !buf?"buf is NULL":
1402 !name?"name is NULL":
1403 "msg is NULL");
1404 goto free_and_out;
1405 }
1406
1407 for ( i = 0; i < n; i++){
1408 char intstr[MAX_INT_LEN];
1409 sprintf(intstr,"%d", buf[i]);
1410 list = g_list_append(list, g_strdup(intstr));
1411 if (list == NULL){
1412 cl_log(LOG_ERR, "cl_msg_add_list_int:"
1413 "adding integer to list failed");
1414 goto free_and_out;
1415 }
1416 }
1417
1418 ret = ha_msg_addraw(msg, name, strlen(name), list,
1419 string_list_pack_length(list),
1420 FT_LIST, 0);
1421 free_and_out:
1422 if (list){
1423 g_list_foreach(list,list_element_free , NULL);
1424 g_list_free(list);
1425 list = NULL;
1426 }
1427
1428 return ret;
1429 }
1430 int
cl_msg_get_list_int(struct ha_msg * msg,const char * name,int * buf,size_t * n)1431 cl_msg_get_list_int(struct ha_msg* msg, const char* name,
1432 int* buf, size_t* n)
1433 {
1434 GList* list;
1435 size_t len;
1436 int i;
1437 GList* list_element;
1438
1439
1440 if (n == NULL || buf == NULL|| name ==NULL ||msg == NULL){
1441 cl_log(LOG_ERR, "cl_msg_get_list_int:"
1442 "invalid parameter(%s)",
1443 !n?"n is NULL":
1444 !buf?"buf is NULL":
1445 !name?"name is NULL":
1446 "msg is NULL");
1447 return HA_FAIL;
1448 }
1449
1450 list = cl_msg_get_list(msg, name);
1451 if (list == NULL){
1452 cl_log(LOG_ERR, "cl_msg_get_list_int:"
1453 "list of integers %s not found", name);
1454 return HA_FAIL;
1455 }
1456
1457 len = g_list_length(list);
1458 if (len > *n){
1459 cl_log(LOG_ERR, "cl_msg_get_list_int:"
1460 "buffer too small: *n=%ld, required len=%ld",
1461 (long)*n, (long)len);
1462 *n = len;
1463 return HA_FAIL;
1464 }
1465
1466 *n = len;
1467 i = 0;
1468 list_element = g_list_first(list);
1469 while( list_element != NULL){
1470 char* intstr = list_element->data;
1471 if (intstr == NULL){
1472 cl_log(LOG_ERR, "cl_msg_get_list_int:"
1473 "element data is NULL");
1474 return HA_FAIL;
1475 }
1476
1477 if (sscanf(intstr,"%d", &buf[i]) != 1){
1478 cl_log(LOG_ERR, "cl_msg_get_list_int:"
1479 "element data is NULL");
1480 return HA_FAIL;
1481 }
1482
1483 i++;
1484 list_element = g_list_next(list_element);
1485 }
1486
1487 return HA_OK;
1488 }
1489
1490 int
cl_msg_replace_value(struct ha_msg * msg,const void * old_value,const void * value,size_t vlen,int type)1491 cl_msg_replace_value(struct ha_msg* msg, const void *old_value,
1492 const void* value, size_t vlen, int type)
1493 {
1494 int j;
1495
1496 if (msg == NULL || old_value == NULL) {
1497 cl_log(LOG_ERR, "cl_msg_replace: invalid argument");
1498 return HA_FAIL;
1499 }
1500
1501 for (j = 0; j < msg->nfields; ++j){
1502 if (old_value == msg->values[j]){
1503 break;
1504 }
1505 }
1506 if (j == msg->nfields){
1507 cl_log(LOG_ERR, "cl_msg_replace: field %p not found", old_value);
1508 return HA_FAIL;
1509 }
1510 return cl_msg_replace(msg, j, value, vlen, type);
1511 }
1512
1513 /*this function is for internal use only*/
1514 int
cl_msg_replace(struct ha_msg * msg,int index,const void * value,size_t vlen,int type)1515 cl_msg_replace(struct ha_msg* msg, int index,
1516 const void* value, size_t vlen, int type)
1517 {
1518 void * newv ;
1519 int newlen = vlen;
1520 int oldtype;
1521
1522 PARANOIDAUDITMSG(msg);
1523 if (msg == NULL || value == NULL) {
1524 cl_log(LOG_ERR, "%s: NULL input.", __FUNCTION__);
1525 return HA_FAIL;
1526 }
1527
1528 if(type >= DIMOF(fieldtypefuncs)){
1529 cl_log(LOG_ERR, "%s:"
1530 "invalid type(%d)",__FUNCTION__, type);
1531 return HA_FAIL;
1532 }
1533
1534 if (index >= msg->nfields){
1535 cl_log(LOG_ERR, "%s: index(%d) out of range(%d)",
1536 __FUNCTION__,index, msg->nfields);
1537 return HA_FAIL;
1538 }
1539
1540 oldtype = msg->types[index];
1541
1542 newv = fieldtypefuncs[type].dup(value,vlen);
1543 if (!newv){
1544 cl_log(LOG_ERR, "%s: duplicating message fields failed"
1545 "value=%p, vlen=%d, msg->names[i]=%s",
1546 __FUNCTION__,value, (int)vlen, msg->names[index]);
1547 return HA_FAIL;
1548 }
1549
1550 fieldtypefuncs[oldtype].memfree(msg->values[index]);
1551
1552 msg->values[index] = newv;
1553 msg->vlens[index] = newlen;
1554 msg->types[index] = type;
1555 PARANOIDAUDITMSG(msg);
1556 return(HA_OK);
1557
1558 }
1559
1560
1561 static int
cl_msg_mod(struct ha_msg * msg,const char * name,const void * value,size_t vlen,int type)1562 cl_msg_mod(struct ha_msg * msg, const char * name,
1563 const void* value, size_t vlen, int type)
1564 {
1565 int j;
1566 int rc;
1567
1568 PARANOIDAUDITMSG(msg);
1569 if (msg == NULL || name == NULL || value == NULL) {
1570 cl_log(LOG_ERR, "cl_msg_mod: NULL input.");
1571 return HA_FAIL;
1572 }
1573
1574 if(type >= DIMOF(fieldtypefuncs)){
1575 cl_log(LOG_ERR, "cl_msg_mod:"
1576 "invalid type(%d)", type);
1577 return HA_FAIL;
1578 }
1579
1580 for (j=0; j < msg->nfields; ++j) {
1581 if (strcmp(name, msg->names[j]) == 0) {
1582
1583 char * newv ;
1584 int newlen = vlen;
1585
1586 if (type != msg->types[j]){
1587 cl_log(LOG_ERR, "%s: type mismatch(%d %d)",
1588 __FUNCTION__, type, msg->types[j]);
1589 return HA_FAIL;
1590 }
1591
1592 newv = fieldtypefuncs[type].dup(value,vlen);
1593 if (!newv){
1594 cl_log(LOG_ERR, "duplicating message fields failed"
1595 "value=%p, vlen=%d, msg->names[j]=%s",
1596 value, (int)vlen, msg->names[j]);
1597 return HA_FAIL;
1598 }
1599
1600 fieldtypefuncs[type].memfree(msg->values[j]);
1601 msg->values[j] = newv;
1602 msg->vlens[j] = newlen;
1603 PARANOIDAUDITMSG(msg);
1604 return(HA_OK);
1605 }
1606 }
1607
1608 rc = ha_msg_nadd_type(msg, name,strlen(name), value, vlen, type);
1609
1610 PARANOIDAUDITMSG(msg);
1611 return rc;
1612 }
1613
1614 int
cl_msg_modstruct(struct ha_msg * msg,const char * name,const struct ha_msg * value)1615 cl_msg_modstruct(struct ha_msg * msg, const char* name,
1616 const struct ha_msg* value)
1617 {
1618 return cl_msg_mod(msg, name, value, 0, FT_STRUCT);
1619 }
1620
1621 int
cl_msg_modbin(struct ha_msg * msg,const char * name,const void * value,size_t vlen)1622 cl_msg_modbin(struct ha_msg * msg, const char* name,
1623 const void* value, size_t vlen)
1624 {
1625 return cl_msg_mod(msg, name, value, vlen, FT_BINARY);
1626
1627 }
1628 int
cl_msg_moduuid(struct ha_msg * msg,const char * name,const cl_uuid_t * uuid)1629 cl_msg_moduuid(struct ha_msg * msg, const char* name,
1630 const cl_uuid_t* uuid)
1631 {
1632 return cl_msg_mod(msg, name, uuid, sizeof(cl_uuid_t), FT_BINARY);
1633 }
1634
1635
1636
1637 /* Modify the value associated with a particular name */
1638 int
cl_msg_modstring(struct ha_msg * msg,const char * name,const char * value)1639 cl_msg_modstring(struct ha_msg * msg, const char * name, const char * value)
1640 {
1641 return cl_msg_mod(msg, name, value, strlen(value), FT_STRING);
1642 }
1643
1644
1645
1646 /* Return the next message found in the stream */
1647 struct ha_msg *
msgfromstream(FILE * f)1648 msgfromstream(FILE * f)
1649 {
1650 char buf[MAXMSGLINE];
1651 char * getsret;
1652 clearerr(f);
1653 /* Skip until we find a MSG_START (hopefully we skip nothing) */
1654 while(1) {
1655 getsret = fgets(buf, sizeof(buf), f);
1656 if (!getsret) {
1657 break;
1658 }
1659 if (strcmp(buf, MSG_START) == 0) {
1660 return msgfromstream_string(f);
1661
1662 }
1663 if (strcmp(buf, MSG_START_NETSTRING) == 0){
1664 return msgfromstream_netstring(f);
1665 }
1666
1667 }
1668
1669 return NULL;
1670 }
1671
1672 /* Return the next message found in the stream with string format */
1673 struct ha_msg *
msgfromstream_string(FILE * f)1674 msgfromstream_string(FILE * f)
1675 {
1676 char buf[MAXMSGLINE];
1677 const char * bufmax = buf + sizeof(buf);
1678 struct ha_msg* ret;
1679 char * getsret;
1680
1681
1682 if ((ret = ha_msg_new(0)) == NULL) {
1683 /* Getting an error with EINTR is pretty normal */
1684 /* (so is EOF) */
1685 if ( (!ferror(f) || (errno != EINTR && errno != EAGAIN))
1686 && !feof(f)) {
1687 cl_log(LOG_ERR, "msgfromstream: cannot get message");
1688 }
1689 return(NULL);
1690 }
1691
1692 /* Add Name=value pairs until we reach MSG_END or EOF */
1693 while(1) {
1694 getsret = fgets(buf, MAXMSGLINE, f);
1695 if (!getsret) {
1696 break;
1697 }
1698
1699 if (strnlen(buf, MAXMSGLINE) > MAXMSGLINE - 2) {
1700 cl_log(LOG_DEBUG
1701 , "msgfromstream: field too long [%s]"
1702 , buf);
1703 }
1704
1705 if (!strcmp(buf, MSG_END)) {
1706 break;
1707 }
1708
1709
1710 /* Add the "name=value" string on this line to the message */
1711 if (ha_msg_add_nv(ret, buf, bufmax) != HA_OK) {
1712 cl_log(LOG_ERR, "NV failure (msgfromsteam): [%s]"
1713 , buf);
1714 ha_msg_del(ret); ret=NULL;
1715 return(NULL);
1716 }
1717 }
1718 return(ret);
1719 }
1720
1721
1722 /* Return the next message found in the stream with netstring format*/
1723
1724 struct ha_msg *
msgfromstream_netstring(FILE * f)1725 msgfromstream_netstring(FILE * f)
1726 {
1727 struct ha_msg * ret;
1728
1729 if ((ret = ha_msg_new(0)) == NULL) {
1730 /* Getting an error with EINTR is pretty normal */
1731 /* (so is EOF) */
1732 if ( (!ferror(f) || (errno != EINTR && errno != EAGAIN))
1733 && !feof(f)) {
1734 cl_log(LOG_ERR
1735 , "msgfromstream_netstring(): cannot get message");
1736 }
1737 return(NULL);
1738 }
1739
1740 while(1) {
1741 char* nvpair;
1742 int nvlen;
1743 int n;
1744
1745 if (fscanf(f, "%d:", &nvlen) <= 0 || nvlen <= 0){
1746 return(ret);
1747 }
1748
1749 nvpair = malloc(nvlen + 2);
1750
1751 if ((n =fread(nvpair, 1, nvlen + 1, f)) != nvlen + 1){
1752 cl_log(LOG_WARNING, "msgfromstream_netstring()"
1753 ": Can't get enough nvpair,"
1754 "expecting %d bytes long, got %d bytes",
1755 nvlen + 1, n);
1756 ha_msg_del(ret);
1757 return(NULL);
1758 }
1759
1760 process_netstring_nvpair(ret, nvpair, nvlen);
1761
1762 }
1763
1764 }
1765
1766 static gboolean ipc_timer_expired = FALSE;
1767
cl_sigalarm_handler(int signum)1768 static void cl_sigalarm_handler(int signum)
1769 {
1770 if (signum == SIGALRM) {
1771 ipc_timer_expired = TRUE;
1772 }
1773 }
1774
1775 int
cl_ipc_wait_timeout(IPC_Channel * chan,int (* waitfun)(IPC_Channel * chan),unsigned int timeout)1776 cl_ipc_wait_timeout(
1777 IPC_Channel *chan, int (*waitfun)(IPC_Channel *chan), unsigned int timeout)
1778 {
1779 int rc = IPC_FAIL;
1780 struct sigaction old_action;
1781
1782 memset(&old_action, 0, sizeof(old_action));
1783 cl_signal_set_simple_handler(SIGALRM, cl_sigalarm_handler, &old_action);
1784
1785 ipc_timer_expired = FALSE;
1786
1787 alarm(timeout);
1788 rc = waitfun(chan);
1789 if (rc == IPC_INTR && ipc_timer_expired) {
1790 rc = IPC_TIMEOUT;
1791 }
1792
1793 alarm(0); /* ensure it expires */
1794 cl_signal_set_simple_handler(SIGALRM, old_action.sa_handler, &old_action);
1795
1796
1797 return rc;
1798 }
1799
1800 /* Return the next message found in the IPC channel */
1801 static struct ha_msg*
msgfromIPC_ll(IPC_Channel * ch,int flag,unsigned int timeout,int * rc_out)1802 msgfromIPC_ll(IPC_Channel * ch, int flag, unsigned int timeout, int *rc_out)
1803 {
1804 int rc;
1805 IPC_Message* ipcmsg;
1806 struct ha_msg* hmsg;
1807 int need_auth = flag & MSG_NEEDAUTH;
1808 int allow_intr = flag & MSG_ALLOWINTR;
1809
1810 startwait:
1811 if(timeout > 0) {
1812 rc = cl_ipc_wait_timeout(ch, ch->ops->waitin, timeout);
1813 } else {
1814 rc = ch->ops->waitin(ch);
1815 }
1816
1817 if(rc_out) {
1818 *rc_out = rc;
1819 }
1820
1821 switch(rc) {
1822 default:
1823 case IPC_FAIL:
1824 cl_perror("msgfromIPC: waitin failure");
1825 return NULL;
1826
1827 case IPC_TIMEOUT:
1828 return NULL;
1829
1830 case IPC_BROKEN:
1831 sleep(1);
1832 return NULL;
1833
1834 case IPC_INTR:
1835 if ( allow_intr){
1836 goto startwait;
1837 }else{
1838 return NULL;
1839 }
1840
1841 case IPC_OK:
1842 break;
1843 }
1844
1845
1846 ipcmsg = NULL;
1847 rc = ch->ops->recv(ch, &ipcmsg);
1848 #if 0
1849 if (DEBUGPKTCONT) {
1850 cl_log(LOG_DEBUG, "msgfromIPC: recv returns %d ipcmsg = 0x%lx"
1851 , rc, (unsigned long)ipcmsg);
1852 }
1853 #endif
1854 if(rc_out) {
1855 *rc_out = rc;
1856 }
1857
1858 if (rc != IPC_OK) {
1859 return NULL;
1860 }
1861
1862 hmsg = wirefmt2msg_ll((char *)ipcmsg->msg_body, ipcmsg->msg_len, need_auth);
1863 if (ipcmsg->msg_done) {
1864 ipcmsg->msg_done(ipcmsg);
1865 }
1866
1867 AUDITMSG(hmsg);
1868 return hmsg;
1869 }
1870
1871 /* Return the next message found in the IPC channel */
1872 struct ha_msg*
msgfromIPC_timeout(IPC_Channel * ch,int flag,unsigned int timeout,int * rc_out)1873 msgfromIPC_timeout(IPC_Channel *ch, int flag, unsigned int timeout, int *rc_out)
1874 {
1875 return msgfromIPC_ll(ch, flag, timeout, rc_out);
1876 }
1877
1878 struct ha_msg*
msgfromIPC(IPC_Channel * ch,int flag)1879 msgfromIPC(IPC_Channel * ch, int flag)
1880 {
1881 return msgfromIPC_ll(ch, flag, 0, NULL);
1882 }
1883
1884
1885 struct ha_msg*
msgfromIPC_noauth(IPC_Channel * ch)1886 msgfromIPC_noauth(IPC_Channel * ch)
1887 {
1888 int flag = 0;
1889
1890 flag |= MSG_ALLOWINTR;
1891 return msgfromIPC_ll(ch, flag, 0, NULL);
1892 }
1893
1894 /* Return the next message found in the IPC channel */
1895 IPC_Message *
ipcmsgfromIPC(IPC_Channel * ch)1896 ipcmsgfromIPC(IPC_Channel * ch)
1897 {
1898 int rc;
1899 IPC_Message* ipcmsg;
1900
1901 rc = ch->ops->waitin(ch);
1902
1903 switch(rc) {
1904 default:
1905 case IPC_FAIL:
1906 cl_perror("msgfromIPC: waitin failure");
1907 return NULL;
1908
1909 case IPC_BROKEN:
1910 sleep(1);
1911 return NULL;
1912
1913 case IPC_INTR:
1914 return NULL;
1915
1916 case IPC_OK:
1917 break;
1918 }
1919
1920
1921 ipcmsg = NULL;
1922 rc = ch->ops->recv(ch, &ipcmsg);
1923 #if 0
1924 if (DEBUGPKTCONT) {
1925 cl_log(LOG_DEBUG, "msgfromIPC: recv returns %d ipcmsg = 0x%lx"
1926 , rc, (unsigned long)ipcmsg);
1927 }
1928 #endif
1929 if (rc != IPC_OK) {
1930 return NULL;
1931 }
1932
1933
1934 return(ipcmsg);
1935 }
1936
1937
1938 /* Writes a message into a stream - used for serial lines */
1939 int
msg2stream(struct ha_msg * m,FILE * f)1940 msg2stream(struct ha_msg* m, FILE * f)
1941 {
1942 size_t len;
1943 char * s = msg2wirefmt(m, &len);
1944
1945 if (s != NULL) {
1946 int rc = HA_OK;
1947 if (fputs(s, f) == EOF) {
1948 rc = HA_FAIL;
1949 cl_perror("msg2stream: fputs failure");
1950 }
1951 if (fflush(f) == EOF) {
1952 cl_perror("msg2stream: fflush failure");
1953 rc = HA_FAIL;
1954 }
1955 free(s);
1956 return(rc);
1957 }else{
1958 return(HA_FAIL);
1959 }
1960 }
1961 static void ipcmsg_done(IPC_Message* m);
1962
1963 static int clmsg_ipcmsg_allocated = 0;
1964 static int clmsg_ipcmsg_freed = 0;
1965
1966 void dump_clmsg_ipcmsg_stats(void);
1967 void
dump_clmsg_ipcmsg_stats(void)1968 dump_clmsg_ipcmsg_stats(void)
1969 {
1970 cl_log(LOG_INFO, "clmsg ipcmsg allocated=%d, freed=%d, diff=%d",
1971 clmsg_ipcmsg_allocated,
1972 clmsg_ipcmsg_freed,
1973 clmsg_ipcmsg_allocated - clmsg_ipcmsg_freed);
1974
1975 return;
1976 }
1977
1978 static void
ipcmsg_done(IPC_Message * m)1979 ipcmsg_done(IPC_Message* m)
1980 {
1981 if (!m) {
1982 return;
1983 }
1984 if (m->msg_buf) {
1985 free(m->msg_buf);
1986 }
1987 free(m);
1988 m = NULL;
1989 clmsg_ipcmsg_freed ++;
1990 }
1991
1992
1993
1994 /*
1995 * create an ipcmsg and copy the data
1996 */
1997
1998 IPC_Message*
wirefmt2ipcmsg(void * p,size_t len,IPC_Channel * ch)1999 wirefmt2ipcmsg(void* p, size_t len, IPC_Channel* ch)
2000 {
2001 IPC_Message* ret = NULL;
2002
2003 if (p == NULL){
2004 return(NULL);
2005 }
2006
2007 ret = MALLOCT(IPC_Message);
2008 if (!ret) {
2009 return(NULL);
2010 }
2011
2012 memset(ret, 0, sizeof(IPC_Message));
2013
2014 if (NULL == (ret->msg_buf = malloc(len + ch->msgpad))) {
2015 free(ret);
2016 return NULL;
2017 }
2018 ret->msg_body = (char*)ret->msg_buf + ch->msgpad;
2019 memcpy(ret->msg_body, p, len);
2020
2021 ret->msg_done = ipcmsg_done;
2022 ret->msg_private = NULL;
2023 ret->msg_ch = ch;
2024 ret->msg_len = len;
2025
2026 clmsg_ipcmsg_allocated ++;
2027
2028 return ret;
2029
2030 }
2031
2032 IPC_Message*
hamsg2ipcmsg(struct ha_msg * m,IPC_Channel * ch)2033 hamsg2ipcmsg(struct ha_msg* m, IPC_Channel* ch)
2034 {
2035 size_t len;
2036 char * s = msg2wirefmt_ll(m, &len, MSG_NEEDCOMPRESS);
2037 IPC_Message* ret = NULL;
2038
2039 if (s == NULL) {
2040 return ret;
2041 }
2042 ret = MALLOCT(IPC_Message);
2043 if (!ret) {
2044 free(s);
2045 return ret;
2046 }
2047
2048 memset(ret, 0, sizeof(IPC_Message));
2049
2050 if (NULL == (ret->msg_buf = malloc(len + ch->msgpad))) {
2051 free(s);
2052 free(ret);
2053 return NULL;
2054 }
2055 ret->msg_body = (char*)ret->msg_buf + ch->msgpad;
2056 memcpy(ret->msg_body, s, len);
2057 free(s);
2058
2059 ret->msg_done = ipcmsg_done;
2060 ret->msg_private = NULL;
2061 ret->msg_ch = ch;
2062 ret->msg_len = len;
2063
2064 clmsg_ipcmsg_allocated ++;
2065
2066 return ret;
2067 }
2068
2069 struct ha_msg*
ipcmsg2hamsg(IPC_Message * m)2070 ipcmsg2hamsg(IPC_Message*m)
2071 {
2072 struct ha_msg* ret = NULL;
2073
2074
2075 ret = wirefmt2msg(m->msg_body, m->msg_len,MSG_NEEDAUTH);
2076 return ret;
2077 }
2078
2079 int
msg2ipcchan(struct ha_msg * m,IPC_Channel * ch)2080 msg2ipcchan(struct ha_msg*m, IPC_Channel*ch)
2081 {
2082 IPC_Message* imsg;
2083
2084 if (m == NULL || ch == NULL) {
2085 cl_log(LOG_ERR, "Invalid msg2ipcchan argument");
2086 errno = EINVAL;
2087 return HA_FAIL;
2088 }
2089
2090 if ((imsg = hamsg2ipcmsg(m, ch)) == NULL) {
2091 cl_log(LOG_ERR, "hamsg2ipcmsg() failure");
2092 return HA_FAIL;
2093 }
2094
2095 if (ch->ops->send(ch, imsg) != IPC_OK) {
2096 if (ch->ch_status == IPC_CONNECT) {
2097 snprintf(ch->failreason,MAXFAILREASON,
2098 "send failed,farside_pid=%d, sendq length=%ld(max is %ld)",
2099 ch->farside_pid, (long)ch->send_queue->current_qlen,
2100 (long)ch->send_queue->max_qlen);
2101 }
2102 imsg->msg_done(imsg);
2103 return HA_FAIL;
2104 }
2105 return HA_OK;
2106 }
2107
2108 static gboolean (*msg_authentication_method)(const struct ha_msg* ret) = NULL;
2109
2110
2111 void
cl_set_oldmsgauthfunc(gboolean (* authfunc)(const struct ha_msg *))2112 cl_set_oldmsgauthfunc(gboolean (*authfunc)(const struct ha_msg*))
2113 {
2114 msg_authentication_method = authfunc;
2115 }
2116
2117
2118
2119 /* Converts a string (perhaps received via UDP) into a message */
2120 struct ha_msg *
string2msg_ll(const char * s,size_t length,int depth,int need_auth)2121 string2msg_ll(const char * s, size_t length, int depth, int need_auth)
2122 {
2123 struct ha_msg* ret;
2124 int startlen;
2125 int endlen;
2126 const char * sp = s;
2127 const char * smax = s + length;
2128
2129
2130 if ((ret = ha_msg_new(0)) == NULL) {
2131 cl_log(LOG_ERR, "%s: creating new msg failed", __FUNCTION__);
2132 return(NULL);
2133 }
2134
2135 startlen = sizeof(MSG_START)-1;
2136 if (strncmp(sp, MSG_START, startlen) != 0) {
2137 /* This can happen if the sender gets killed */
2138 /* at just the wrong time... */
2139 if (!cl_msg_quiet_fmterr) {
2140 cl_log(LOG_WARNING, "string2msg_ll: no MSG_START");
2141 cl_log(LOG_WARNING, "%s: s=%s", __FUNCTION__, s);
2142 cl_log(LOG_WARNING, "depth=%d", depth);
2143 }
2144 ha_msg_del(ret);
2145 return(NULL);
2146 }else{
2147 sp += startlen;
2148 }
2149
2150 endlen = sizeof(MSG_END)-1;
2151
2152 /* Add Name=value pairs until we reach MSG_END or end of string */
2153
2154 while (*sp != EOS && strncmp(sp, MSG_END, endlen) != 0) {
2155
2156 if (sp >= smax) {
2157 cl_log(LOG_ERR, "%s: buffer overflow(sp=%p, smax=%p)",
2158 __FUNCTION__, sp, smax);
2159 return(NULL);
2160 }
2161 /* Skip over initial CR/NL things */
2162 sp += strspn(sp, NEWLINE);
2163 if (sp >= smax) {
2164 cl_log(LOG_ERR, "%s: buffer overflow after NEWLINE(sp=%p, smax=%p)",
2165 __FUNCTION__, sp, smax);
2166 return(NULL);
2167 }
2168 /* End of message marker? */
2169 if (strncmp(sp, MSG_END, endlen) == 0) {
2170 break;
2171 }
2172 /* Add the "name=value" string on this line to the message */
2173 if (ha_msg_add_nv_depth(ret, sp, smax, depth) != HA_OK) {
2174 if (!cl_msg_quiet_fmterr) {
2175 cl_log(LOG_ERR, "NV failure (string2msg_ll):");
2176 cl_log(LOG_ERR, "Input string: [%s]", s);
2177 cl_log(LOG_ERR, "sp=%s", sp);
2178 cl_log(LOG_ERR, "depth=%d", depth);
2179 cl_log_message(LOG_ERR,ret);
2180 }
2181 ha_msg_del(ret);
2182 return(NULL);
2183 }
2184 if (sp >= smax) {
2185 cl_log(LOG_ERR, "%s: buffer overflow after adding field(sp=%p, smax=%p)",
2186 __FUNCTION__, sp, smax);
2187 return(NULL);
2188 }
2189 sp += strcspn(sp, NEWLINE);
2190 }
2191
2192 if (need_auth && msg_authentication_method
2193 && !msg_authentication_method(ret)) {
2194 const char* from = ha_msg_value(ret, F_ORIG);
2195 if (!cl_msg_quiet_fmterr) {
2196 cl_log(LOG_WARNING,
2197 "string2msg_ll: node [%s]"
2198 " failed authentication", from ? from : "?");
2199 }
2200 ha_msg_del(ret);
2201 ret = NULL;
2202 }
2203 return(ret);
2204 }
2205
2206
2207
2208 struct ha_msg *
string2msg(const char * s,size_t length)2209 string2msg(const char * s, size_t length)
2210 {
2211 return(string2msg_ll(s, length, 0, MSG_NEEDAUTH));
2212 }
2213
2214
2215
2216
2217
2218
2219 /* Converts a message into a string (for sending out UDP interface)
2220
2221 used in two places:
2222
2223 1.called by msg2string as a implementation for computing string for a
2224 message provided the buffer
2225
2226 2.called by is_authentic. In this case, there are no start/end string
2227 and the "auth" field is not included in the string
2228
2229 */
2230
2231 #define NOROOM { \
2232 cl_log(LOG_ERR, "%s:%d: out of memory bound" \
2233 ", bp=%p, buf + len=%p, len=%ld" \
2234 , __FUNCTION__, __LINE__ \
2235 , bp, buf + len, (long)len); \
2236 cl_log_message(LOG_ERR, m); \
2237 return(HA_FAIL); \
2238 }
2239
2240 #define CHECKROOM_CONST(c) CHECKROOM_INT(STRLEN_CONST(c))
2241 #define CHECKROOM_STRING(s) CHECKROOM_INT(strnlen(s, len))
2242 #define CHECKROOM_STRING_INT(s,i) CHECKROOM_INT(strnlen(s, len)+(i))
2243 #define CHECKROOM_INT(i) { \
2244 if ((bp + (i)) > maxp) { \
2245 NOROOM; \
2246 } \
2247 }
2248
2249
2250 int
msg2string_buf(const struct ha_msg * m,char * buf,size_t len,int depth,int needhead)2251 msg2string_buf(const struct ha_msg *m, char* buf, size_t len
2252 , int depth,int needhead)
2253 {
2254
2255 char * bp = NULL;
2256 int j;
2257 char* maxp = buf + len;
2258
2259 buf[0]=0;
2260 bp = buf;
2261
2262 if (needhead){
2263 CHECKROOM_CONST(MSG_START);
2264 strcpy(bp, MSG_START);
2265 bp += STRLEN_CONST(MSG_START);
2266 }
2267
2268 for (j=0; j < m->nfields; ++j) {
2269
2270 int truelen;
2271 int (*tostring)(char*, char*, void*, size_t, int);
2272
2273 if (needhead == NOHEAD && strcmp(m->names[j], F_AUTH) == 0) {
2274 continue;
2275 }
2276
2277 if (m->types[j] != FT_STRING){
2278 CHECKROOM_STRING_INT(FT_strings[m->types[j]],2);
2279 strcat(bp, "(");
2280 bp++;
2281 strcat(bp, FT_strings[m->types[j]]);
2282 bp++;
2283 strcat(bp,")");
2284 bp++;
2285 }
2286
2287 CHECKROOM_STRING_INT(m->names[j],1);
2288 strcat(bp, m->names[j]);
2289 bp += m->nlens[j];
2290 strcat(bp, "=");
2291 bp++;
2292
2293 if(m->types[j] < DIMOF(fieldtypefuncs)){
2294 tostring = fieldtypefuncs[m->types[j]].tostring;
2295 } else {
2296 cl_log(LOG_ERR, "type(%d) unrecognized", m->types[j]);
2297 return HA_FAIL;
2298 }
2299 if (!tostring ||
2300 (truelen = tostring(bp, maxp, m->values[j], m->vlens[j], depth))
2301 < 0){
2302 cl_log(LOG_ERR, "tostring failed for field %d", j);
2303 return HA_FAIL;
2304 }
2305
2306 CHECKROOM_INT(truelen+1);
2307 bp +=truelen;
2308
2309 strcat(bp,"\n");
2310 bp++;
2311 }
2312 if (needhead){
2313 CHECKROOM_CONST(MSG_END);
2314 strcat(bp, MSG_END);
2315 bp += strlen(MSG_END);
2316 }
2317
2318 CHECKROOM_INT(1);
2319 bp[0] = EOS;
2320
2321 return(HA_OK);
2322 }
2323
2324
2325 char *
msg2string(const struct ha_msg * m)2326 msg2string(const struct ha_msg *m)
2327 {
2328 void *buf;
2329 int len;
2330
2331 AUDITMSG(m);
2332 if (m->nfields <= 0) {
2333 cl_log(LOG_ERR, "msg2string: Message with zero fields");
2334 return(NULL);
2335 }
2336
2337 len = get_stringlen(m);
2338
2339 buf = malloc(len);
2340
2341 if (buf == NULL) {
2342 cl_log(LOG_ERR, "msg2string: no memory for string");
2343 return(NULL);
2344 }
2345
2346 if (msg2string_buf(m, buf, len ,0, NEEDHEAD) != HA_OK){
2347 cl_log(LOG_ERR, "msg2string: msg2string_buf failed");
2348 free(buf);
2349 return(NULL);
2350 }
2351
2352 return(buf);
2353 }
2354
2355 gboolean
must_use_netstring(const struct ha_msg * msg)2356 must_use_netstring(const struct ha_msg* msg)
2357 {
2358 int i;
2359
2360 for ( i = 0; i < msg->nfields; i++){
2361 if (msg->types[i] == FT_COMPRESS
2362 || msg->types[i] == FT_UNCOMPRESS
2363 || msg->types[i] == FT_STRUCT){
2364 return TRUE;
2365 }
2366 }
2367
2368 return FALSE;
2369
2370 }
2371
2372 #define use_netstring(m) (msgfmt == MSGFMT_NETSTRING || must_use_netstring(m))
2373
2374 static char*
msg2wirefmt_ll(struct ha_msg * m,size_t * len,int flag)2375 msg2wirefmt_ll(struct ha_msg*m, size_t* len, int flag)
2376 {
2377
2378 int wirefmtlen;
2379 int i;
2380 int netstg = use_netstring(m);
2381
2382 wirefmtlen = netstg ? get_netstringlen(m) : get_stringlen(m);
2383 if (use_traditional_compression
2384 &&(flag & MSG_NEEDCOMPRESS)
2385 && (wirefmtlen> compression_threshold)
2386 && cl_get_compress_fns() != NULL){
2387 return cl_compressmsg(m, len);
2388 }
2389
2390 if (flag & MSG_NEEDCOMPRESS){
2391 for (i=0 ;i < m->nfields; i++){
2392 int type = m->types[i];
2393 if (fieldtypefuncs[type].prepackaction){
2394 fieldtypefuncs[type].prepackaction(m,i);
2395 }
2396 }
2397 }
2398
2399 wirefmtlen = netstg ? get_netstringlen(m) : get_stringlen(m);
2400 if (wirefmtlen >= MAXMSG){
2401 if (flag&MSG_NEEDCOMPRESS) {
2402 if (cl_get_compress_fns() != NULL)
2403 return cl_compressmsg(m, len);
2404 }
2405 cl_log(LOG_ERR, "%s: msg too big(%d)",
2406 __FUNCTION__, wirefmtlen);
2407 return NULL;
2408 }
2409 if (flag & MSG_NEEDAUTH) {
2410 return msg2netstring(m, len);
2411 }
2412 return msg2wirefmt_noac(m, len);
2413 }
2414
2415 char*
msg2wirefmt(struct ha_msg * m,size_t * len)2416 msg2wirefmt(struct ha_msg*m, size_t* len){
2417 return msg2wirefmt_ll(m, len, MSG_NEEDAUTH|MSG_NEEDCOMPRESS);
2418 }
2419
2420 char*
msg2wirefmt_noac(struct ha_msg * m,size_t * len)2421 msg2wirefmt_noac(struct ha_msg*m, size_t* len)
2422 {
2423 if (use_netstring(m)) {
2424 return msg2netstring_noauth(m, len);
2425 } else {
2426 char *tmp;
2427
2428 tmp = msg2string(m);
2429 if(tmp == NULL){
2430 *len = 0;
2431 return NULL;
2432 }
2433 *len = strlen(tmp) + 1;
2434 return tmp;
2435 }
2436 }
2437
2438 static struct ha_msg*
wirefmt2msg_ll(const char * s,size_t length,int need_auth)2439 wirefmt2msg_ll(const char* s, size_t length, int need_auth)
2440 {
2441
2442 size_t startlen;
2443 struct ha_msg* msg = NULL;
2444
2445
2446 startlen = sizeof(MSG_START)-1;
2447
2448 if (startlen > length){
2449 return NULL;
2450 }
2451
2452 if (strncmp( s, MSG_START, startlen) == 0) {
2453 msg = string2msg_ll(s, length, 0, need_auth);
2454 goto out;
2455 }
2456
2457 startlen = sizeof(MSG_START_NETSTRING) - 1;
2458
2459 if (startlen > length){
2460 return NULL;
2461 }
2462
2463 if (strncmp(s, MSG_START_NETSTRING, startlen) == 0) {
2464 msg = netstring2msg(s, length, need_auth);
2465 goto out;
2466 }
2467
2468 out:
2469 if (msg && is_compressed_msg(msg)){
2470 struct ha_msg* ret;
2471 if ((ret = cl_decompressmsg(msg))==NULL){
2472 cl_log(LOG_ERR, "decompress msg failed");
2473 ha_msg_del(msg);
2474 return NULL;
2475 }
2476 ha_msg_del(msg);
2477 return ret;
2478 }
2479 return msg;
2480
2481 }
2482
2483
2484
2485
2486 struct ha_msg*
wirefmt2msg(const char * s,size_t length,int flag)2487 wirefmt2msg(const char* s, size_t length, int flag)
2488 {
2489 return wirefmt2msg_ll(s, length, flag& MSG_NEEDAUTH);
2490
2491 }
2492
2493
2494 void
cl_log_message(int log_level,const struct ha_msg * m)2495 cl_log_message (int log_level, const struct ha_msg *m)
2496 {
2497 int j;
2498
2499 if(m == NULL) {
2500 cl_log(log_level, "MSG: No message to dump");
2501 return;
2502 }
2503
2504 cl_log(log_level, "MSG: Dumping message with %d fields", m->nfields);
2505
2506 for (j=0; j < m->nfields; ++j) {
2507
2508 if(m->types[j] < DIMOF(fieldtypefuncs)){
2509 fieldtypefuncs[m->types[j]].display(log_level, j,
2510 m->names[j],
2511 m->values[j],
2512 m->vlens[j]);
2513 }
2514 }
2515 }
2516
2517
2518 #ifdef TESTMAIN_MSGS
2519 int
main(int argc,char ** argv)2520 main(int argc, char ** argv)
2521 {
2522 struct ha_msg* m;
2523 while (!feof(stdin)) {
2524 if ((m=controlfifo2msg(stdin)) != NULL) {
2525 fprintf(stderr, "Got message!\n");
2526 if (msg2stream(m, stdout) == HA_OK) {
2527 fprintf(stderr, "Message output OK!\n");
2528 }else{
2529 fprintf(stderr, "Could not output Message!\n");
2530 }
2531 }else{
2532 fprintf(stderr, "Could not get message!\n");
2533 }
2534 }
2535 return(0);
2536 }
2537 #endif
2538