home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <string.h>
- #include <time.h>
- #include "global.h"
- #include "mbuf.h"
- #include "ax25.h"
- #include "timer.h"
- #include "lapb.h"
- #include "trace.h"
- #include "arp.h"
- #include "ip.h"
- #include "misc.h"
- #include "netrom.h"
-
- static void netrom_dump(struct mbuf **);
-
- /* Dump an AX.25 packet header */
- void ax25_dump(struct mbuf **bpp, int check)
- {
- char tmp[20], tmp1[20];
- char control,pid,seg,ipcam;
- int16 type;
- struct ax25 hdr;
- struct ax25_addr *hp;
- int unsegmented;
- char header[128];
- char buf[80];
- struct mbuf *temp;
-
- check = check;
-
- /* Extract the address header */
- if(ntohax25(&hdr,bpp) < 0){
- /* Something wrong with the header */
- twprintf("AX25: bad header\n");
- return;
- }
-
- pax25(tmp,&hdr.source);
- pax25(tmp1,&hdr.dest);
- sprintf(header,"AX25: %s->%s ", tmp, tmp1);
-
- if(hdr.ndigis > 0){
- strcat(header,"v ");
- for(hp = &hdr.digis[0]; hp < &hdr.digis[hdr.ndigis]; hp++){
- /* Print digi string */
- pax25(tmp,hp);
- strcat(header,tmp);
- strcat(header,(hp->ssid & REPEATED) ? "*":" ");
- }
- }
-
- if(pullone(bpp,&control) != 1){
- twprintf("%s\n",header);
- return;
- }
-
- type = ftype(control);
- strcat(header,decode_type(type));
- /* Dump poll/final bit */
- if(control & PF){
- switch(hdr.cmdrsp){
- case COMMAND:
- strcat(header,"(P)");
- break;
- case RESPONSE:
- strcat(header,"(F)");
- break;
- default:
- strcat(header,"(P/F)");
- break;
- }
- }
-
- twputs(header);
-
- /* Dump sequence numbers */
- if((type & 0x3) != U) /* I or S frame? */
- twprintf(" NR=%d",(control>>5)&7);
-
- if(type == I || type == UI){
- if(type == I)
- twprintf(" NS=%d",(control>>1)&7);
- /* Decode I field */
- if(pullone(bpp,&pid) == 1){ /* Get pid */
- if(pid == PID_SEGMENT){
- unsegmented = 0;
- pullone(bpp,&seg);
- twprintf("%s remain %u", (seg & SEG_FIRST) ?
- " First seg;" : "", seg & SEG_REM);
- if(seg & SEG_FIRST)
- pullone(bpp,&pid);
- } else
- unsegmented = 1;
-
- temp = *bpp;
- if (pid == PID_NO_L3 && temp->cnt >= 20
- && temp->data[0] == 0x45
- && temp->data[1] == 0x00
- && temp->data[2] < 0x02){
- pid = PID_IP;
- ipcam = 1;
- }
- else
- ipcam = 0;
-
- if(pid == PID_SEGMENT)
- twprintf("\n");
- else{
- twprintf(" pid=");
- switch(pid){
- case PID_ARP:
- twprintf("ARP\n");
- arp_dump(bpp);
- break;
- case PID_NETROM:
- twprintf("NET/ROM\n");
- netrom_dump(bpp);
- break;
- case PID_IP:
- twprintf("IP\n");
- ip_dump(bpp,unsegmented);
- break;
- case PID_NO_L3:
- twprintf("Text\n");
- break;
- default:
- twprintf("0x%x\n",pid);
- }
- }
- }
- } else if(type == FRMR && pullup(bpp,tmp,3) == 3){
- sprintf(buf," Vr = %d Vs = %d",(tmp[1] >> 5) & MMASK,
- (tmp[1] >> 1) & MMASK);
- if(tmp[2] & W)
- strcat(buf," Invalid control field");
- if(tmp[2] & X)
- strcat(buf," Illegal I-field");
- if(tmp[2] & Y)
- strcat(buf," Too-long I-field");
- if(tmp[2] & Z)
- strcat(buf," Invalid seq number");
- twprintf(":\n%s %s\n",decode_type(ftype(tmp[0])),buf);
- }
- else
- twprintf("\n");
- }
- /* Display NET/ROM network and transport headers */
- static void netrom_dump(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) {
- pullone(bpp,tmp); /* Signature */
- pullup(bpp,tmp,ALEN);
- tmp[ALEN] = '\0';
- twprintf("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);
- twprintf(" %12s",tmp);
- pullup(bpp,tmp,ALEN);
- tmp[ALEN] = '\0';
- twprintf("%8s",tmp);
- pullup(bpp,tmp,AXALEN);
- memcpy(src.call,tmp, ALEN);
- src.ssid = tmp[ALEN];
- pax25(tmp,&src);
- twprintf(" %12s", tmp);
- pullone(bpp,tmp);
- twprintf(" %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);
- twprintf("NET/ROM: %s",tmp);
-
- pullup(bpp,tmp,AXALEN);
- memcpy(dest.call,tmp,ALEN);
- dest.ssid = tmp[ALEN];
- pax25(tmp,&dest);
- twprintf("->%s",tmp);
-
- pullup(bpp,&x,1);
- twprintf(" ttl %d\n",uchar(x));
-
- /* Read first five bytes of "transport" header */
- pullup(bpp,thdr,5);
- switch((thdr[4] & 0xf) | (thdr[0] & IPVERSION << 4)){
- case 0: /* network PID extension */
- case (0 | IPVERSION << 4): /* try to handle old IP format */
- case (1 | IPVERSION << 4): /* try to handle old IP format */
- case (2 | IPVERSION << 4): /* try to handle old IP format */
- case (3 | IPVERSION << 4): /* try to handle old IP format */
- case (4 | IPVERSION << 4): /* try to handle old IP format */
- case (5 | IPVERSION << 4): /* try to handle old IP format */
- case (6 | IPVERSION << 4): /* try to handle old IP format */
- if (thdr[0] == NRPROTO_IP && thdr[1] == NRPROTO_IP)
- ip_dump(bpp,1) ; /* new format of IP over NET/ROM */
- else
- {
- twprintf(" protocol family %x, proto %x",
- uchar(thdr[0]), uchar(thdr[1])) ;
- /* Try to use IPVERSION value to descriminate */
- /* maybe it's an old format IP datagram! */
- if ((thdr[0] & 0xf0) == IPVERSION << 4)
- {
- struct mbuf *thbuf, *save ;
- twprintf(" - old format IP\n");
- 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;
- case 1: /* Connect request */
- twprintf(" conn rqst: ckt %d/%d",uchar(thdr[0]),uchar(thdr[1]));
- pullone(bpp,&x);
- twprintf(" wnd %d",x);
- pullup(bpp,(char *)&src,AXALEN);
- pax25(tmp,&src);
- twprintf(" %s",tmp);
- pullup(bpp,(char *)&dest,AXALEN);
- pax25(tmp,&dest);
- twprintf("@%s",tmp);
- break;
- case 2: /* Connect acknowledgement */
- twprintf(" conn ack: ur ckt %d/%d my ckt %d/%d",
- uchar(thdr[0]), uchar(thdr[1]), uchar(thdr[2]),
- uchar(thdr[3]));
- pullone(bpp,&x);
- twprintf(" wnd %d",x);
- break;
- case 3: /* Disconnect request */
- twprintf(" disc: ckt %d/%d",uchar(thdr[0]),uchar(thdr[1]));
- break;
- case 4: /* Disconnect acknowledgement */
- twprintf(" disc ack: ckt %d/%d",uchar(thdr[0]),uchar(thdr[1]));
- break;
- case 5: /* Information (data) */
- twprintf(" info: ckt %d/%d",uchar(thdr[0]),uchar(thdr[1]));
- twprintf(" txseq %d rxseq %d",uchar(thdr[2]), uchar(thdr[3]));
- break;
- case 6: /* Information acknowledgement */
- twprintf(" info ack: ckt %d/%d",uchar(thdr[0]),uchar(thdr[1]));
- twprintf(" txseq %d rxseq %d",uchar(thdr[2]), uchar(thdr[3]));
- break;
- default:
- twprintf(" unknown transport type %d", thdr[4] & 0x0f) ;
- /* Try to use IPVERSION value to descriminate */
- /* maybe it's an old format IP datagram! */
- if ((thdr[0] & 0xf0) == IPVERSION << 4)
- {
- struct mbuf *thbuf, *save ;
- twprintf(" - old format IP\n");
- 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)
- twprintf(" CHOKE");
- if(thdr[4] & 0x40)
- twprintf(" NAK");
- twprintf("\n");
- }
- char *decode_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]";
- }
- }
-
-