/* cat > ./ax25dump.c << '\Rogue\Monster\' */ #include #include "global.h" #include "mbuf.h" #include "ax25.h" #include "timer.h" #include "lapb.h" #include "trace.h" #define uchar(c) (c & 0xff) /* char uchar(c) char c; { return (c & 0xff); } */ /* Dump an AX.25 packet header */ ax25_dump(bpp,check) struct mbuf **bpp; int check; /* Not used */ { char *decode_type(); char tmp[20]; char control,pid; int16 type,ftype(); struct ax25 hdr; struct ax25_addr *hp; printf("AX25: "); /* Extract the address header */ if(ntohax25(&hdr,bpp) < 0){ /* Something wrong with the header */ printf(" bad header!\n"); return; } pax25(tmp,&hdr.source); printf("%s",tmp); pax25(tmp,&hdr.dest); printf("->%s",tmp); if(hdr.ndigis > 0){ printf(" v"); for(hp = &hdr.digis[0]; hp < &hdr.digis[hdr.ndigis]; hp++){ /* Print digi string */ pax25(tmp,hp); printf(" %s%s",tmp,(hp->ssid & REPEATED) ? "*":""); } } if(pullup(bpp,&control,1) != 1) return; putchar(' '); type = ftype(control); printf("%s",decode_type(type)); /* Dump poll/final bit */ if(control & PF){ switch(hdr.cmdrsp){ case COMMAND: printf("(P)"); break; case RESPONSE: printf("(F)"); break; default: printf("(P/F)"); break; } } /* Dump sequence numbers */ if((type & 0x3) != U) /* I or S frame? */ printf(" NR=%d",(control>>5)&7); if(type == I || type == UI){ if(type == I) printf(" NS=%d",(control>>1)&7); /* Decode I field */ if(pullup(bpp,&pid,1) == 1){ /* Get pid */ switch(pid & (PID_FIRST | PID_LAST)){ case PID_FIRST: printf(" First frag"); break; case PID_LAST: printf(" Last frag"); break; case PID_FIRST|PID_LAST: break; /* Complete message, say nothing */ case 0: printf(" Middle frag"); break; } printf(" pid="); switch(pid & 0x3f){ case PID_ARP: printf("ARP\n"); break; case PID_NETROM: printf("NET/ROM\n"); break; case PID_IP: printf("IP\n"); break; case PID_NO_L3: printf("Text\n"); break; default: printf("0x%x\n",pid); } /* Only decode frames that are the first in a * multi-frame sequence */ switch(pid & (PID_PID | PID_FIRST)){ case PID_ARP | PID_FIRST: arp_dump(bpp); break; case PID_IP | PID_FIRST: /* Only checksum complete frames */ ip_dump(bpp,pid & PID_LAST); break; case PID_NETROM | PID_FIRST: netrom_dump(bpp); nsport headers */ static netrom_dump(bpp) struct mbuf **bpp; { struct ax25_addr src,dest; char x; char tmp[16]; char thdr[5]; register i; if(bpp == NULLBUFP || *bpp == NULLBUF) return; /* See if it is a routing broadcast */ if(uchar(*(*bpp)->data) == 0xff) { pullup(bpp,tmp,1); /* Signature */ pullup(bpp,tmp,ALEN); tmp[ALEN] = '\0'; printf("NET/ROM Routing: %s\n",tmp); for(i = 0;i < 11;i++) { if (pullup(bpp,tmp,AXALEN) < AXALEN) break; memcpy(src.call,tmp,ALEN); src.ssid = tmp[ALEN]; pax25(tmp,&src); printf(" %12s",tmp); pullup(bpp,tmp,ALEN); tmp[ALEN] = '\0'; printf("%8s",tmp); pullup(bpp,tmp,AXALEN); memcpy(src.call,tmp, ALEN); src.ssid = tmp[ALEN]; pax25(tmp,&src); printf(" %12s", tmp); pullup(bpp,tmp,1); printf(" %3u\n", (unsigned)uchar(tmp[0])); } return; } /* Decode network layer */ pullup(bpp,tmp,AXALEN); memcpy(src.call,tmp,ALEN); src.ssid = tmp[ALEN]; pax25(tmp,&src); printf("NET/ROM: %s",tmp); pullup(bpp,tmp,AXALEN); memcpy(dest.call,tmp,ALEN); dest.ssid = tmp[ALEN]; pax25(tmp,&dest); printf("->%s",tmp); pullup(bpp,&x,1); printf(" ttl %d\n",uchar(x)); printf(" "); /* Read first five bytes of "transport" header */ pullup(bpp,thdr,5); switch(thdr[4] & 0xf){ case 1: /* Connect request */ printf("conn rqst: ckt %d/%d",uchar(thdr[0]),uchar(thdr[1])); pullup(bpp,&x,1); printf(" wnd %d",x); pullup(bpp,(char *)&src,sizeof(struct ax25_addr)); pax25(tmp,&src); printf(" %s",tmp); pullup(bpp,(char *)&dest,sizeof(struct ax25_addr)); pax25(tmp,&dest); printf("->%s",tmp); break; case 2: /* Connect acknowledgement */ printf("conn ack: ur ckt %d/%d my ckt %d/%d", uchar(thdr[0]), uchar(thdr[1]), uchar(thdr[2]), uchar(thdr[3])); pullup(bpp,&x,1); printf(" wnd %d",x); break; case 3: /* Disconnect request */ printf("disc: ckt %d/%d",uchar(thdr[0]),uchar(thdr[1])); break; case 4: /* Disconnect acknowledgement */ printf("disc ack: ckt %d/%d",uchar(thdr[0]),uchar(thdr[1])); break; case 5: /* Information (data) */ printf("info: ckt %d/%d",uchar(thdr[0]),uchar(thdr[1])); printf(" txseq %d rxseq %d",uchar(thdr[2]), uchar(thdr[3])); break; case 6: /* Information acknowledgement */ printf("info ack: ckt %d/%d",uchar(thdr[0]),uchar(thdr[1])); printf(" txseq %d rxseq %d",uchar(thdr[2]), uchar(thdr[3])); break; default: /* maybe it's an IP datagram! */ /* the following is gross and disgusting */ { struct mbuf *thbuf, *save ; if ((thbuf = alloc_mbuf(5)) == NULLBUF) break ; thbuf->cnt = 5 ; memcpy(thbuf->data,thdr,5) ; save = *bpp ; *bpp = thbuf ; append(bpp,save) ; ip_dump(bpp,1) ; } break; } if(thdr[4] & 0x80) printf(" CHOKE"); if(thdr[4] & 0x40) printf(" NAK"); printf("\n"); } char * decode_type(type) int16 type; { switch(uchar(type)){ case I: return "I"; case SABM: return "SABM"; case DISC: return "DISC"; case DM: return "DM"; case UA: return "UA"; case RR: return "RR"; case RNR: return "RNR"; case REJ: return "REJ"; case FRMR: return "FRMR"; case UI: return "UI"; default: return "[invalid]"; } }