pktdump.c 5.94 KB
Newer Older
1 2 3 4 5
/* pktdump.c */

/* $Id$ */

#include "fidodefs.h"
deuce's avatar
deuce committed
6
#include "xpendian.h"	/* swap */
7 8
#include "dirwrap.h"	/* _PATH_DEVNULL */
#include <stdio.h>
9
#include <string.h>
10 11 12 13 14 15 16

FILE* nulfp;
FILE* bodyfp;

/****************************************************************************/
/* Returns an ASCII string for FidoNet address 'addr'                       */
/****************************************************************************/
17
char *faddrtoa(struct fidoaddr* addr, char* outstr)
18 19 20 21 22 23
{
	static char str[64];

	if(addr==NULL)
		return("0:0/0");
	sprintf(str,"%hu:%hu/%hu",addr->zone,addr->net,addr->node);
24 25 26 27
	if(addr->point)
		sprintf(str + strlen(str), ".%hu", addr->point);
	if(addr->domain[0])
		sprintf(str + strlen(str), "@%s", addr->domain);
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
	if(outstr==NULL)
		return(str);
	strcpy(outstr,str);
	return(outstr);
}

char* freadstr(FILE* fp, char* str, size_t maxlen)
{
	int		ch;
	size_t	len=0;

	while((ch=fgetc(fp))!=EOF && len<maxlen) {
		str[len++]=ch;
		if(ch==0)
			break;
	}

	str[maxlen-1]=0;

	return(str);
}
	

int pktdump(FILE* fp, const char* fname)
{
53
	int			ch,lastch=0;
54 55 56 57 58
	char		buf[128];
	char		to[FIDO_NAME_LEN];
	char		from[FIDO_NAME_LEN];
	char		subj[FIDO_SUBJ_LEN];
	long		offset;
59 60
	struct fidoaddr	orig = {0};
	struct fidoaddr	dest = {0};
61 62 63
	fpkthdr_t	pkthdr;
	fpkdmsg_t	pkdmsg;

64
	if(fread(&pkthdr,sizeof(pkthdr),1,fp) != 1) {
65
		fprintf(stderr,"%s !Error reading pkthdr (%" XP_PRIsize_t "u bytes)\n"
66 67 68 69 70 71 72 73 74 75 76 77
			,fname,sizeof(pkthdr));
		return(-1);
	}

	fseek(fp,-2L,SEEK_END);
	fread(buf,sizeof(BYTE),sizeof(buf),fp);
	if(memcmp(buf,"\x00\x00",2)) {
		fprintf(stderr,"%s !Packet missing terminating nulls: %02X %02X\n"
			,fname,buf[0],buf[1]);
//		return(-2);
	}

78 79 80 81 82 83 84 85 86 87
	printf("%s Packet Type ", fname);

	if(pkthdr.type2.pkttype != 2) {
		fprintf(stderr, "%u (unsupported packet type)\n", pkthdr.type2.pkttype);
		return -3;
	}

	orig.zone=pkthdr.type2.origzone;
	orig.net=pkthdr.type2.orignet;
	orig.node=pkthdr.type2.orignode;
88 89
	orig.point=0;

90 91 92
	dest.zone=pkthdr.type2.destzone;
	dest.net=pkthdr.type2.destnet;
	dest.node=pkthdr.type2.destnode;
93 94
	dest.point=0;				/* No point info in the 2.0 hdr! */

95 96
	if(pkthdr.type2plus.cword==BYTE_SWAP_16(pkthdr.type2plus.cwcopy)  /* 2+ Packet Header */
		&& pkthdr.type2plus.cword&1) {
97 98 99
		fprintf(stdout,"2+ (prod: %02X%02X, rev: %u.%u)"
			,pkthdr.type2plus.prodcodeHi	,pkthdr.type2plus.prodcodeLo
			,pkthdr.type2plus.prodrevMajor	,pkthdr.type2plus.prodrevMinor);
100 101 102 103
		dest.point=pkthdr.type2plus.destpoint;
		if(pkthdr.type2plus.origpoint!=0 && orig.net==0xffff) {	/* see FSC-0048 for details */
			orig.net=pkthdr.type2plus.auxnet;
			orig.point=pkthdr.type2plus.origpoint;
104
		}
105
		if(pkthdr.type2plus.origzone != orig.zone)
106
			printf("!Warning: origination zone mismatch in type 2+ packet header (%u != %u)\n"
107 108
				,pkthdr.type2plus.origzone, orig.zone);
		if(pkthdr.type2plus.destzone != dest.zone)
109
			printf("!Warning: destination zone mismatch in type 2+ packet header (%u != %u)\n"
110
				,pkthdr.type2plus.destzone, dest.zone);
111
	} else if(pkthdr.type2_2.subversion==2) {					/* Type 2.2 Packet Header (FSC-45) */
112
		fprintf(stdout,"2.2 (prod: %02X, rev: %u)", pkthdr.type2_2.prodcode, pkthdr.type2_2.prodrev);
113
		dest.point=pkthdr.type2_2.destpoint; 
114 115
		memcpy(orig.domain, pkthdr.type2_2.origdomn, sizeof(pkthdr.type2_2.origdomn));
		memcpy(dest.domain, pkthdr.type2_2.destdomn, sizeof(pkthdr.type2_2.destdomn));
116
	} else
117
		fprintf(stdout,"2.0 (prod: %02X, serial: %u)", pkthdr.type2.prodcode, pkthdr.type2.sernum);
118

119 120
	printf(" from %s",faddrtoa(&orig,NULL));
	printf(" to %s\n"	,faddrtoa(&dest,NULL));
121

122 123
	if(pkthdr.type2.password[0])
		fprintf(stdout,"Password: '%.*s'\n",sizeof(pkthdr.type2.password),pkthdr.type2.password);
124

125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
	fseek(fp,sizeof(pkthdr),SEEK_SET);

	/* Read/Display packed messages */
	while(!feof(fp)) {

		printf("%08lX\n",offset=ftell(fp));

		/* Read fixed-length header fields */
		if(fread(&pkdmsg,sizeof(BYTE),sizeof(pkdmsg),fp)!=sizeof(pkdmsg))
			break;
		/* Display fixed-length fields */
		printf("%s %06lX Packed Message Type: %d from %u/%u to %u/%u\n"
			,fname
			,offset
			,pkdmsg.type
			,pkdmsg.orignet, pkdmsg.orignode
			,pkdmsg.destnet, pkdmsg.destnode);
		printf("Attribute: %04X\n",pkdmsg.attr);
		printf("Date/Time: %s\n",pkdmsg.time);

		/* Read variable-length header fields */
		freadstr(fp,to,sizeof(to));
		freadstr(fp,from,sizeof(from));
		freadstr(fp,subj,sizeof(subj));
	
		/* Display variable-length fields */
		printf("%-4s : %s\n","To",to);
		printf("%-4s : %s\n","From",from);
		printf("%-4s : %s\n","Subj",subj);

		fprintf(bodyfp,"\n-start of message text-\n");

		while((ch=fgetc(fp))!=EOF && ch!=0) {
			if(lastch=='\r' && ch!='\n')
				fputc('\n',bodyfp);
			fputc(lastch=ch,bodyfp);
		}

		fprintf(bodyfp,"\n-end of message text-\n");
	}

	return(0);
}

