Browse code

ctl: internal mode to allow non-strict reading binrpc packets

- allow handling structs with simple values inside, some rpc responses
are not strictly build as per xmlrpc/jsonrpc specs

Daniel-Constantin Mierla authored on 26/08/2015 17:03:55
Showing 2 changed files
... ...
@@ -614,12 +614,15 @@ inline static int binrpc_bytes_needed(struct binrpc_parse_ctx *ctx)
614 614
 /* prefill v with the requested type, if type==BINRPC_T_ALL it 
615 615
  * will be replaced by the actual record type 
616 616
  * known problems: no support for arrays inside STRUCT
617
+ * param smode: allow simple vals inside struct (needed for 
618
+ * not-strict-formatted rpc responses)
617 619
  * returns position after the record and *err==0 if succesfull
618 620
  *         original position and *err<0 if not */
619 621
 inline static unsigned char* binrpc_read_record(struct binrpc_parse_ctx* ctx,
620 622
 												unsigned char* buf,
621 623
 												unsigned char* end,
622 624
 												struct binrpc_val* v,
625
+												int smode,
623 626
 												int* err
624 627
 												)
625 628
 {
... ...
@@ -664,18 +667,30 @@ inline static unsigned char* binrpc_read_record(struct binrpc_parse_ctx* ctx,
664 667
 		goto error_type;
665 668
 	}
666 669
 	v->type=type;
667
-	if (ctx->in_struct){
668
-		switch(type){
669
-			case BINRPC_T_STRUCT:
670
+	switch(type){
671
+		case BINRPC_T_STRUCT:
672
+			if (ctx->in_struct){
670 673
 				if (end_tag){
671 674
 					ctx->in_struct--;
672 675
 					v->u.end=1;
673 676
 				}else{
674
-					goto error_record;
677
+					if(smode==0) {
678
+						goto error_record;
679
+					} else {
680
+						v->u.end=0;
681
+						ctx->in_struct++;
682
+					}
675 683
 				}
676
-				break;
677
-			case BINRPC_T_AVP:
678
-				/* name | value */
684
+			} else {
685
+				if (end_tag)
686
+					goto error_record;
687
+				v->u.end=0;
688
+				ctx->in_struct++;
689
+			}
690
+			break;
691
+		case BINRPC_T_AVP:
692
+			/* name | value */
693
+			if (ctx->in_struct){
679 694
 				v->name.s=(char*)p;
680 695
 				v->name.len=(len-1); /* don't include 0 term */
681 696
 				p+=len;
... ...
@@ -689,7 +704,7 @@ inline static unsigned char* binrpc_read_record(struct binrpc_parse_ctx* ctx,
689 704
 					tmp=ctx->in_struct;
690 705
 					ctx->in_struct=0; /* hack to parse a normal record */
691 706
 					v->type=type; /* hack */
692
-					p=binrpc_read_record(ctx, p, end, v, err);
707
+					p=binrpc_read_record(ctx, p, end, v, smode, err);
693 708
 					if (err<0){
694 709
 						ctx->in_struct=tmp;
695 710
 						goto error;
... ...
@@ -701,50 +716,51 @@ inline static unsigned char* binrpc_read_record(struct binrpc_parse_ctx* ctx,
701 716
 				}else{
702 717
 					goto  error_record;
703 718
 				}
704
-				break;
705
-			default:
706
-				goto error_record;
707
-		}
708
-	}else{
709
-		switch(type){
710
-			case BINRPC_T_INT:
711
-				p=binrpc_read_int(&v->u.intval, len, p, end, err);
712
-				break;
713
-			case BINRPC_T_STR:
714
-				v->u.strval.s=(char*)p;
715
-				v->u.strval.len=(len-1); /* don't include terminating 0 */
716
-				p+=len;
717
-				break;
718
-			case BINRPC_T_BYTES:
719
-				v->u.strval.s=(char*)p;
720
-				v->u.strval.len=len;
721
-				p+=len;
722
-			case BINRPC_T_STRUCT:
723
-				if (end_tag)
724
-					goto error_record;
725
-				v->u.end=0;
726
-				ctx->in_struct++;
727
-				break;
728
-			case BINRPC_T_ARRAY:
729
-				if (end_tag){
730
-					if (ctx->in_array>0){
731
-						ctx->in_array--;
732
-						v->u.end=1;
733
-					}else
734
-						goto error_record;
719
+			} else {
720
+				goto error_type;
721
+			}
722
+			break;
723
+		case BINRPC_T_INT:
724
+			if (ctx->in_struct && smode==0) goto error_record;
725
+			p=binrpc_read_int(&v->u.intval, len, p, end, err);
726
+			break;
727
+		case BINRPC_T_STR:
728
+			if (ctx->in_struct && smode==0) goto error_record;
729
+			v->u.strval.s=(char*)p;
730
+			v->u.strval.len=(len-1); /* don't include terminating 0 */
731
+			p+=len;
732
+			break;
733
+		case BINRPC_T_BYTES:
734
+			if (ctx->in_struct && smode==0) goto error_record;
735
+			v->u.strval.s=(char*)p;
736
+			v->u.strval.len=len;
737
+			p+=len;
738
+		case BINRPC_T_ARRAY:
739
+			if (ctx->in_struct && smode==0) goto error_record;
740
+			if (end_tag){
741
+				if (ctx->in_array>0){
742
+					ctx->in_array--;
743
+					v->u.end=1;
735 744
 				}else{
736
-					ctx->in_array++;
737
-					v->u.end=0;
745
+					goto error_record;
738 746
 				}
739
-				break;
740
-			case BINRPC_T_DOUBLE: /* FIXME: hack: represented as fixed point
741
-			                                      inside an int */
742
-				p=binrpc_read_int(&i, len, p, end, err);
743
-				v->u.fval=((double)i)/1000;
744
-				break;
745
-			default:
747
+			}else{
748
+				ctx->in_array++;
749
+				v->u.end=0;
750
+			}
751
+			break;
752
+		case BINRPC_T_DOUBLE: /* FIXME: hack: represented as fixed point
753
+		                                      inside an int */
754
+			if (ctx->in_struct && smode==0) goto error_record;
755
+			p=binrpc_read_int(&i, len, p, end, err);
756
+			v->u.fval=((double)i)/1000;
757
+			break;
758
+		default:
759
+			if (ctx->in_struct){
760
+				goto error_record;
761
+			} else {
746 762
 				goto error_type;
747
-		}
763
+			}
748 764
 	}
749 765
 	ctx->offset+=(int)(p-buf);
750 766
 no_offs_update:
... ...
@@ -655,7 +655,7 @@ int process_rpc_req(unsigned char* buf, int size, int* bytes_needed,
655 655
 	
656 656
 	/* get rpc method */
657 657
 	val.type=BINRPC_T_STR;
658
-	f_ctx.in.s=binrpc_read_record(ctx, f_ctx.in.s, f_ctx.in.end, &val, &err);
658
+	f_ctx.in.s=binrpc_read_record(ctx, f_ctx.in.s, f_ctx.in.end, &val, 0, &err);
659 659
 	if (err<0){
660 660
 		LOG(L_CRIT, "ERROR: bad rpc request method, binrpc error: %s (%d)\n",
661 661
 				binrpc_error(err), err);
... ...
@@ -857,7 +857,7 @@ static int rpc_scan(struct binrpc_ctx* ctx, char* fmt, ...)
857 857
 			case 'd': /* int */
858 858
 				v.type=autoconv?BINRPC_T_ALL:BINRPC_T_INT;
859 859
 				ctx->in.s=binrpc_read_record(&ctx->in.ctx, ctx->in.s,
860
-												ctx->in.end, &v, &err);
860
+												ctx->in.end, &v, 0, &err);
861 861
 				if (err<0 || ((i=binrpc_val_conv_int(&v, &err))==0 && err<0))
862 862
 						goto error_read;
863 863
 				*(va_arg(ap, int*))=i;
... ...
@@ -865,7 +865,7 @@ static int rpc_scan(struct binrpc_ctx* ctx, char* fmt, ...)
865 865
 			case 'f':
866 866
 				v.type=autoconv?BINRPC_T_ALL:BINRPC_T_DOUBLE;
867 867
 				ctx->in.s=binrpc_read_record(&ctx->in.ctx, ctx->in.s,
868
-												ctx->in.end, &v, &err);
868
+												ctx->in.end, &v, 0, &err);
869 869
 				if (err<0 || ((d=binrpc_val_conv_double(&v, &err))==0 &&
870 870
 						err<0))
871 871
 					goto error_read;
... ...
@@ -875,7 +875,7 @@ static int rpc_scan(struct binrpc_ctx* ctx, char* fmt, ...)
875 875
 			case 'S': /* str */
876 876
 				v.type=autoconv?BINRPC_T_ALL:BINRPC_T_STR;
877 877
 				ctx->in.s=binrpc_read_record(&ctx->in.ctx, ctx->in.s, 
878
-												ctx->in.end, &v,&err);
878
+												ctx->in.end, &v, 0, &err);
879 879
 				if (err<0 || ((s=binrpc_val_conv_str(ctx, &v, &err))==0 &&
880 880
 							err<0)){
881 881
 					v.u.strval.s="if you get this string, you don't"
... ...
@@ -895,7 +895,7 @@ static int rpc_scan(struct binrpc_ctx* ctx, char* fmt, ...)
895 895
 				/* FIXME: structure reading doesn't work for now */
896 896
 #if 0
897 897
 				ctx->in.s=binrpc_read_record(&ctx->in.ctx, ctx->in.s, 
898
-												ctx->in.end, &v, &err);
898
+												ctx->in.end, &v, 0, &err);
899 899
 				if (err<0) goto error_read;
900 900
 				ctx->in.in_struct++;
901 901
 				*(va_arg(ap, void**))=ctx; /* use the same context */