/* ipxparse.c */ /* Copyright 1996 Volker Lendecke, Goettingen, Germany * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ipxutil.h" struct ipx_address { unsigned long net; unsigned char node[IPX_NODE_LEN]; unsigned short sock; }; struct ipx_packet { unsigned short ipx_checksum; #define IPX_NO_CHECKSUM 0xFFFF unsigned short ipx_pktsize; unsigned char ipx_tctrl; unsigned char ipx_type; #define IPX_TYPE_UNKNOWN 0x00 #define IPX_TYPE_RIP 0x01 /* may also be 0 */ #define IPX_TYPE_SAP 0x04 /* may also be 0 */ #define IPX_TYPE_SPX 0x05 /* Not yet implemented */ #define IPX_TYPE_NCP 0x11 /* $lots for docs on this (SPIT) */ #define IPX_TYPE_PPROP 0x14 /* complicated flood fill brdcast [Not supported] */ struct ipx_address ipx_dest __attribute__ ((packed)); struct ipx_address ipx_source __attribute__ ((packed)); }; #define NCP_ALLOC_SLOT_REQUEST (0x1111) #define NCP_REQUEST (0x2222) #define NCP_DEALLOC_SLOT_REQUEST (0x5555) struct ncp_request_header { __u16 type __attribute__ ((packed)); __u8 sequence __attribute__ ((packed)); __u8 conn_low __attribute__ ((packed)); __u8 task __attribute__ ((packed)); __u8 conn_high __attribute__ ((packed)); __u8 function __attribute__ ((packed)); __u8 data[0] __attribute__ ((packed)); }; #define NCP_REPLY (0x3333) #define NCP_POSITIVE_ACK (0x9999) struct ncp_reply_header { __u16 type __attribute__ ((packed)); __u8 sequence __attribute__ ((packed)); __u8 conn_low __attribute__ ((packed)); __u8 task __attribute__ ((packed)); __u8 conn_high __attribute__ ((packed)); __u8 completion_code __attribute__ ((packed)); __u8 connection_state __attribute__ ((packed)); __u8 data[0] __attribute__ ((packed)); }; void handle_ipx (unsigned char *buf, int length, char *frame, int no); void handle_ncp (struct sockaddr_ipx *source, struct sockaddr_ipx *target, unsigned char *buf, int length, int no); void handle_ipx (unsigned char *buf, int length, char *frame, int no) { struct ipx_packet *h = (struct ipx_packet *)buf; struct sockaddr_ipx s_addr; struct sockaddr_ipx d_addr; memset(&s_addr, 0, sizeof(s_addr)); memset(&d_addr, 0, sizeof(d_addr)); memcpy(s_addr.sipx_node, h->ipx_source.node, sizeof(s_addr.sipx_node)); s_addr.sipx_port = h->ipx_source.sock; s_addr.sipx_network = h->ipx_source.net; memcpy(d_addr.sipx_node, h->ipx_dest.node, sizeof(d_addr.sipx_node)); d_addr.sipx_port = h->ipx_dest.sock; d_addr.sipx_network = h->ipx_dest.net; printf("%6.6d %s from ", no, frame); ipx_print_saddr(&s_addr); printf(" to "); ipx_print_saddr(&d_addr); printf("\n"); if ( (ntohs(s_addr.sipx_port) == 0x451) || (ntohs(d_addr.sipx_port) == 0x451)) { handle_ncp(&s_addr, &d_addr, buf + sizeof(struct ipx_packet), length - sizeof(struct ipx_packet), no); } } void handle_ncp (struct sockaddr_ipx *source, struct sockaddr_ipx *target, unsigned char *buf, int length, int no) { struct ncp_request_header *rq = (struct ncp_request_header *)buf; struct ncp_reply_header *rs = (struct ncp_reply_header *)buf; unsigned char *data = NULL; int data_length = 0; int i; if (ntohs(rq->type) == NCP_REQUEST) { /* Request */ printf("NCP request: conn: %-5d, seq: %-3d, task: %-3d, ", rq->conn_low + 256 * rq->conn_high, rq->sequence, rq->task); data = buf + sizeof(struct ncp_request_header); data_length = length - sizeof(struct ncp_request_header); switch(rq->function) { case 87: printf("fn: %-3d, subfn: %-3d\n", rq->function, data[0]); switch(data[0]) { case 1: { unsigned char *p = &(data[0]); printf("Open Create File or Subdirectory\n"); printf("Name Space: %d\n", p[1]); printf("Open Create Mode: %x\n", p[2]); printf("Search Attributes: %x\n", *(__u16 *)&(p[3])); printf("Return Information Mask: %x\n", (unsigned int)(*(__u32 *)&(p[5]))); printf("Desired Access Rights: %x\n", *(__u16 *)&(p[9])); break; } case 2: printf("Initialize Search\n"); break; case 3: printf("Search for File or Subdirectory\n"); break; case 6: printf("Obtain File Or Subdirectory " "Information\n"); break; case 8: printf("Delete a File Or Subdirectory\n"); break; } data += 1; data_length -= 1; break; case 22: printf("fn: %-3d, subfn: %-3d\n", rq->function, data[2]); switch(data[2]) { case 21: printf("Get Volume Info with handle\n"); break; } data += 3; data_length -= 3; break; case 23: printf("fn: %-3d, subfn: %-3d\n", rq->function, data[2]); data += 3; data_length -= 3; break; case 24: printf("fn: %-3d\n", rq->function); printf("End of Job\n"); break; case 34: printf("fn: %-3d, subfn: %-3d\n", rq->function, data[2]); data += 3; data_length -= 3; break; case 62: printf("fn: %-3d\n", rq->function); printf("File Search Initialize\n"); break; case 63: printf("fn: %-3d\n", rq->function); printf("File Search Continue\n"); break; case 64: printf("fn: %-3d\n", rq->function); printf("Search for a file\n"); break; case 66: printf("fn: %-3d\n", rq->function); printf("Close File\n"); break; case 73: printf("fn: %-3d\n", rq->function); printf("Write to File\n"); break; case 75: printf("fn: %-3d\n", rq->function); printf("Set File Time Date Stamp\n"); break; default: printf("fn: %-3d\n", rq->function); } } if (ntohs(rs->type) == NCP_REPLY) { printf("NCP respons: conn: %-5d, seq: %-3d, task: %-3d, ", rs->conn_low + 256 * rs->conn_high, rs->sequence, rs->task); printf("compl: %-3d, conn_st: %-3d\n", rs->completion_code, rs->connection_state); data = buf + sizeof(struct ncp_reply_header); data_length = length - sizeof(struct ncp_reply_header); } if (data == NULL) { data = buf; data_length = length; } i = 0; while (i < data_length) { int j; for (j = i; j < i+16; j++) { if (j >= data_length) { printf(" "); } else { printf("%-2.2X", data[j]); } } printf(" "); for (j = i; j < i+16; j++) { if (j >= data_length) { break; } if (isprint(data[j])) { printf("%c", data[j]); } else { printf("."); } } printf("\n"); i += 16; } printf("\n"); } void main (int argc, char *argv[]) { unsigned char buf[16384]; unsigned char packet[8192]; unsigned char *b; int len; int i = 1; while (fgets(buf, sizeof(buf), stdin) != NULL) { if (strlen(buf) == sizeof(buf)-1) { fprintf(stderr, "line too long\n"); exit(1); } b = strchr(buf, ' '); if (b == NULL) { fprintf(stderr, "illegal line format\n"); exit(1); } *b = '\0'; b += 1; len = 0; while ((b[0] != '\0') && (b[1] != '\0')) { unsigned int value; if (sscanf(b, "%2x", &value) != 1) { fprintf(stderr, "illegal packet\n"); exit(1); } packet[len] = value; b += 2; len += 1; } handle_ipx(packet, len, buf, i); i += 1; } exit (0); }