build standalone ipx utilities without ncpfs private headers

This commit is contained in:
Mario Fetka
2026-04-29 19:17:02 +02:00
parent 80f13f2193
commit ea1cadb737
32 changed files with 11006 additions and 666 deletions

45
tools/README Normal file
View File

@@ -0,0 +1,45 @@
This is a VERY stupid packet sniffer for IPX ethernet packets.
=============================================
! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
! ! ! S E C U R I T Y W A R N I N G ! ! !
! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
=============================================
If you are using unencrypted passwords, and use this tool to send a
dump to somebody else or store it on a computer, you might very well
store passwords there. So, be VERY careful! This is exactly the kind
of tools Novell designed the encrypted passwords for (or against).
I hacked it together to be able to help people with problems with
ncpfs. The socket handling was taken from Statnet-2.0.
You can use it to watch commercial NetWare clients when they talk to
servers. I divided the program into 2 parts, ipxdump and ipxparse.
ipxdump simply pumps all the IPX frames it receives to stdout.
If you use ipxdump to watch a workstation, you can use the simple
filter function ipxdump provides. You can call ipxdump with the node
address of the workstation you want to watch. This way only the
packets this workstation sends and receives are monitored. As an
example, I call ipxdump as
./ipxdump 00001B038B11
to look at my 286/10MHz test 'workstation'. ipxdump still generates
huge amounts of data, so you should be very careful to start it just
before you perform the operation (such as file creation for OS/2
clients with NW4.1 as a server, or a 'dir' on a directory with long
and short file names, or an encrypted password change ;-)) and stop it
directly after that. And, please gzip -9 and uuencode it before you
send it to anybody.
ipxparse will eventually take apart the dump that ipxdump
generates. They can as well be used in a pipe. Currently ipxparse does
not do anything sensible, but that will definitely change.
Volker Lendecke
<lendecke@namu01.gwdg.de>

305
tools/ipxdump.c Normal file
View File

