head 1.14; access; symbols; locks mouse:1.14; strict; comment @ * @; 1.14 date 2010.02.25.05.45.57; author mouse; state Exp; branches; next 1.13; 1.13 date 2010.02.25.05.40.06; author mouse; state Exp; branches; next 1.12; 1.12 date 2010.02.25.05.38.35; author mouse; state Exp; branches; next 1.11; 1.11 date 2010.02.25.05.35.47; author mouse; state Exp; branches; next 1.10; 1.10 date 2010.02.25.05.28.11; author mouse; state Exp; branches; next 1.9; 1.9 date 2010.02.25.02.44.44; author mouse; state Exp; branches; next 1.8; 1.8 date 2010.02.25.02.27.19; author mouse; state Exp; branches; next 1.7; 1.7 date 2010.02.25.00.34.06; author mouse; state Exp; branches; next 1.6; 1.6 date 2010.02.25.00.32.26; author mouse; state Exp; branches; next 1.5; 1.5 date 2010.02.23.22.53.52; author mouse; state Exp; branches; next 1.4; 1.4 date 2010.02.23.22.28.58; author mouse; state Exp; branches; next 1.3; 1.3 date 2010.02.18.03.08.52; author mouse; state Exp; branches; next 1.2; 1.2 date 2010.02.18.03.02.14; author mouse; state Exp; branches; next 1.1; 1.1 date 2010.02.16.06.29.39; author mouse; state Exp; branches; next ; desc @fmt-util.c @ 1.14 log @Add padding calls where tests show the need for them. @ text @#include #include #include #include "atoms.h" #include "structs.h" #include "fmt-util.h" typedef struct getpriv GETPRIV; struct getpriv { unsigned int flags; #define GPF_DISABLE 0x00000001 unsigned char *v; #define GET_BLK_1 0x01 #define GET_BLK_2 0x02 #define GET_BLK_4 0x04 #define GET_BLK_BIN 0x08 #define GET_BLK_TXT 0x10 #define GET_BLK_PAD 0x20 unsigned int a; unsigned int l; } ; static int printpref(FILE *to, const char *pref, const char *ifnil) { if (pref) { return(fprintf(to,"%s",pref)); } else { return(fprintf(to,"%*s",(int)strlen(ifnil),"")); } } static void gp_room(GETPRIV *p, unsigned int n) { if (n > p->a) p->v = realloc(p->v,(p->a=n)*sizeof(*p->v)); } void get_init(FLOW *f) { GETPRIV *p; p = malloc(sizeof(GETPRIV)); p->flags = GPF_DISABLE; p->v = 0; p->a = 0; p->l = 0; f->getpriv = p; } void get_free(FLOW *f) { GETPRIV *p; p = f->getpriv; free(p->v); free(p); f->getpriv = 0; } void get_clear(FLOW *f) { GETPRIV *p; p = f->getpriv; p->flags &= ~GPF_DISABLE; gp_room(p,f->ibfill); p->l = f->ibfill; memset(p->v,0,f->ibfill); } void get_done(FLOW *f, FILE *o) { GETPRIV *p; int i; p = f->getpriv; if (p->l != f->ibfill) abort(); if (p->flags & GPF_DISABLE) return; for (i=0;iibfill;i++) { switch (p->v[i]) { case GET_BLK_1: case GET_BLK_2: case GET_BLK_4: case GET_BLK_BIN: case GET_BLK_TXT: case GET_BLK_PAD: break; default: fprintf(o,"*** map[%d] = %02x\n",i,p->v[i]); break; } } p->flags |= GPF_DISABLE; } void get_disable(FLOW *f) { GETPRIV *p; p = f->getpriv; p->flags |= GPF_DISABLE; } static void get_record_blk(FLOW *f, unsigned int offset, unsigned int len, unsigned char type) { GETPRIV *p; unsigned char *vp; p = f->getpriv; if (p->flags & GPF_DISABLE) return; if ((offset > p->l) || (len > p->l) || (offset+len > p->l)) abort(); gp_room(f->getpriv,offset+len); for (vp=p->v+offset;len>0;len--,vp++) *vp |= type; } void get_pad(FLOW *f, unsigned int offset, unsigned int len) { get_record_blk(f,offset,len,GET_BLK_PAD); } static void get_record(FLOW *f, unsigned int offset, int kind) { switch (kind) { case 1: get_record_blk(f,offset,1,GET_BLK_1); break; case 2: get_record_blk(f,offset,2,GET_BLK_2); break; case 4: get_record_blk(f,offset,4,GET_BLK_4); break; default: abort(); break; } } void print_text_blk(FLOW *f, FILE *o, unsigned int offset, int len, const char *pref1, const char *prefn) { int i; int col; int ch; const unsigned char *blk; get_record_blk(f,offset,len,GET_BLK_TXT); fprintf(o,"%s\"",pref1); blk = f->ibuf + offset; col = 0; for (i=0;i= 50) { fprintf(o,"\"\n"); printpref(o,prefn,pref1); putc('"',o); col = 0; } ch = blk[i]; if (ch < 32) { if ((i+1 < len) && (blk[i+1] >= '0') && (blk[i+1] <= '9')) { col += fprintf(o,"\\%03o",ch); } else { col += fprintf(o,"\\%o",ch); } } else if ((ch >= 127) && (ch < 160)) { col += fprintf(o,"\\%o",ch); } else { putc(ch,o); col ++; } } fprintf(o,"\"\n"); } void print_padded_text_blk(FLOW *f, FILE *o, unsigned int offset, int len, const char *pref1, const char *prefn) { print_text_blk(f,o,offset,len,pref1,prefn); get_pad(f,offset+len,pad(len)); } void print_bin_blk(FLOW *f, FILE *o, unsigned int offset, int len, const char *pref1, const char *prefn) { int i; int n; int ch; unsigned char *blk; unsigned char tbuf[16]; if (len < 1) { fprintf(o,"%s%*s||\n",pref1,(3*16)+1+2-1,""); return; } get_record_blk(f,offset,len,GET_BLK_BIN); fprintf(o,"%s",pref1); blk = f->ibuf + offset; n = 0; for (i=0;i= 127) && (ch < 160))) { tbuf[n] = '·'; } else { tbuf[n] = ch; } if (n) putc(' ',o); fprintf(o,"%02x",ch); n = (n + 1) & 15; if (n == 0) fprintf(o," |%.16s|\n",&tbuf[0]); } if (n) fprintf(o,"%*s|%.*s|\n",((16-n)*3)+2+(n<=8),"",n,&tbuf[0]); } void print_raw_data(FILE *o, FLOW *f) { get_disable(f); print_bin_blk(f,o,0,f->ibfull,"Raw data ",0); } unsigned int get1u(FLOW *f, unsigned int offset) { get_record(f,offset,1); if (offset+1 > f->ibfill) abort(); return(f->ibuf[offset]); } int get1s(FLOW *f, unsigned int offset) { int v; v = get1u(f,offset); return((v&0x80)?v-256:v); } unsigned int get2u(FLOW *f, unsigned int offset) { get_record(f,offset,2); if (offset+2 > f->ibfill) abort(); switch (f->conn->endian) { case END_L: return(f->ibuf[offset]+(f->ibuf[offset+1]*256)); break; case END_B: return(f->ibuf[offset+1]+(f->ibuf[offset]*256)); break; default: abort(); break; } } int get2s(FLOW *f, unsigned int offset) { int v; v = get2u(f,offset); return((v&0x8000)?v-65536:v); } unsigned int get4u(FLOW *f, unsigned int offset) { get_record(f,offset,4); if (offset+4 > f->ibfill) abort(); switch (f->conn->endian) { case END_L: return( f->ibuf[offset ] + (f->ibuf[offset+1] * 0x00000100) + (f->ibuf[offset+2] * 0x00010000) + (f->ibuf[offset+3] * 0x01000000) ); break; case END_B: return( f->ibuf[offset+3] + (f->ibuf[offset+2] * 0x00000100) + (f->ibuf[offset+1] * 0x00010000) + (f->ibuf[offset ] * 0x01000000) ); break; default: abort(); break; } } /* * There's a dilemma here. We'd _like_ to test the 0x80000000 bit and * then maybe subtract 0x100000000, parallel to get2s and get1s. But * the preprocessor can't even test sizeof(int), which isn't the right * test anyway (because we want size in bits, not in chars). We can * test at runtime, with something like 0x80000000U*2U, but the * ">32bit" case involves a number too large for 32 bits, which draws * a warning, and it's a warning we don't want to just turn off. * * I'm not sure what the best answer is. For the moment, we just * blindly assume that int is 32 bits wide. :( */ int get4s(FLOW *f, unsigned int offset) { return(get4u(f,offset)); } unsigned int ltob_u(unsigned int v) { return(v&0xff); } int ltob_s(unsigned int v) { return((v&0x80)?(v&0xff)-0x100:(v&0xff)); } unsigned int ltos_u(unsigned int v) { return(v&0xffff); } int ltos_s(unsigned int v) { return((v&0x8000)?(v&0xffff)-0x10000:(v&0xffff)); } void print_xid_alt(FILE *o, unsigned int id, int nalt, ...) { va_list ap; unsigned int val; const char *s; va_start(ap,nalt); for (;nalt>0;nalt--) { val = va_arg(ap,unsigned int); s = va_arg(ap,const char *); if (id == val) { fprintf(o,"%s",s); return; } } va_end(ap); fprintf(o,XID_FMT,id); } void print_xid_z(FILE *o, unsigned int id, const char *if0) { if (id == 0) fprintf(o,"%s",if0); else fprintf(o,XID_FMT,id); } void print_set_alt(FILE *to, const char *pref1, const char *prefn, unsigned int set, const SETVALS *setv, int nalt, ...) { va_list ap; int i; int col; const char *sep; unsigned int bit; const char *txt; char *hex; void add_string(const char *s) { if (col+strlen(s) > 70) { fprintf(to,"\n"); col = printpref(to,prefn,pref1); sep = ""; } col += fprintf(to,"%s%s",sep,s); sep = " "; } fprintf(to,"%s",pref1); sep = ""; col = strlen(pref1); for (i=0;setv[i].bit;i++) { if (! (set & setv[i].bit)) continue; set &= ~setv[i].bit; add_string(setv[i].string); } va_start(ap,nalt); for (;nalt>0;nalt--) { bit = va_arg(ap,unsigned int); txt = va_arg(ap,const char *); if (set & bit) { set &= ~bit; add_string(txt); } } va_end(ap); if (set) { asprintf(&hex,"0x%x",set); add_string(hex); free(hex); } fprintf(to,"\n"); } void print_set(FILE *to, const char *pref1, const char *prefn, unsigned int set, const SETVALS *setv) { print_set_alt(to,pref1,prefn,set,setv,0); } unsigned int bitcount(unsigned int v) { v = ((v >> 1) & 0x55555555) + (v & 0x55555555); v = ((v >> 2) & 0x33333333) + (v & 0x33333333); v = ((v >> 4) & 0x0f0f0f0f) + (v & 0x0f0f0f0f); v = ((v >> 8) & 0x00ff00ff) + (v & 0x00ff00ff); v = ((v >> 16) & 0x0000ffff) + (v & 0x0000ffff); return(v); } unsigned int pad(unsigned int n) { return("\0\3\2\1"[n&3]); } unsigned int padded(unsigned int n) { return(n+pad(n)); } void *copy_block(const void *data, int len) { void *b; b = malloc(len); bcopy(data,b,len); return(b); } void print_atom(FILE *to, CONN *c, unsigned int a) { const char *an; an = atoms_lookup(c->atoms,a); if (an) { fprintf(to,"%s",an); return; } fprintf(to,XID_FMT" (unknown)",a); } void print_atom_z(FILE *to, CONN *c, unsigned int a, const char *if0) { if (a == 0) { fprintf(to,"%s",if0); } else { print_atom(to,c,a); } } void print_timestamp(FILE *to, unsigned int ts) { if (ts == 0) { fprintf(to,"CurrentTime"); } else { fprintf(to,"%u",ts); } } void print_choice(FILE *o, unsigned int val, int nalt, ...) { va_list ap; unsigned int v; const char *s; va_start(ap,nalt); for (;nalt>0;nalt--) { v = va_arg(ap,unsigned int); s = va_arg(ap,const char *); if (val == v) { fprintf(o,"%s",s); return; } } va_end(ap); fprintf(o,"%u (INVALID)",val); } void minlength(FLOW *f, FILE *o, unsigned int minlen) { if (f->ibfill < minlen) { fprintf(o,"*** Too short (min length %d)\n",minlen); print_raw_data(o,f); set_eof(f); abort_packet_print(); } } void exactlength(FLOW *f, FILE *o, unsigned int len) { if (f->ibfill != len) { fprintf(o,"*** Length wrong (length %d, should be %d)\n",f->ibfill,len); print_raw_data(o,f); set_eof(f); abort_packet_print(); } } void rep_hdr(FLOW *f, FILE *o, const char *name) { fprintf(o,"%s reply, length %d\n",name,f->ibfill); fprintf(o," Sequence number: %04x\n",get2u(f,2)); EXACTLENGTH(32+(4*get4u(f,4))); } void req_hdr_min(FLOW *f, FILE *o, const char *name, int len) { fprintf(o,"%s request, length %d\n",name,f->ibfill); fprintf(o," Sequence number: %08x\n",f->conn->reqseq); MINLENGTH(len); } void req_hdr_exact(FLOW *f, FILE *o, const char *name, int len) { fprintf(o,"%s request, length %d\n",name,f->ibfill); fprintf(o," Sequence number: %08x\n",f->conn->reqseq); EXACTLENGTH(len); } void event_hdr(FLOW *f, FILE *o, const char *name) { fprintf(o,"%s event\n",name); EXACTLENGTH(32); fprintf(o," Sequence number: %04x\n",get2u(f,2)); } void error_hdr(FLOW *f, FILE *o, const char *name) { fprintf(o,"%s error\n",name); EXACTLENGTH(32); fprintf(o," Sequence number: %04x\n",get2u(f,2)); fprintf(o," Minor opcode: %u\n",get2u(f,8)); fprintf(o," Major opcode: %u\n",get1u(f,10)); } @ 1.13 log @Check reply length more stringently. @ text @d119 5 d178 6 @ 1.12 log @Set bits starting at the correct offset in the checking buffer! @ text @d500 1 @ 1.11 log @Leave the buffer-checking machinery disabled when not unpacking a packet. This allows code such as the preliminary packet classifier code to use get[124][su]() without crashing because the checking isn't set up. @ text @d116 1 a116 1 for (vp=p->v;len>0;len--,vp++) *vp |= type; @ 1.10 log @Add get_disable(), to mark the buffer-checking machinery disabled for this packet, and use it where appropriate. @ text @d46 1 a46 1 p->flags = 0; d68 1 d81 1 d96 1 d113 1 @ 1.9 log @Add checking that all bytes in packets are accounted for and none used multiple times with inconsistent sizes. This should catch most of the worst of botched packet parsing bugs. @ text @d96 8 @ 1.8 log @Type the offset arg to get[124][su] as unsigned, which it really is. This also means removing <0 checks. @ text @d10 16 d36 90 a125 1 void print_text_blk(FILE *o, const unsigned char *blk, int len, const char *pref1, const char *prefn) d130 1 d132 1 d134 1 d163 1 a163 1 void print_bin_blk(FILE *o, const unsigned char *blk, int len, const char *pref1, const char *prefn) d168 1 d175 1 d177 1 d205 2 a206 1 print_bin_blk(o,f->ibuf,f->ibfull,"Raw data ",0); d211 1 d226 1 d251 1 @ 1.7 log @Rename FILE * arg to print_raw_data, for consistency with other code. @ text @d97 1 a97 1 unsigned int get1u(FLOW *f, int offset) d99 1 a99 1 if ((offset < 0) || (offset+1 > f->ibfill)) abort(); d103 1 a103 1 int get1s(FLOW *f, int offset) d111 1 a111 1 unsigned int get2u(FLOW *f, int offset) d113 1 a113 1 if ((offset < 0) || (offset+2 > f->ibfill)) abort(); d127 1 a127 1 int get2s(FLOW *f, int offset) d135 1 a135 1 unsigned int get4u(FLOW *f, int offset) d137 1 a137 1 if ((offset < 0) || (offset+4 > f->ibfill)) abort(); d169 1 a169 1 int get4s(FLOW *f, int offset) @ 1.6 log @Rename the FILE * argument to print_*_blk, for consistency with most of the rest of the code. @ text @d92 1 a92 1 void print_raw_data(FILE *to, FLOW *f) d94 1 a94 1 print_bin_blk(to,f->ibuf,f->ibfull,"Raw data ",0); @ 1.5 log @Create XID_FMT and use it for printing XIDs. @ text @d20 1 a20 1 void print_text_blk(FILE *to, const unsigned char *blk, int len, const char *pref1, const char *prefn) d26 1 a26 1 fprintf(to,"%s\"",pref1); d30 3 a32 3 { fprintf(to,"\"\n"); printpref(to,prefn,pref1); putc('"',to); d38 1 a38 1 { col += fprintf(to,"\\%03o",ch); d41 1 a41 1 { col += fprintf(to,"\\%o",ch); d45 1 a45 1 { col += fprintf(to,"\\%o",ch); d48 1 a48 1 { putc(ch,to); d52 1 a52 1 fprintf(to,"\"\n"); d55 1 a55 1 void print_bin_blk(FILE *to, const unsigned char *blk, int len, const char *pref1, const char *prefn) d63 1 a63 1 { fprintf(to,"%s%*s||\n",pref1,(3*16)+1+2-1,""); d66 1 a66 1 fprintf(to,"%s",pref1); d71 1 a71 1 if (i) printpref(to,prefn,pref1); d74 1 a74 1 fprintf(to," "); d84 2 a85 2 if (n) putc(' ',to); fprintf(to,"%02x",ch); d87 1 a87 1 if (n == 0) fprintf(to," |%.16s|\n",&tbuf[0]); d89 1 a89 1 if (n) fprintf(to,"%*s|%.*s|\n",((16-n)*3)+2+(n<=8),"",n,&tbuf[0]); @ 1.4 log @Move event_hdr and error_hdr from fmt-core.c statics to fmt-util.c globals. This is preparatory to their use by extensions. @ text @d210 1 a210 1 fprintf(o,"0x%x",id); d215 1 a215 1 if (id == 0) fprintf(o,"%s",if0); else fprintf(o,"0x%x",id); d307 1 a307 1 fprintf(to,"0x%08x (unknown)",a); @ 1.3 log @Move minlength, exactlength, rep_hdr, req_hdr_min, req_hdr_exact to fmt-util.c, for use by more than just core. @ text @d388 16 @ 1.2 log @Shut off a spurious warning. Comment how and why. @ text @d348 40 @ 1.1 log @Initial revision @ text @d157 12 d171 1 a171 9 int v; v = get4u(f,offset); if (0x80000000U*2U == 0) { return(v); } else { return(v-0x100000000U); } @