169 170
char* usage = "usage: pktdump [-body] <file1.pkt> [file2.pkt] [...]\n";

171 172 173 174
int main(int argc, char** argv)
{
	FILE*	fp;
	int		i;
175 176 177 178 179 180 181 182 183 184 185 186
	char	revision[16];

	sscanf("$Revision$", "%*s %s", revision);

	fprintf(stderr,"pktdump rev %s - Dump FidoNet Packets\n\n"
		,revision
		);

	if(argc<2) {
		fprintf(stderr,"%s",usage);
		return -1;
	}
187 188 189 190 191 192 193 194

	if((nulfp=fopen(_PATH_DEVNULL,"w+"))==NULL) {
		perror(_PATH_DEVNULL);
		return -1;
	}
	bodyfp=nulfp;

	if(sizeof(fpkthdr_t)!=FIDO_PACKET_HDR_LEN) {
195
		printf("sizeof(fpkthdr_t)=%" XP_PRIsize_t "u, expected: %d\n",sizeof(fpkthdr_t),FIDO_PACKET_HDR_LEN);
196 197 198
		return(-1);
	}
	if(sizeof(fpkdmsg_t)!=FIDO_PACKED_MSG_HDR_LEN) {
199
		printf("sizeof(fpkdmsg_t)=%" XP_PRIsize_t "u, expected: %d\n",sizeof(fpkdmsg_t),FIDO_PACKED_MSG_HDR_LEN);
200 201 202
		return(-1);
	}
	if(sizeof(fmsghdr_t)!=FIDO_STORED_MSG_HDR_LEN) {
203
		printf("sizeof(fmsghdr_t)=%" XP_PRIsize_t "u, expected: %d\n",sizeof(fmsghdr_t),FIDO_STORED_MSG_HDR_LEN);
204 205 206 207 208 209 210 211 212 213
		return(-1);
	}

	for(i=1;i<argc;i++) {
		if(argv[i][0]=='-') {
			switch(tolower(argv[i][1])) {
				case 'b':
					bodyfp=stdout;;
					break;
				default:
214
					printf("%s",usage);
215 216 217 218 219 220 221 222 223 224 225 226 227 228
					return(0);
			}
			continue;
		}
		fprintf(stdout,"Opening %s\n",argv[i]);
		if((fp=fopen(argv[i],"rb"))==NULL) {
			perror(argv[i]);
			continue;
		}
		pktdump(fp, argv[i]);
		fclose(fp);
	}

	return(0);
deuce's avatar
deuce committed
229
}