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