@@ -0,0 +1,305 @@
/*
ipxdump.c
Copyright 1996 Volker Lendecke, Goettingen, Germany
Copyright 1999, 2001 Petr Vandrovec, Prague, Czech Republic
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.
Revision History:
1.01 1999, December, 15 Petr Vandrovec <vandrove@vc.cvut.cz>
Use sigaction instead of signal, so ^C works
immediately and not after next frame comes
(bsd vs. sysv signal() semantic bug)
1.02 2001, July 15 Petr Vandrovec <vandrove@vc.cvut.cz>
Add #include <stdlib> to fix some warnings.
*/
#include "config.h"
#include <unistd.h>
#include <sys/types.h>
#include <ncp/ext/socket.h>
/* TBD */
#include <netinet/in.h>
#ifdef HAVE_NETINET_IF_ETHER_H
#include <netinet/if_ether.h>
#else
#include <linux/if_ether.h>
#endif
#include <string.h>
#include <sys/ioctl.h>
#include <ncp/kernel/if.h>
#include <signal.h>
#include <stdlib.h>
/* TBD */
#include <netinet/ip.h>
/* TBD */
#include <netinet/tcp.h>
#include <stdio.h>
#include <time.h>
#include <signal.h>
#include "ipxutil.h"
struct ipx_address
{
IPXNet net __attribute__((packed));
IPXNode node __attribute__((packed));
IPXPort sock __attribute__((packed));
};
struct ipx_packet
{
unsigned short ipx_checksum __attribute__((packed));
#define IPX_NO_CHECKSUM 0xFFFF
unsigned short ipx_pktsize __attribute__((packed));
unsigned char ipx_tctrl __attribute__((packed));
unsigned char ipx_type __attribute__((packed));
#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));
};
void handle_frame(unsigned char *buf, int length, struct sockaddr *saddr);
void handle_ipx(const char *frame, unsigned char *buf);
static int filter = 0;
static int allframes = 0;
static IPXNode filter_node;
static const char* progname;
static void usage(void) {
fprintf(stderr, "usage: %s [-r] [-d device] [node]\n", progname);
}
static int exit_request = 0;
static void
int_handler(int dummy)
{
exit_request = 1;
(void)dummy;
}
int
main(int argc, char *argv[])
{
int sd;
struct ifreq ifr, oldifr;
const char *device = "eth0";
struct sockaddr saddr;
int sizeaddr;
unsigned char buf[4096];
int length;
int opt;
struct sigaction saint;
progname = strrchr(argv[0], '/');
if (progname)
progname++;
else
progname = argv[0];
saint.sa_handler = int_handler;
saint.sa_flags = 0;
sigemptyset(&saint.sa_mask);
sigaction(SIGINT, &saint, NULL);
while ((opt = getopt(argc, argv, "rd:h")) != -1) {
switch (opt) {
case 'r':allframes = 1;
break;
case 'd':device = optarg;
break;
case 'h':usage();
return 5;
case ':':;
case '?':break;
default: printf("?? unknown option returned by getopt\n");
break;
}
}
if (optind < argc)
{
if (ipx_sscanf_node(argv[optind], filter_node) != 0)
{
usage();
exit(1);
}
filter = 1;
}
setvbuf(stdout, NULL, _IOLBF, 0);
// if ((sd = socket(AF_INET, SOCK_PACKET, htons(ETH_P_ALL))) < 0)
if ((sd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0)
{
perror("Can't get socket");
fprintf(stderr, "You must run %s as root\n", progname);
exit(1);
}
/* SET PROMISC */
strcpy(oldifr.ifr_name, device);
if (ioctl(sd, SIOCGIFFLAGS, &oldifr) < 0)
{
close(sd);
perror("Can't get flags");
exit(2);
}
/* This should be rewritten to cooperate with other net tools */
ifr = oldifr;
ifr.ifr_flags |= IFF_PROMISC;
if (ioctl(sd, SIOCSIFFLAGS, &ifr) < 0)
{
close(sd);
perror("Can't set flags");
exit(3);
}
while (exit_request == 0)
{
/* This is the main data-gathering loop; keep it small
and fast */
sizeaddr = sizeof(saddr);
length = recvfrom(sd, buf, sizeof(buf), 0,
&saddr, &sizeaddr);
if (length < 0)
continue;
if (allframes) {
unsigned char* ptr = buf;
if (filter) {
if (memcmp(filter_node, buf, 6)&&memcmp(filter_node, buf+6, 6))
continue;
}
printf("raweth ");
while (length--) printf("%02X", *ptr++);
printf("\n");
} else {
handle_frame(buf, length, &saddr);
}
}
/* This should be rewritten to cooperate with other net tools */
if (ioctl(sd, SIOCSIFFLAGS, &oldifr) < 0)
{
close(sd);
perror("Can't set flags");
exit(4);
}
close(sd);
return 0;
}
void
handle_ipx(const char *frame, unsigned char *buf)
{
int i;
struct ipx_packet *h = (struct ipx_packet *) buf;
struct sockaddr_ipx s_addr;
struct sockaddr_ipx d_addr;
int length = ntohs(h->ipx_pktsize);
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;
if (filter != 0)
{
if ((memcmp(filter_node, s_addr.sipx_node,
sizeof(filter_node)) != 0)
&& (memcmp(filter_node, d_addr.sipx_node,
sizeof(filter_node)) != 0))
{
/* Not for us */
return;
}
}
printf("%s ", frame);
for (i = 0; i < length; i++)
{
printf("%2.2X", buf[i]);
}
printf("\n");
if (!isatty(STDOUT_FILENO))
{
fflush(stdout);
}
}
void
handle_other(unsigned char *buf, int length, struct sockaddr *saddr)
{
struct ethhdr *eth = (struct ethhdr *) buf;
unsigned char *p = &(buf[sizeof(struct ethhdr)]);
if (ntohs(eth->h_proto) < 1536)
{
/* This is a magic hack to spot IPX packets. Older
* Novell breaks the protocol design and runs IPX over
* 802.3 without an 802.2 LLC layer. We look for FFFF
* which isnt a used 802.2 SSAP/DSAP. This won't work
* for fault tolerant netware but does for the rest.
*/
if (*(unsigned short *) p == 0xffff)
{
handle_ipx("802.3", p);
return;
}
if ((*(unsigned short *) p == htons(0xe0e0))
&& (p[2] == 0x03))
{
handle_ipx("802.2", p + 3);
return;
}
if (memcmp(p, "\252\252\003\000\000\000\201\067", 8) == 0)
{
handle_ipx("snap", p + 8);
return;
}
}
}
void
handle_frame(unsigned char *buf, int length, struct sockaddr *saddr)
{
/* Ethernet packet type ID field */
unsigned short packet_type = ((struct ethhdr *) buf)->h_proto;
switch (htons(packet_type))
{
case ETH_P_IPX:
handle_ipx("EtherII", &(buf[sizeof(struct ethhdr)]));
break;
default:
handle_other(buf, length, saddr);
break;
}
}

1140
tools/ipxparse.c Normal file

File diff suppressed because it is too large Load Diff

133
tools/ipxutil.c Normal file
View File

@@ -0,0 +1,133 @@
/*
IPX support library - general functions
Copyright (C) 1994, 1995 Ales Dryak <e-mail: A.Dryak@sh.cvut.cz>
Copyright (C) 1996, Volker Lendecke <lendecke@namu01.gwdg.de>
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 <string.h>
#include <netinet/in.h>
#include "ipxutil.h"
void
ipx_fprint_node(FILE * file, IPXNode node)
{
fprintf(file, "%02X%02X%02X%02X%02X%02X",
(unsigned char) node[0],
(unsigned char) node[1],
(unsigned char) node[2],
(unsigned char) node[3],
(unsigned char) node[4],
(unsigned char) node[5]
);
}
void
ipx_fprint_network(FILE * file, IPXNet net)
{
fprintf(file, "%08lX", (unsigned long)net);
}
void
ipx_fprint_port(FILE * file, IPXPort port)
{
fprintf(file, "%04X", port);
}
void
ipx_fprint_saddr(FILE * file, struct sockaddr_ipx *sipx)
{
ipx_fprint_network(file, ntohl(sipx->sipx_network));
fprintf(file, ":");
ipx_fprint_node(file, sipx->sipx_node);
fprintf(file, ":");
ipx_fprint_port(file, ntohs(sipx->sipx_port));
}
void
ipx_print_node(IPXNode node)
{
ipx_fprint_node(stdout, node);
}
void
ipx_print_network(IPXNet net)
{
ipx_fprint_network(stdout, net);
}
void
ipx_print_port(IPXPort port)
{
ipx_fprint_port(stdout, port);
}
void
ipx_print_saddr(struct sockaddr_ipx *sipx)
{
ipx_fprint_saddr(stdout, sipx);
}
void
ipx_assign_node(IPXNode dest, IPXNode src)
{
memcpy(dest, src, sizeof(IPXNode));
}
int
ipx_node_equal(IPXNode n1, IPXNode n2)
{
return memcmp(n1, n2, sizeof(IPXNode)) == 0;
}
int
ipx_sscanf_node(char *buf, IPXNode node)
{
int i;
int n[6];
if ((i = sscanf(buf, "%2x%2x%2x%2x%2x%2x",
&(n[0]), &(n[1]), &(n[2]),
&(n[3]), &(n[4]), &(n[5]))) != 6)
{
return -1;
}
for (i = 0; i < 6; i++)
{
node[i] = n[i];
}
return 0;
}
int
ipx_sscanf_net(char *buf, IPXNet * target)
{
unsigned long net;
if (sscanf(buf, "%8lX", &net) == 1)
{
*target = net;
return 0;
}
return -1;
}
IPXNode ipx_this_node =
{0, 0, 0, 0, 0, 0};
IPXNode ipx_broadcast_node =
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
char ipx_err_string[IPX_MAX_ERROR + 1] = "no error detected";

65
tools/ipxutil.h Normal file
View File

@@ -0,0 +1,65 @@
/*
IPX support library
Copyright (C) 1994, 1995 Ales Dryak <e-mail: A.Dryak@sh.cvut.cz>
Copyright (C) 1996, Volker Lendecke <lendecke@namu01.gwdg.de>
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.
*/
#ifndef __IPXUTIL_H__
#define __IPXUTIL_H__
#include <stdio.h>
#include <ncp/kernel/ipx.h>
#define IPX_MAX_ERROR (255)
#define IPX_THIS_NET (0)
#define IPX_THIS_NODE (ipx_this_node)
#define IPX_BROADCAST (ipx_broadcast_node)
#define IPX_AUTO_PORT (0)
#define IPX_USER_PTYPE (0)
#define IPX_IS_INTERNAL (1)
typedef u_int8_t IPXNode[6];
typedef u_int32_t IPXNet;
typedef u_int16_t IPXPort;
typedef u_int16_t hop_t;
typedef u_int16_t tick_t;
void ipx_print_node(IPXNode node);
void ipx_print_network(IPXNet net);
void ipx_print_port(IPXPort port);
void ipx_print_saddr(struct sockaddr_ipx *sipx);
void ipx_fprint_node(FILE * file, IPXNode node);
void ipx_fprint_network(FILE * file, IPXNet net);
void ipx_fprint_port(FILE * file, IPXPort port);
void ipx_fprint_saddr(FILE * file, struct sockaddr_ipx *sipx);
int ipx_sscanf_node(char *buf, IPXNode node);
int ipx_sscanf_net(char *buf, IPXNet * target);
void ipx_assign_node(IPXNode dest, IPXNode src);
int ipx_node_equal(IPXNode n1, IPXNode n2);
extern IPXNode ipx_this_node;
extern IPXNode ipx_broadcast_node;
extern char ipx_err_string[IPX_MAX_ERROR + 1];
#endif