Skip to content

Commit

Permalink
ctl: internal mode to allow non-strict reading binrpc packets
Browse files Browse the repository at this point in the history
- allow handling structs with simple values inside, some rpc responses
  are not strictly build as per xmlrpc/jsonrpc specs
  • Loading branch information
miconda committed Aug 26, 2015
1 parent 3f4c638 commit 39ab16e
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 54 deletions.
114 changes: 65 additions & 49 deletions modules/ctl/binrpc.h
Expand Up @@ -614,12 +614,15 @@ inline static int binrpc_bytes_needed(struct binrpc_parse_ctx *ctx)
/* prefill v with the requested type, if type==BINRPC_T_ALL it
* will be replaced by the actual record type
* known problems: no support for arrays inside STRUCT
* param smode: allow simple vals inside struct (needed for
* not-strict-formatted rpc responses)
* returns position after the record and *err==0 if succesfull
* original position and *err<0 if not */
inline static unsigned char* binrpc_read_record(struct binrpc_parse_ctx* ctx,
unsigned char* buf,
unsigned char* end,
struct binrpc_val* v,
int smode,
int* err
)
{
Expand Down Expand Up @@ -664,18 +667,30 @@ inline static unsigned char* binrpc_read_record(struct binrpc_parse_ctx* ctx,
goto error_type;
}
v->type=type;
if (ctx->in_struct){
switch(type){
case BINRPC_T_STRUCT:
switch(type){
case BINRPC_T_STRUCT:
if (ctx->in_struct){
if (end_tag){
ctx->in_struct--;
v->u.end=1;
}else{
goto error_record;
if(smode==0) {
goto error_record;
} else {
v->u.end=0;
ctx->in_struct++;
}
}
break;
case BINRPC_T_AVP:
/* name | value */
} else {
if (end_tag)
goto error_record;
v->u.end=0;
ctx->in_struct++;
}
break;
case BINRPC_T_AVP:
/* name | value */
if (ctx->in_struct){
v->name.s=(char*)p;
v->name.len=(len-1); /* don't include 0 term */
p+=len;
Expand All @@ -689,7 +704,7 @@ inline static unsigned char* binrpc_read_record(struct binrpc_parse_ctx* ctx,
tmp=ctx->in_struct;
ctx->in_struct=0; /* hack to parse a normal record */
v->type=type; /* hack */
p=binrpc_read_record(ctx, p, end, v, err);
p=binrpc_read_record(ctx, p, end, v, smode, err);
if (err<0){
ctx->in_struct=tmp;
goto error;
Expand All @@ -701,50 +716,51 @@ inline static unsigned char* binrpc_read_record(struct binrpc_parse_ctx* ctx,
}else{
goto error_record;
}
break;
default:
goto error_record;
}
}else{
switch(type){
case BINRPC_T_INT:
p=binrpc_read_int(&v->u.intval, len, p, end, err);
break;
case BINRPC_T_STR:
v->u.strval.s=(char*)p;
v->u.strval.len=(len-1); /* don't include terminating 0 */
p+=len;
break;
case BINRPC_T_BYTES:
v->u.strval.s=(char*)p;
v->u.strval.len=len;
p+=len;
case BINRPC_T_STRUCT:
if (end_tag)
goto error_record;
v->u.end=0;
ctx->in_struct++;
break;
case BINRPC_T_ARRAY:
if (end_tag){
if (ctx->in_array>0){
ctx->in_array--;
v->u.end=1;
}else
goto error_record;
} else {
goto error_type;
}
break;
case BINRPC_T_INT:
if (ctx->in_struct && smode==0) goto error_record;
p=binrpc_read_int(&v->u.intval, len, p, end, err);
break;
case BINRPC_T_STR:
if (ctx->in_struct && smode==0) goto error_record;
v->u.strval.s=(char*)p;
v->u.strval.len=(len-1); /* don't include terminating 0 */
p+=len;
break;
case BINRPC_T_BYTES:
if (ctx->in_struct && smode==0) goto error_record;
v->u.strval.s=(char*)p;
v->u.strval.len=len;
p+=len;
case BINRPC_T_ARRAY:
if (ctx->in_struct && smode==0) goto error_record;
if (end_tag){
if (ctx->in_array>0){
ctx->in_array--;
v->u.end=1;
}else{
ctx->in_array++;
v->u.end=0;
goto error_record;
}
break;
case BINRPC_T_DOUBLE: /* FIXME: hack: represented as fixed point
inside an int */
p=binrpc_read_int(&i, len, p, end, err);
v->u.fval=((double)i)/1000;
break;
default:
}else{
ctx->in_array++;
v->u.end=0;
}
break;
case BINRPC_T_DOUBLE: /* FIXME: hack: represented as fixed point
inside an int */
if (ctx->in_struct && smode==0) goto error_record;
p=binrpc_read_int(&i, len, p, end, err);
v->u.fval=((double)i)/1000;
break;
default:
if (ctx->in_struct){
goto error_record;
} else {
goto error_type;
}
}
}
ctx->offset+=(int)(p-buf);
no_offs_update:
Expand Down
10 changes: 5 additions & 5 deletions modules/ctl/binrpc_run.c
Expand Up @@ -655,7 +655,7 @@ int process_rpc_req(unsigned char* buf, int size, int* bytes_needed,

/* get rpc method */
val.type=BINRPC_T_STR;
f_ctx.in.s=binrpc_read_record(ctx, f_ctx.in.s, f_ctx.in.end, &val, &err);
f_ctx.in.s=binrpc_read_record(ctx, f_ctx.in.s, f_ctx.in.end, &val, 0, &err);
if (err<0){
LOG(L_CRIT, "ERROR: bad rpc request method, binrpc error: %s (%d)\n",
binrpc_error(err), err);
Expand Down Expand Up @@ -857,15 +857,15 @@ static int rpc_scan(struct binrpc_ctx* ctx, char* fmt, ...)
case 'd': /* int */
v.type=autoconv?BINRPC_T_ALL:BINRPC_T_INT;
ctx->in.s=binrpc_read_record(&ctx->in.ctx, ctx->in.s,
ctx->in.end, &v, &err);
ctx->in.end, &v, 0, &err);
if (err<0 || ((i=binrpc_val_conv_int(&v, &err))==0 && err<0))
goto error_read;
*(va_arg(ap, int*))=i;
break;
case 'f':
v.type=autoconv?BINRPC_T_ALL:BINRPC_T_DOUBLE;
ctx->in.s=binrpc_read_record(&ctx->in.ctx, ctx->in.s,
ctx->in.end, &v, &err);
ctx->in.end, &v, 0, &err);
if (err<0 || ((d=binrpc_val_conv_double(&v, &err))==0 &&
err<0))
goto error_read;
Expand All @@ -875,7 +875,7 @@ static int rpc_scan(struct binrpc_ctx* ctx, char* fmt, ...)
case 'S': /* str */
v.type=autoconv?BINRPC_T_ALL:BINRPC_T_STR;
ctx->in.s=binrpc_read_record(&ctx->in.ctx, ctx->in.s,
ctx->in.end, &v,&err);
ctx->in.end, &v, 0, &err);
if (err<0 || ((s=binrpc_val_conv_str(ctx, &v, &err))==0 &&
err<0)){
v.u.strval.s="if you get this string, you don't"
Expand All @@ -895,7 +895,7 @@ static int rpc_scan(struct binrpc_ctx* ctx, char* fmt, ...)
/* FIXME: structure reading doesn't work for now */
#if 0
ctx->in.s=binrpc_read_record(&ctx->in.ctx, ctx->in.s,
ctx->in.end, &v, &err);
ctx->in.end, &v, 0, &err);
if (err<0) goto error_read;
ctx->in.in_struct++;
*(va_arg(ap, void**))=ctx; /* use the same context */
Expand Down

0 comments on commit 39ab16e

Please sign in to comment.