#include #include #include #include "atoms.h" #include "structs.h" #include "fmt-util.h" 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),"")); } } void print_text_blk(FILE *to, const unsigned char *blk, int len, const char *pref1, const char *prefn) { int i; int col; int ch; fprintf(to,"%s\"",pref1); col = 0; for (i=0;i= 50) { fprintf(to,"\"\n"); printpref(to,prefn,pref1); putc('"',to); col = 0; } ch = blk[i]; if (ch < 32) { if ((i+1 < len) && (blk[i+1] >= '0') && (blk[i+1] <= '9')) { col += fprintf(to,"\\%03o",ch); } else { col += fprintf(to,"\\%o",ch); } } else if ((ch >= 127) && (ch < 160)) { col += fprintf(to,"\\%o",ch); } else { putc(ch,to); col ++; } } fprintf(to,"\"\n"); } void print_bin_blk(FILE *to, const unsigned char *blk, int len, const char *pref1, const char *prefn) { int i; int n; int ch; unsigned char tbuf[16]; if (len < 1) { fprintf(to,"%s%*s||\n",pref1,(3*16)+1+2-1,""); return; } fprintf(to,"%s",pref1); n = 0; for (i=0;i= 127) && (ch < 160))) { tbuf[n] = '·'; } else { tbuf[n] = ch; } if (n) putc(' ',to); fprintf(to,"%02x",ch); n = (n + 1) & 15; if (n == 0) fprintf(to," |%.16s|\n",&tbuf[0]); } if (n) fprintf(to,"%*s|%.*s|\n",((16-n)*3)+2+(n<=8),"",n,&tbuf[0]); } void print_raw_data(FILE *to, FLOW *f) { print_bin_blk(to,f->ibuf,f->ibfull,"Raw data ",0); } unsigned int get1u(FLOW *f, int offset) { if ((offset < 0) || (offset+1 > f->ibfill)) abort(); return(f->ibuf[offset]); } int get1s(FLOW *f, int offset) { int v; v = get1u(f,offset); return((v&0x80)?v-256:v); } unsigned int get2u(FLOW *f, int offset) { if ((offset < 0) || (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, int offset) { int v; v = get2u(f,offset); return((v&0x8000)?v-65536:v); } unsigned int get4u(FLOW *f, int offset) { if ((offset < 0) || (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, 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)); } 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)); }