diff --git a/.downloads/ncpfs-0.9.tgz b/.downloads/ncpfs-0.9.tgz new file mode 100644 index 0000000..fd44950 Binary files /dev/null and b/.downloads/ncpfs-0.9.tgz differ diff --git a/Makefile b/Makefile index f567a11..b1017b9 100644 --- a/Makefile +++ b/Makefile @@ -6,13 +6,13 @@ KERNEL = 1.2 INCLUDES = -I/usr/src/linux/include -Ikernel BINDIR = ./bin +SUBDIRS = kernel-$(KERNEL)/src util ipx-0.75 CFLAGS = -Wall $(INCLUDES) CC = gcc all: kernel - make -C util - make -C kernel/src ncpfs.o + for i in $(SUBDIRS); do make -C $$i; done cp kernel/src/ncpfs.o bin kernel: @@ -20,7 +20,7 @@ kernel: ln -s kernel-$(KERNEL) kernel dep: - $(CPP) -M $(INCLUDES) *.c > .depend + for i in $(SUBDIRS); do make -C $$i dep; done clean: rm -f kernel @@ -28,7 +28,7 @@ clean: rm -f `find . -type f -name '*~' -print` rm -f `find . -type f -name '.depend' -print` rm -f `find . -type f -name '*.out' -print` - + for i in $(SUBDIRS); do make -C $$i clean; done realclean: clean rm -fr bin/* ncpfs.tgz diff --git a/README b/README index 9d9feec..814a0c5 100644 --- a/README +++ b/README @@ -1,14 +1,14 @@ -This is version 0.7 of ncpfs, a free NetWare client filesystem for +This is version 0.8 of ncpfs, a free NetWare client filesystem for Linux. This one currently works with Kernel 1.2.13. I do not know whether it works with any other kernel of the 1.2.x series, I only used it with 1.2.13. -Due to problems in the 1.3.x IPX kernel code, ncpfs-0.7 does NOT work -with any 1.3.x kernel up to 1.3.44, although there is a kernel-1.3 +Due to problems in the 1.3.x IPX kernel code, ncpfs-0.8 does NOT work +with any 1.3.x kernel up to 1.3.45, although there is a kernel-1.3 subdirectory. It compiles fine and seems to work, but any connection will block after a very short time. Please be patient. I'm sure this will be solved. If you follow the kernel development closely, you -might want to try ncpfs with a kernel later than 1.3.44, but I can not +might want to try ncpfs with a kernel later than 1.3.45, but I can not promise anything. To try it with 1.3, simply change the variable KERNEL in the Makefile from 1.2 to 1.3 and continue as usual. diff --git a/ipx-0.75/Makefile b/ipx-0.75/Makefile new file mode 100644 index 0000000..9670636 --- /dev/null +++ b/ipx-0.75/Makefile @@ -0,0 +1,30 @@ +CFLAGS = -O2 -Wall +BINDIR = ../bin +UTILS = $(BINDIR)/ipx_configure $(BINDIR)/ipx_interface \ + $(BINDIR)/ipx_internal_net $(BINDIR)/ipx_route + +all: $(UTILS) + +$(BINDIR)/ipx_configure: ipx_configure.o + $(CC) -o $(BINDIR)/ipx_configure ipx_configure.o + +$(BINDIR)/ipx_interface: ipx_interface.o + $(CC) -o $(BINDIR)/ipx_interface ipx_interface.o + +$(BINDIR)/ipx_internal_net: ipx_internal_net.o + $(CC) -o $(BINDIR)/ipx_internal_net ipx_internal_net.o + +$(BINDIR)/ipx_route: ipx_route.o + $(CC) -o $(BINDIR)/ipx_route ipx_route.o + + +clean: + rm -f $(UTILS) *.o rip sap ipxrcv ipxsend + +install: $(UTILS) + for i in $(UTILS); \ + do \ + install --strip $$i /sbin; \ + install $$i.8 /usr/man/man8; \ + done + diff --git a/ipx-0.75/README b/ipx-0.75/README new file mode 100644 index 0000000..dcc4e88 --- /dev/null +++ b/ipx-0.75/README @@ -0,0 +1,65 @@ +This file contains a very short introduction to the IPX implementation +on Linux. Feel free to forward comments (especially suggested additions) +to greg@caldera.com. + +The following are important definitions in understanding the descriptions +in this README file. + +IPX Interface - This is the item to which IPX sockets are bound. +An IPX interface corresponds to an IPX Network Number which corresponds +to a physical device and frame type. A sample IPX Interface would be: +Network Number: 0x00ABCDEF +Device: Eth0 +Frame Type: 802.2. +The particular interface is selected during binding by using the +Network Number (see sample code below). + +Primary Interface - The interface that is selected by default when +binding a socket. This is selected when binding by using +a network number of 0 (see sample code below). + +Internal Network - This is a special kind of IPX interface that does +not have a physical device or frame type. It is used to provide +a route-independent address for service providers. Internal network +numbers are optional; however, when one is present it is also the +Primary Interface. + +This tar file contains the following IPX utilities: + +ipx_interface.c +This program is used to create an IPX interface. + +ipx_internal_net.c +This program is used to create an IPX Internal Network number. + +ipx_route.c +This program creates an IPX route. + +ipx_configure.c +This program is used to read/write two configuration parameters: + AUTO INTERFACE CREATE - IPX should/shouldn't automatically create + an IPX interface when it discovers one that has not been + registered via ipx_interface above. + AUTO PRIMARY SELECT - IPX should/shouldn't automatically select + a primary interface when it one an interface exists and + none are designated as the primary. Manual designation + is performed via ipx_interface. + +By default, these are both turned off. + +The following are sample IPX programs: + +ipxrcv.c and ipxsend.c +ipxsend will send a single packet to an instance of ipxrcv running on the +same machine. It uses getsockname(2) to determine the address to which to +send the packet. +rip.c +rip passively monitors the rip traffic on the attached IPX network. +sap.c +sap passively monitors the sap traffic on the attached IPX network. + +There are three files in /proc/net that relate to IPX. +ipx_interface contains the list of IPX interfaces. +ipx_route contains the list of IPX routes. +ipx contains the list of IPX sockets in use. + diff --git a/util/ipx_configure.c b/ipx-0.75/ipx_configure.c similarity index 100% rename from util/ipx_configure.c rename to ipx-0.75/ipx_configure.c diff --git a/ipx-0.75/ipx_interface.c b/ipx-0.75/ipx_interface.c new file mode 100644 index 0000000..ec67751 --- /dev/null +++ b/ipx-0.75/ipx_interface.c @@ -0,0 +1,303 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct ifreq id; +static char *progname; + +void +usage(void) +{ + fprintf(stderr, "Usage: %s add [-p] device frame_type [net_number]\n\ +Usage: %s del device frame_type\n\ +Usage: %s check device frame_type\n", progname, progname, progname); + exit(-1); +} + +struct frame_type { + char *ft_name; + unsigned char ft_val; +} frame_types[] = { + {"802.2", IPX_FRAME_8022}, + {"802.3", IPX_FRAME_8023}, + {"SNAP", IPX_FRAME_SNAP}, + {"EtherII", IPX_FRAME_ETHERII} +}; + +#define NFTYPES (sizeof(frame_types)/sizeof(struct frame_type)) + +int +lookup_frame_type(char *frame) +{ + int j; + + for (j = 0; (j < NFTYPES) && + (strcasecmp(frame_types[j].ft_name, frame)); + j++) + ; + + if (j != NFTYPES) + return j; + + fprintf(stderr, "%s: Frame type must be", progname); + for (j = 0; j < NFTYPES; j++) { + fprintf(stderr, "%s%s", + (j == NFTYPES-1) ? " or " : " ", + frame_types[j].ft_name); + } + fprintf(stderr, ".\n"); + return -1; +} + +int +ipx_add_interface(int argc, char **argv) +{ + struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr; + int s; + int result; + unsigned long netnum; + char errmsg[80]; + int i, fti = 0; + char c; + + sipx->sipx_special = IPX_SPECIAL_NONE; + sipx->sipx_network = 0L; + sipx->sipx_type = IPX_FRAME_NONE; + while ((c = getopt(argc, argv, "p")) > 0) { + switch (c) { + case 'p': sipx->sipx_special = IPX_PRIMARY; break; + } + } + + if (((i = (argc - optind)) < 2) || (i > 3)) { + usage(); + } + + for (i = optind; i < argc; i++) { + switch (i-optind) { + case 0: /* Physical Device - Required */ + strcpy(id.ifr_name, argv[i]); + break; + case 1: /* Frame Type - Required */ + fti = lookup_frame_type(argv[i]); + if (fti < 0) + exit(-1); + sipx->sipx_type = frame_types[fti].ft_val; + break; + + case 2: /* Network Number - Optional */ + netnum = strtoul(argv[i], (char **)NULL, 16); + if (netnum == 0xffffffffL) { + fprintf(stderr, + "%s: Inappropriate network number %08lX\n", + progname, netnum); + exit(-1); + } + sipx->sipx_network = htonl(netnum); + break; + } + } + + s = socket(AF_IPX, SOCK_DGRAM, AF_IPX); + if (s < 0) { + sprintf(errmsg, "%s: socket", progname); + perror(errmsg); + exit(-1); + } + + i = 0; + sipx->sipx_family = AF_IPX; + sipx->sipx_action = IPX_CRTITF; + do { + result = ioctl(s, SIOCSIFADDR, &id); + i++; + } while ((i < 5) && (result < 0) && (errno == EAGAIN)); + + if (result == 0) exit(0); + + switch (errno) { + case EEXIST: + fprintf(stderr, "%s: Primary network already selected.\n", + progname); + break; + case EADDRINUSE: + fprintf(stderr, "%s: Network number (%08lX) already in use.\n", + progname, htonl(sipx->sipx_network)); + break; + case EPROTONOSUPPORT: + fprintf(stderr, "%s: Invalid frame type (%s).\n", + progname, frame_types[fti].ft_name); + break; + case ENODEV: + fprintf(stderr, "%s: No such device (%s).\n", progname, + id.ifr_name); + break; + case ENETDOWN: + fprintf(stderr, "%s: Requested device (%s) is down.\n", progname, + id.ifr_name); + break; + case EINVAL: + fprintf(stderr, "%s: Invalid device (%s).\n", progname, + id.ifr_name); + break; + case EAGAIN: + fprintf(stderr, + "%s: Insufficient memory to create interface.\n", + progname); + break; + default: + sprintf(errmsg, "%s: ioctl", progname); + perror(errmsg); + break; + } + exit(-1); +} + +int +ipx_del_interface(int argc, char **argv) +{ + struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr; + int s; + int result; + char errmsg[80]; + int fti; + + if (argc != 3) { + usage(); + } + + sipx->sipx_network = 0L; + strcpy(id.ifr_name, argv[1]); + fti = lookup_frame_type(argv[2]); + if (fti < 0) + exit(-1); + sipx->sipx_type = frame_types[fti].ft_val; + + s = socket(AF_IPX, SOCK_DGRAM, AF_IPX); + if (s < 0) { + sprintf(errmsg, "%s: socket", progname); + perror(errmsg); + exit(-1); + } + sipx->sipx_action = IPX_DLTITF; + sipx->sipx_family = AF_IPX; + result = ioctl(s, SIOCSIFADDR, &id); + if (result == 0) exit(0); + + switch (errno) { + case EPROTONOSUPPORT: + fprintf(stderr, "%s: Invalid frame type (%s).\n", + progname, frame_types[fti].ft_name); + break; + case ENODEV: + fprintf(stderr, "%s: No such device (%s).\n", progname, + id.ifr_name); + break; + case EINVAL: + fprintf(stderr, "%s: No such IPX interface %s %s.\n", progname, + id.ifr_name, frame_types[fti].ft_name); + break; + default: + sprintf(errmsg, "%s: ioctl", progname); + perror(errmsg); + break; + } + exit(-1); +} + +int +ipx_check_interface(int argc, char **argv) +{ + struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr; + int s; + int result; + char errmsg[80]; + int fti; + + if (argc != 3) { + usage(); + } + + sipx->sipx_network = 0L; + strcpy(id.ifr_name, argv[1]); + fti = lookup_frame_type(argv[2]); + if (fti < 0) + exit(-1); + sipx->sipx_type = frame_types[fti].ft_val; + + s = socket(AF_IPX, SOCK_DGRAM, AF_IPX); + if (s < 0) { + sprintf(errmsg, "%s: socket", progname); + perror(errmsg); + exit(-1); + } + sipx->sipx_family = AF_IPX; + result = ioctl(s, SIOCGIFADDR, &id); + if (result == 0) { + printf( + "IPX Address for (%s, %s) is %08lX:%02X%02X%02X%02X%02X%02X.\n", + argv[1], frame_types[fti].ft_name, + htonl(sipx->sipx_network), sipx->sipx_node[0], + sipx->sipx_node[1], sipx->sipx_node[2], + sipx->sipx_node[3], sipx->sipx_node[4], + sipx->sipx_node[5]); + exit(0); + } + + switch (errno) { + case EPROTONOSUPPORT: + fprintf(stderr, "%s: Invalid frame type (%s).\n", + progname, frame_types[fti].ft_name); + break; + case ENODEV: + fprintf(stderr, "%s: No such device (%s).\n", progname, + id.ifr_name); + break; + case EADDRNOTAVAIL: + fprintf(stderr, "%s: No such IPX interface %s %s.\n", progname, + id.ifr_name, frame_types[fti].ft_name); + break; + default: + sprintf(errmsg, "%s: ioctl", progname); + perror(errmsg); + break; + } + exit(-1); +} + +int +main(int argc, char **argv) +{ + int i; + + progname = argv[0]; + if (argc < 2) { + usage(); + exit(-1); + } + + if (strncasecmp(argv[1], "add", 3) == 0) { + for (i = 1; i < (argc-1); i++) + argv[i] = argv[i+1]; + ipx_add_interface(argc-1, argv); + } else if (strncasecmp(argv[1], "del", 3) == 0) { + for (i = 1; i < (argc-1); i++) + argv[i] = argv[i+1]; + ipx_del_interface(argc-1, argv); + } else if (strncasecmp(argv[1], "check", 5) == 0) { + for (i = 1; i < (argc-1); i++) + argv[i] = argv[i+1]; + ipx_check_interface(argc-1, argv); + } + usage(); + return 0; +} diff --git a/ipx-0.75/ipx_internal_net.c b/ipx-0.75/ipx_internal_net.c new file mode 100644 index 0000000..54cb234 --- /dev/null +++ b/ipx-0.75/ipx_internal_net.c @@ -0,0 +1,195 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct ifreq id; +static char *progname; + +void +usage(void) +{ + fprintf(stderr, "Usage: %s add net_number(hex) node(hex)\n\ +Usage: %s del\n", progname, progname); + exit(-1); +} + +int +map_char_to_val(char dig) +{ + char digit = tolower(dig); + if ((digit >= '0') && (digit <= '9')) { + return digit - '0'; + } else if ((digit >= 'a') && (digit <= 'f')) { + return (10 + (digit - 'a')); + } else { + return 0; + } +} + +int +ipx_add_internal_net(int argc, char **argv) +{ + struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr; + int s; + int result; + unsigned long netnum; + char errmsg[80]; + int nodelen; + char *node; + char tmpnode[13]; + unsigned char *tout; + char *tin; + int i; + + if (argc != 3) { + usage(); + } + + netnum = strtoul(argv[1], (char **)NULL, 16); + if ((netnum == 0L) || (netnum == 0xffffffffL)) { + fprintf(stderr, "%s: Inappropriate network number %08lX\n", + progname, netnum); + exit(-1); + } + + node = argv[2]; + nodelen = strlen(node); + if (nodelen > 12) { + fprintf(stderr, "%s: Node length is too long (> 12).\n", progname); + exit(-1); + } + + for (i = 0; (i < nodelen) && isxdigit(node[i]); i++) + ; + + if (i < nodelen) { + fprintf(stderr, "%s: Invalid value in node, must be hex digits.\n", + progname); + exit(-1); + } + + strcpy(tmpnode, "000000000000"); + memcpy(&(tmpnode[12-nodelen]), node, nodelen); + for (tin = tmpnode, tout = sipx->sipx_node; *tin != '\0'; tin += 2, tout++) { + *tout = (unsigned char) map_char_to_val(*tin); + *tout <<= 4; + *tout |= (unsigned char) map_char_to_val(*(tin+1)); + } + + if ((memcmp(sipx->sipx_node, "\0\0\0\0\0\0\0\0", IPX_NODE_LEN) == 0) || + (memcmp(sipx->sipx_node, "\377\377\377\377\377\377", IPX_NODE_LEN) == 0)){ + fprintf(stderr, "%s: Node is invalid.\n", progname); + exit(-1); + } + + sipx->sipx_network = htonl(netnum); + sipx->sipx_type = IPX_FRAME_NONE; + sipx->sipx_special = IPX_INTERNAL; + s = socket(AF_IPX, SOCK_DGRAM, AF_IPX); + if (s < 0) { + sprintf(errmsg, "%s: socket", progname); + perror(errmsg); + exit(-1); + } + + sipx->sipx_family = AF_IPX; + sipx->sipx_action = IPX_CRTITF; + i = 0; + do { + result = ioctl(s, SIOCSIFADDR, &id); + i++; + } while ((i < 5) && (result < 0) && (errno == EAGAIN)); + + if (result == 0) exit(0); + + switch (errno) { + case EEXIST: + fprintf(stderr, "%s: Primary network already selected.\n", + progname); + break; + case EADDRINUSE: + fprintf(stderr, "%s: Network number (%08lX) already in use.\n", + progname, htonl(sipx->sipx_network)); + break; + case EAGAIN: + fprintf(stderr, + "%s: Insufficient memory to create internal net.\n", + progname); + break; + default: + sprintf(errmsg, "%s: ioctl", progname); + perror(errmsg); + break; + } + exit(-1); +} + +int +ipx_del_internal_net(int argc, char **argv) +{ + struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr; + int s; + int result; + char errmsg[80]; + + if (argc != 1) { + usage(); + } + + sipx->sipx_network = 0L; + sipx->sipx_special = IPX_INTERNAL; + s = socket(AF_IPX, SOCK_DGRAM, AF_IPX); + if (s < 0) { + sprintf(errmsg, "%s: socket", progname); + perror(errmsg); + exit(-1); + } + sipx->sipx_family = AF_IPX; + sipx->sipx_action = IPX_DLTITF; + result = ioctl(s, SIOCSIFADDR, &id); + if (result == 0) exit(0); + + switch (errno) { + case ENOENT: + fprintf(stderr, "%s: No internal network configured.\n", progname); + break; + default: + sprintf(errmsg, "%s: ioctl", progname); + perror(errmsg); + break; + } + exit(-1); +} + +int +main(int argc, char **argv) +{ + int i; + + progname = argv[0]; + if (argc < 2) { + usage(); + exit(-1); + } + + if (strncasecmp(argv[1], "add", 3) == 0) { + for (i = 1; i < (argc-1); i++) + argv[i] = argv[i+1]; + ipx_add_internal_net(argc-1, argv); + } else if (strncasecmp(argv[1], "del", 3) == 0) { + for (i = 1; i < (argc-1); i++) + argv[i] = argv[i+1]; + ipx_del_internal_net(argc-1, argv); + } + usage(); + return 0; +} + diff --git a/ipx-0.75/ipx_route.c b/ipx-0.75/ipx_route.c new file mode 100644 index 0000000..1e991c0 --- /dev/null +++ b/ipx-0.75/ipx_route.c @@ -0,0 +1,215 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct rtentry rd; +static char *progname; + +int +map_char_to_val(char dig) +{ + char digit = tolower(dig); + if ((digit >= '0') && (digit <= '9')) { + return digit - '0'; + } else if ((digit >= 'a') && (digit <= 'f')) { + return (10 + (digit - 'a')); + } else { + return 0; + } +} + +void +usage(void) +{ + fprintf(stderr, + "Usage: %s add network(hex) router_network(hex) router_node(hex)\n\ +Usage: %s del network(hex)\n", progname, progname); + exit(-1); +} + +int +ipx_add_route(int argc, char **argv) +{ + /* Router */ + struct sockaddr_ipx *sr = (struct sockaddr_ipx *)&rd.rt_gateway; + /* Target */ + struct sockaddr_ipx *st = (struct sockaddr_ipx *)&rd.rt_dst; + int s; + int result; + int nodelen; + int i; + unsigned long netnum; + char errmsg[80]; + char *node; + char *tin; + char tmpnode[13]; + unsigned char *tout; + + if (argc != 4) + usage(); + + /* Network Number */ + netnum = strtoul(argv[1], (char **)NULL, 16); + if ((netnum == 0xffffffffL) || (netnum == 0L)) { + fprintf(stderr, "%s: Inappropriate network number %08lX\n", + progname, netnum); + exit(-1); + } + rd.rt_flags = RTF_GATEWAY; + st->sipx_network = htonl(netnum); + + /* Router Network Number */ + netnum = strtoul(argv[2], (char **)NULL, 16); + if ((netnum == 0xffffffffL) || (netnum == 0L)) { + fprintf(stderr, "%s: Inappropriate network number %08lX\n", + progname, netnum); + exit(-1); + } + sr->sipx_network = htonl(netnum); + + /* Router Node */ + node = argv[3]; + nodelen = strlen(node); + if (nodelen > 12) { + fprintf(stderr, "%s: Node length is too long (> 12).\n", + progname); + exit(-1); + } + + for (i = 0; (i < nodelen) && isxdigit(node[i]); i++) + ; + + if (i < nodelen) { + fprintf(stderr, "%s: Invalid value in node, must be hex digits.\n", + progname); + exit(-1); + } + + strcpy(tmpnode, "000000000000"); + memcpy(&(tmpnode[12-nodelen]), node, nodelen); + for (tin = tmpnode, tout = sr->sipx_node; *tin != '\0'; tin += 2, tout++) { + *tout = (unsigned char) map_char_to_val(*tin); + *tout <<= 4; + *tout |= (unsigned char) map_char_to_val(*(tin+1)); + } + + if ((memcmp(sr->sipx_node, "\0\0\0\0\0\0\0\0", IPX_NODE_LEN) == 0) || + (memcmp(sr->sipx_node, "\377\377\377\377\377\377", IPX_NODE_LEN) == 0)){ + fprintf(stderr, "%s: Node (%s) is invalid.\n", progname, tmpnode); + exit(-1); + } + + s = socket(AF_IPX, SOCK_DGRAM, AF_IPX); + if (s < 0) { + sprintf(errmsg, "%s: socket", progname); + perror(errmsg); + exit(-1); + } + + sr->sipx_family = st->sipx_family = AF_IPX; + i = 0; + do { + result = ioctl(s, SIOCADDRT, &rd); + i++; + } while ((i < 5) && (result < 0) && (errno == EAGAIN)); + + if (result == 0) exit(0); + + switch (errno) { + case ENETUNREACH: + fprintf(stderr, "%s: Router network (%08lX) not reachable.\n", + progname, htonl(sr->sipx_network)); + break; + default: + sprintf(errmsg, "%s: ioctl", progname); + perror(errmsg); + break; + } + exit(-1); +} + +int +ipx_del_route(int argc, char **argv) +{ + /* Router */ + struct sockaddr_ipx *sr = (struct sockaddr_ipx *)&rd.rt_gateway; + /* Target */ + struct sockaddr_ipx *st = (struct sockaddr_ipx *)&rd.rt_dst; + int s; + int result; + unsigned long netnum; + char errmsg[80]; + + if (argc != 2) { + usage(); + } + + rd.rt_flags = RTF_GATEWAY; + /* Network Number */ + netnum = strtoul(argv[1], (char **)NULL, 16); + if ((netnum == 0xffffffffL) || (netnum == 0L)) { + fprintf(stderr, "%s: Inappropriate network number %08lX.\n", + progname, netnum); + exit(-1); + } + st->sipx_network = htonl(netnum); + + st->sipx_family = sr->sipx_family = AF_IPX; + s = socket(AF_IPX, SOCK_DGRAM, AF_IPX); + if (s < 0) { + sprintf(errmsg, "%s: socket", progname); + perror(errmsg); + exit(-1); + } + result = ioctl(s, SIOCDELRT, &rd); + if (result == 0) exit(0); + + switch (errno) { + case ENOENT: + fprintf(stderr, "%s: Route not found for network %08lX.\n", + progname, netnum); + break; + case EPERM: + fprintf(stderr, "%s: Network %08lX is directly connected.\n", + progname, netnum); + break; + default: + sprintf(errmsg, "%s: ioctl", progname); + perror(errmsg); + break; + } + exit(-1); +} + +int +main(int argc, char **argv) +{ + int i; + + progname = argv[0]; + if (argc < 2) { + usage(); + exit(-1); + } + + if (strncasecmp(argv[1], "add", 3) == 0) { + for (i = 1; i < (argc-1); i++) + argv[i] = argv[i+1]; + ipx_add_route(argc-1, argv); + } else if (strncasecmp(argv[1], "del", 3) == 0) { + for (i = 1; i < (argc-1); i++) + argv[i] = argv[i+1]; + ipx_del_route(argc-1, argv); + } + usage(); + return 0; +} diff --git a/ipx-0.75/ipxrcv.c b/ipx-0.75/ipxrcv.c new file mode 100644 index 0000000..2a71e64 --- /dev/null +++ b/ipx-0.75/ipxrcv.c @@ -0,0 +1,52 @@ +#include +#include +#include +#include +#include +#include + +int +main(int argc, char **argv) +{ + struct sockaddr_ipx sipx; + int s; + int result; + char msg[100]; + int len; + + s = socket(AF_IPX, SOCK_DGRAM, AF_IPX); + if (s < 0) { + perror("IPX: socket: "); + exit(-1); + } + sipx.sipx_family = AF_IPX; + sipx.sipx_network = 0; + sipx.sipx_port = htons(0x5000); + sipx.sipx_type = 17; + len = sizeof(sipx); + result = bind(s, (struct sockaddr *)&sipx, sizeof(sipx)); + if (result < 0) { + perror("IPX: bind: "); + exit(-1); + } + + msg[0] = '\0'; + result = recvfrom(s, msg, sizeof(msg), 0, (struct sockaddr *)&sipx, + &len); + if (result < 0) { + perror("IPX: recvfrom: "); + } + + printf("From %08lX:%02X%02X%02X%02X%02X%02X:%04X\n", + htonl(sipx.sipx_network), + sipx.sipx_node[0], sipx.sipx_node[1], + sipx.sipx_node[2], sipx.sipx_node[3], + sipx.sipx_node[4], sipx.sipx_node[5], + htons(sipx.sipx_port)); + printf("\tGot \"%s\"\n", msg); + return 0; +} + + + + diff --git a/ipx-0.75/ipxsend.c b/ipx-0.75/ipxsend.c new file mode 100644 index 0000000..f999fee --- /dev/null +++ b/ipx-0.75/ipxsend.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include +#include + +int +main(int argc, char **argv) +{ + struct sockaddr_ipx sipx; + int s; + int result; + char msg[100] = "Hi Mom"; + int len = sizeof(sipx); + + s = socket(AF_IPX, SOCK_DGRAM, AF_IPX); + if (s < 0) { + perror("IPX: socket: "); + exit(-1); + } + sipx.sipx_family = AF_IPX; + sipx.sipx_network = 0; + sipx.sipx_port = 0; + sipx.sipx_type = 17; + + result = bind(s, (struct sockaddr *)&sipx, sizeof(sipx)); + if (result < 0) { + perror("IPX: bind: "); + exit(-1); + } + + result = getsockname(s, (struct sockaddr *)&sipx, &len); + sipx.sipx_port = htons(0x5000); + result = sendto(s, msg, sizeof(msg), 0, (struct sockaddr *)&sipx, + sizeof(sipx)); + if (result < 0) { + perror("IPX: send: "); + exit(-1); + } + return 0; +} + + + + diff --git a/ipx-0.75/rip.c b/ipx-0.75/rip.c new file mode 100644 index 0000000..762df7d --- /dev/null +++ b/ipx-0.75/rip.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include +#include + +struct rip_data { + unsigned long rip_net; + unsigned short rip_hops __attribute__ ((packed)); + unsigned short rip_ticks __attribute__ ((packed)); +}; + +int +main(int argc, char **argv) +{ + struct sockaddr_ipx sipx; + int result; + int s; + char msg[1024]; + int len; + char *bptr; + struct rip_data *rp; + + s = socket(AF_IPX, SOCK_DGRAM, AF_IPX); + if (s < 0) { + perror("IPX: socket: "); + exit(-1); + } + sipx.sipx_family = AF_IPX; + sipx.sipx_network = 0; + sipx.sipx_port = htons(0x453); + sipx.sipx_type = 17; + result = bind(s, (struct sockaddr *)&sipx, sizeof(sipx)); + if (result < 0) { + perror("IPX: bind: "); + exit(-1); + } + + while (1) { + len = sizeof(sipx); + result = recvfrom(s, msg, sizeof(msg), 0, + (struct sockaddr *)&sipx, &len); + if (result < 0) { + perror("IPX: recvfrom"); + exit(-1); + } + bptr = msg; + result -= 2; + printf("RIP packet from: %08lX:%02X%02X%02X%02X%02X%02X\n", + htonl(sipx.sipx_network), + sipx.sipx_node[0], sipx.sipx_node[1], + sipx.sipx_node[2], sipx.sipx_node[3], + sipx.sipx_node[4], sipx.sipx_node[5]); + bptr += 2; + rp = (struct rip_data *) bptr; + while (result >= sizeof(struct rip_data)) { + printf("\tNET: %08lX HOPS: %d\n", ntohl(rp->rip_net), + ntohs(rp->rip_hops)); + result -= sizeof(struct rip_data); + rp++; + } + } +} + + + + diff --git a/ipx-0.75/sap.c b/ipx-0.75/sap.c new file mode 100644 index 0000000..594e52d --- /dev/null +++ b/ipx-0.75/sap.c @@ -0,0 +1,96 @@ +#include +#include +#include +#include +#include +#include + + +struct sap_data { + unsigned short sap_type __attribute__ ((packed)); + char sap_name[48] __attribute__ ((packed)); + unsigned long sap_net __attribute__ ((packed)); + unsigned char sap_node[6] __attribute__ ((packed)); + unsigned short sap_sock __attribute__ ((packed)); + unsigned short sap_hops __attribute__ ((packed)); +}; + +int +main(int argc, char **argv) +{ + int s; + int result; + struct sockaddr_ipx sipx; + char msg[1024]; + long val = 0; + int len; + char *bptr; + struct sap_data *sp; + + s = socket(AF_IPX, SOCK_DGRAM, AF_IPX); + if (s < 0) { + perror("IPX: socket: "); + exit(-1); + } + + result = setsockopt(s, SOL_SOCKET, SO_DEBUG, &val, 4); + if (result < 0) { + perror("IPX: setsockopt: "); + exit(-1); + } + + sipx.sipx_family = PF_IPX; + sipx.sipx_network = 0L; + sipx.sipx_port = htons(0x452); + sipx.sipx_type = 17; + + result = bind(s, (struct sockaddr *)&sipx, sizeof(sipx)); + if (result < 0) { + perror("IPX: bind: "); + exit(-1); + } + + while (1) { + len = 1024; + result = recvfrom(s, msg, sizeof(msg), 0, + (struct sockaddr *)&sipx, &len); + if (result < 0) { + perror("IPX: recvfrom: "); + exit(-1); + } + bptr = msg; + result -= 2; + printf("SAP: OP is %x %x\n", bptr[0], bptr[1]); + printf("Length is %d\n", result); + if (bptr[1] != 2) + continue; + + bptr += 2; + sp = (struct sap_data *) bptr; + while (result >= sizeof(struct sap_data)) { + int i; + + sp->sap_name[32] = '\0'; + for (i = 31; (i > 0) && (sp->sap_name[i] == '_'); i--); + i++; + sp->sap_name[i] = '\0'; + printf("NAME: %s TYPE: %x HOPS: %x\n", sp->sap_name, + ntohs(sp->sap_type), ntohs(sp->sap_hops)); + printf("%lx:%x %x %x %x %x %x: %x\n", + ntohl(sp->sap_net), + sp->sap_node[0], + sp->sap_node[1], + sp->sap_node[2], + sp->sap_node[3], + sp->sap_node[4], + sp->sap_node[5], + ntohs(sp->sap_sock)); + result -= sizeof(struct sap_data); + sp++; + } + } +} + + + + diff --git a/kernel-1.2/linux/ncp.h b/kernel-1.2/linux/ncp.h index 83ffefd..895c5ae 100644 --- a/kernel-1.2/linux/ncp.h +++ b/kernel-1.2/linux/ncp.h @@ -9,6 +9,7 @@ #define _LINUX_NCP_H #include +#include #define NCP_PTYPE (0x11) #define NCP_PORT (0x0451) @@ -51,6 +52,9 @@ struct ncp_bindery_object { __u32 object_id; __u16 object_type; __u8 object_name[NCP_BINDERY_NAME_LEN]; + __u8 object_flags; + __u8 object_security; + __u8 object_has_prop; }; struct nw_property { @@ -59,6 +63,11 @@ struct nw_property { __u8 property_flag; }; +struct prop_net_address { + __u32 network __attribute__ ((packed)); + __u8 node[IPX_NODE_LEN] __attribute__ ((packed)); + __u16 port __attribute__ ((packed)); +}; #define NCP_VOLNAME_LEN (16) #define NCP_NUMBER_OF_VOLUMES (64) @@ -263,16 +272,23 @@ struct queue_job { /* ClientRecordArea for print jobs */ +#define KEEP_ON 0x0400 +#define NO_FORM_FEED 0x0800 +#define NOTIFICATION 0x1000 +#define DELETE_FILE 0x2000 +#define EXPAND_TABS 0x4000 +#define PRINT_BANNER 0x8000 + struct print_job_record { __u8 Version __attribute__ ((packed)); - __u16 TabSize __attribute__ ((packed)); + __u8 TabSize __attribute__ ((packed)); __u16 Copies __attribute__ ((packed)); - __u8 CtrlFlags __attribute__ ((packed)); + __u16 CtrlFlags __attribute__ ((packed)); __u16 Lines __attribute__ ((packed)); __u16 Rows __attribute__ ((packed)); char FormName[16] __attribute__ ((packed)); __u8 Reserved[6] __attribute__ ((packed)); - char Banner[13] __attribute__ ((packed)); + char BannerName[13] __attribute__ ((packed)); char FnameBanner[13] __attribute__ ((packed)); char FnameHeader[14] __attribute__ ((packed)); char Path[80] __attribute__ ((packed)); diff --git a/kernel-1.2/src/Makefile b/kernel-1.2/src/Makefile index 7477eb1..d52c0f1 100644 --- a/kernel-1.2/src/Makefile +++ b/kernel-1.2/src/Makefile @@ -20,14 +20,14 @@ ARCH = i386 .s.o: $(AS) -o $*.o $< -OBJS= dir.o inode.o file.o sock.o ioctl.o ncplib.o +OBJS= dir.o inode.o file.o sock.o ioctl.o ncplib_kernel.o all: ncpfs.o ncpfs.o: $(OBJS) $(LD) -r -o ncpfs.o $(OBJS) -ncplib.o: ncplib.c ncplib.h +ncplib_kernel.o: ncplib_kernel.c ncplib_kernel.h $(CC) $(CFLAGS) -finline-functions -c $< dep: diff --git a/kernel-1.2/src/dir.c b/kernel-1.2/src/dir.c index 070afe0..eca38ba 100644 --- a/kernel-1.2/src/dir.c +++ b/kernel-1.2/src/dir.c @@ -23,7 +23,7 @@ #include #include #include -#include "ncplib.h" +#include "ncplib_kernel.h" struct ncp_dirent { struct nw_info_struct i; diff --git a/kernel-1.2/src/file.c b/kernel-1.2/src/file.c index 0ad8185..c2f0b95 100644 --- a/kernel-1.2/src/file.c +++ b/kernel-1.2/src/file.c @@ -26,7 +26,7 @@ #include #include #include -#include "ncplib.h" +#include "ncplib_kernel.h" #include static int diff --git a/kernel-1.2/src/inode.c b/kernel-1.2/src/inode.c index 780aa08..7bc5459 100644 --- a/kernel-1.2/src/inode.c +++ b/kernel-1.2/src/inode.c @@ -27,7 +27,7 @@ #include #include #include -#include "ncplib.h" +#include "ncplib_kernel.h" extern int close_fp(struct file *filp); diff --git a/kernel-1.2/src/ncplib.c b/kernel-1.2/src/ncplib_kernel.c similarity index 99% rename from kernel-1.2/src/ncplib.c rename to kernel-1.2/src/ncplib_kernel.c index f751233..a614c3b 100644 --- a/kernel-1.2/src/ncplib.c +++ b/kernel-1.2/src/ncplib_kernel.c @@ -9,7 +9,7 @@ -#include "ncplib.h" +#include "ncplib_kernel.h" typedef __u8 byte; typedef __u16 word; diff --git a/kernel-1.2/src/ncplib.h b/kernel-1.2/src/ncplib_kernel.h similarity index 100% rename from kernel-1.2/src/ncplib.h rename to kernel-1.2/src/ncplib_kernel.h diff --git a/kernel-1.3/linux/ncp.h b/kernel-1.3/linux/ncp.h index 6a9627d..df1772e 100644 --- a/kernel-1.3/linux/ncp.h +++ b/kernel-1.3/linux/ncp.h @@ -11,6 +11,7 @@ #error "Please use kernel 1.2.13" #include +#include #define NCP_PTYPE (0x11) #define NCP_PORT (0x0451) @@ -53,6 +54,9 @@ struct ncp_bindery_object { __u32 object_id; __u16 object_type; __u8 object_name[NCP_BINDERY_NAME_LEN]; + __u8 object_flags; + __u8 object_security; + __u8 object_has_prop; }; struct nw_property { @@ -61,6 +65,11 @@ struct nw_property { __u8 property_flag; }; +struct prop_net_address { + __u32 network __attribute__ ((packed)); + __u8 node[IPX_NODE_LEN] __attribute__ ((packed)); + __u16 port __attribute__ ((packed)); +}; #define NCP_VOLNAME_LEN (16) #define NCP_NUMBER_OF_VOLUMES (64) @@ -265,16 +274,23 @@ struct queue_job { /* ClientRecordArea for print jobs */ +#define KEEP_ON 0x0400 +#define NO_FORM_FEED 0x0800 +#define NOTIFICATION 0x1000 +#define DELETE_FILE 0x2000 +#define EXPAND_TABS 0x4000 +#define PRINT_BANNER 0x8000 + struct print_job_record { __u8 Version __attribute__ ((packed)); - __u16 TabSize __attribute__ ((packed)); + __u8 TabSize __attribute__ ((packed)); __u16 Copies __attribute__ ((packed)); - __u8 CtrlFlags __attribute__ ((packed)); + __u16 CtrlFlags __attribute__ ((packed)); __u16 Lines __attribute__ ((packed)); __u16 Rows __attribute__ ((packed)); char FormName[16] __attribute__ ((packed)); __u8 Reserved[6] __attribute__ ((packed)); - char Banner[13] __attribute__ ((packed)); + char BannerName[13] __attribute__ ((packed)); char FnameBanner[13] __attribute__ ((packed)); char FnameHeader[14] __attribute__ ((packed)); char Path[80] __attribute__ ((packed)); diff --git a/kernel-1.3/src/Makefile b/kernel-1.3/src/Makefile index 7477eb1..d52c0f1 100644 --- a/kernel-1.3/src/Makefile +++ b/kernel-1.3/src/Makefile @@ -20,14 +20,14 @@ ARCH = i386 .s.o: $(AS) -o $*.o $< -OBJS= dir.o inode.o file.o sock.o ioctl.o ncplib.o +OBJS= dir.o inode.o file.o sock.o ioctl.o ncplib_kernel.o all: ncpfs.o ncpfs.o: $(OBJS) $(LD) -r -o ncpfs.o $(OBJS) -ncplib.o: ncplib.c ncplib.h +ncplib_kernel.o: ncplib_kernel.c ncplib_kernel.h $(CC) $(CFLAGS) -finline-functions -c $< dep: diff --git a/kernel-1.3/src/dir.c b/kernel-1.3/src/dir.c index 4f1f9b2..c419466 100644 --- a/kernel-1.3/src/dir.c +++ b/kernel-1.3/src/dir.c @@ -14,7 +14,7 @@ #include #include #include -#include "ncplib.h" +#include "ncplib_kernel.h" struct ncp_dirent { struct nw_info_struct i; diff --git a/kernel-1.3/src/file.c b/kernel-1.3/src/file.c index 6d40afc..fb125f8 100644 --- a/kernel-1.3/src/file.c +++ b/kernel-1.3/src/file.c @@ -15,7 +15,7 @@ #include #include #include -#include "ncplib.h" +#include "ncplib_kernel.h" #include static int diff --git a/kernel-1.3/src/inode.c b/kernel-1.3/src/inode.c index 517690f..1254622 100644 --- a/kernel-1.3/src/inode.c +++ b/kernel-1.3/src/inode.c @@ -20,7 +20,7 @@ #include #include #include -#include "ncplib.h" +#include "ncplib_kernel.h" extern int close_fp(struct file *filp); @@ -142,7 +142,7 @@ ncp_put_inode(struct inode *inode) printk("ncp_put_inode: could not close\n"); } } - + DDPRINTK("ncp_put_inode: put %s\n", finfo->i.entryName); diff --git a/kernel-1.3/src/ncplib.c b/kernel-1.3/src/ncplib_kernel.c similarity index 99% rename from kernel-1.3/src/ncplib.c rename to kernel-1.3/src/ncplib_kernel.c index 7a14317..7947199 100644 --- a/kernel-1.3/src/ncplib.c +++ b/kernel-1.3/src/ncplib_kernel.c @@ -1,4 +1,4 @@ -#include "ncplib.h" +#include "ncplib_kernel.h" typedef __u8 byte; typedef __u16 word; diff --git a/kernel-1.3/src/ncplib.h b/kernel-1.3/src/ncplib_kernel.h similarity index 100% rename from kernel-1.3/src/ncplib.h rename to kernel-1.3/src/ncplib_kernel.h diff --git a/man/ipx_interface.8 b/man/ipx_interface.8 new file mode 100644 index 0000000..55eae22 --- /dev/null +++ b/man/ipx_interface.8 @@ -0,0 +1,61 @@ +.TH IPX_INTERFACE 8 "IPX Utilities" "Caldera, Inc." +.SH NAME +ipx_interface \- add, delete, or display an IPX interface +.SH SYNOPSIS +.B ipx_interface +add [-p] device frame_type [network number] +.LP +.B ipx_interface +del device frame_type +.LP +.B ipx_interface +check device frame_type +.LP +.B ipx_interface +help +.SH DESCRIPTION +.B ipx_interface +adds, deletes, or displays IPX interfaces depending on the option selected. +.P +An IPX interface is the item to which IPX sockets are bound. +An IPX interface corresponds to an IPX Network Number which corresponds +to a physical device and frame type. A sample IPX Interface would be: +.LP +Network Number: 0x00ABCDEF +.LP +Device: Eth0 +.LP +Frame Type: 802.2. +.P +There is a special IPX interface per host known as the +.B PRIMARY +or default interface. +.SS OPTIONS +.TP +.I add +This option is used to create an IPX interface. If the +.B -p +flag is used, the interface is made +.B +PRIMARY. +The network number can be optionally assigned. If it is not assigned, it +is set to 0 which indicates it should be detected from the traffic on the +network. +.TP +.I del +This option is used to delete an IPX interface. +.TP +.I check +This option is used to display the device, frame type, and network number +of an IPX interface. +.TP +.I help +This option displays information about the utility. +.SH FILES +.I /proc/net/ipx_interface /proc/net/ipx_route +.SH BUGS +This functionality really belongs in +.B +ifconfig(8). +.SH AUTHOR +Greg Page diff --git a/man/ipx_internal_net.8 b/man/ipx_internal_net.8 new file mode 100644 index 0000000..fbe21ef --- /dev/null +++ b/man/ipx_internal_net.8 @@ -0,0 +1,32 @@ +.TH IPX_INTERNAL_NET 8 "IPX Utilities" "Caldera, Inc." +.SH NAME +ipx_internal_net \- add or delete the IPX internal network +.SH SYNOPSIS +.B ipx_internal_net +add network_number node_number +.LP +.B ipx_internal_net +del +.SH DESCRIPTION +.B ipx_internal_net +adds or deletes the IPX internal network. +An IPX internal network is a special kind of IPX interface that does +not have a physical device or frame type. It is used to provide +a route-independent address for service providers. Internal networks +are optional; however, when one is present it is also the +Primary Interface. There can only be one internal network per host. +.SS OPTIONS +.TP +.I add +This option is used to create the IPX internal network. +.TP +.I del +This option is used to delete the IPX internal network. +.SH FILES +.I /proc/net/ipx_interface /proc/net/ipx_route +.SH BUGS +This functionality really belongs in +.B +ifconfig(8). +.SH AUTHOR +Greg Page diff --git a/man/ipx_route.8 b/man/ipx_route.8 new file mode 100644 index 0000000..2f8eb3e --- /dev/null +++ b/man/ipx_route.8 @@ -0,0 +1,24 @@ +.TH IPX_ROUTE 8 "IPX Utilities" "Caldera, Inc." +.SH NAME +ipx_route \- add or delete IPX route +.SH SYNOPSIS +.B ipx_route +add target_network router_network router_node +.LP +.B ipx_route +del target_network +.SH DESCRIPTION +.B ipx_route +adds or deletes an IPX route. +The kernel IPX stores only one route per target network at a time. +.SS OPTIONS +.TP +.I add +This option is used to set up the route to a target network. +.TP +.I del +This option is used to delete the route to a target network. +.SH FILES +.I /proc/net/ipx_interface /proc/net/ipx_route +.SH AUTHOR +Greg Page diff --git a/man/ncpmount.8 b/man/ncpmount.8 index a168c3c..53e9b21 100644 --- a/man/ncpmount.8 +++ b/man/ncpmount.8 @@ -1,4 +1,4 @@ -.TH NCPMOUNT 8 25/11/1995 ncpmount ncpmount +.TH NCPMOUNT 8 11/25/1995 ncpmount ncpmount .SH NAME ncpmount \- mount program for ncpfs .SH SYNOPSIS diff --git a/man/ncpumount.8 b/man/ncpumount.8 index 6724407..633ecb6 100644 --- a/man/ncpumount.8 +++ b/man/ncpumount.8 @@ -1,4 +1,4 @@ -.TH NCPUMOUNT 8 25/11/1995 ncpumount ncpumount +.TH NCPUMOUNT 8 11/25/1995 ncpumount ncpumount .SH NAME ncpumount \- umount for normal users .SH SYNOPSIS diff --git a/man/slist.1 b/man/slist.1 new file mode 100644 index 0000000..539b148 --- /dev/null +++ b/man/slist.1 @@ -0,0 +1,44 @@ +.TH SLIST 1 12/02/1995 slist slist +.SH NAME +slist \- list all know NetWare file servers +.SH SYNOPSIS +.B slist +[pattern] + +.SH DESCRIPTION +With +.B slist +you can list all NetWare file servers that are known in your IPX network. +.B slist +is modeled after the well-know DOS utility. As an option, you can give +a wildcard pattern to slist. This can be convienient if you want to +know whether a specific server is reachable, of if your IPX network +contains a lot of servers. + +The pattern is converted to upper case, because NetWare stores only upper-case name. So you can find out whether you can access FS311 by typing + +.RS 3 +slist fs311 +.RE + +Please note that the decorative header is +.I not +printed if slist prints to a pipe. So you can count the number of file +servers simply by typing + +.RS 3 +slist | wc -l +.RE + +.SH BUGS +You might need superuser privileges to run slist. This sounds paradox, +but if your IPX routing table is not administered by an IPX routing +daemon, slist needs to add a route to the internal network of the +server that's nearest to you. For ncpmount, this is no problem, as it +has to be suid root anyway. So you could make slist setuid root. This +should be safe, because slist does not do much. The second option is +to run an IPX routing daemon, which automatically adjusts your routing +tables. + +.SH AUTHOR +Volker Lendecke diff --git a/ncpfs-0.8.lsm b/ncpfs-0.9.lsm similarity index 73% rename from ncpfs-0.8.lsm rename to ncpfs-0.9.lsm index add35e5..c9029bf 100644 --- a/ncpfs-0.8.lsm +++ b/ncpfs-0.9.lsm @@ -1,14 +1,14 @@ Begin3 Title: ncpfs -Version: 0.8 -Entered-date: 28. November 1995 +Version: 0.9 +Entered-date: 02. December 1995 Description: With ncpfs you can mount volumes of your novell server under Linux. Keywords: filesystem kernel ncp novell netware Author: lendecke@namu01.gwdg.de (Volker Lendecke) Maintained-by: lendecke@namu01.gwdg.de (Volker Lendecke) Primary-site: linux01.gwdg.de:/pub/ncpfs - ~80k ncpfs-0.8.tgz - ~ 1k ncpfs-0.8.lsm + ~81k ncpfs-0.9.tgz + ~ 1k ncpfs-0.9.lsm Copying-policy: GPL End diff --git a/util/Makefile b/util/Makefile index 7fd9f60..ec9d9e2 100644 --- a/util/Makefile +++ b/util/Makefile @@ -4,30 +4,24 @@ INCLUDES = -I/usr/src/linux/include -I../kernel BINDIR = ../bin -UTILS = ncpmount ncpumount ncptest ipx_configure +UTILS = $(BINDIR)/ncpmount $(BINDIR)/ncpumount $(BINDIR)/slist ncptest CFLAGS = -Wall $(INCLUDES) -O2 CC = gcc all: $(UTILS) -ncpmount: ncpmount.o ncplib_user.o nwcrypt.o - $(CC) -o ncpmount ncpmount.o ncplib_user.o nwcrypt.o - cp ncpmount $(BINDIR) +$(BINDIR)/ncpmount: ncpmount.o ncplib.o + $(CC) -o $(BINDIR)/ncpmount ncpmount.o ncplib.o -ncpumount: ncpumount.o ncplib_user.o nwcrypt.o - $(CC) -o ncpumount ncpumount.o ncplib_user.o nwcrypt.o - cp ncpumount $(BINDIR) +$(BINDIR)/ncpumount: ncpumount.o ncplib.o + $(CC) -o $(BINDIR)/ncpumount ncpumount.o ncplib.o -ipx_configure: ipx_configure.c - $(CC) $(CFLAGS) ipx_configure.c -o ipx_configure - cp ipx_configure $(BINDIR) +$(BINDIR)/slist: slist.o ncplib.o + $(CC) -o $(BINDIR)/slist slist.o ncplib.o -ncptest: ncptest.o ncplib_user.o nwcrypt.o - $(CC) -o ncptest ncptest.o ncplib_user.o nwcrypt.o - -nwcrypt.o: nwcrypt.c - $(CC) -c -O3 -Wall nwcrypt.c +ncptest: ncptest.o ncplib.o + $(CC) -o ncptest ncptest.o ncplib.o dep: $(CPP) -M $(INCLUDES) *.c > .depend diff --git a/util/ipx.tar b/util/ipx.tar deleted file mode 100644 index f4b1ecc..0000000 Binary files a/util/ipx.tar and /dev/null differ diff --git a/util/ipxutil.h b/util/ipxutil.h deleted file mode 100644 index 9b6e1e2..0000000 --- a/util/ipxutil.h +++ /dev/null @@ -1,76 +0,0 @@ - -/* - - IPX support library - - Copyright (C) 1994, 1995 Ales Dryak - - 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 -#include - -#define IPX_RIP_PTYPE (0x01) -#define IPX_SAP_PTYPE (0x04) -#define IPX_SAP_PORT (0x0452) -#define IPX_RIP_PORT (0x0453) - -#define IPX_SAP_GENERAL_QUERY (0x0001) -#define IPX_SAP_GENERAL_RESPONSE (0x0002) -#define IPX_SAP_NEAREST_QUERY (0x0003) -#define IPX_SAP_NEAREST_RESPONSE (0x0004) - -#define IPX_SAP_FILE_SERVER (0x0004) - -#define IPX_RIP_REQUEST (0x1) -#define IPX_RIP_RESPONSE (0x2) - -struct ipx_rip_packet { - __u16 operation __attribute__ ((packed)); - struct ipx_rt_def { - __u32 network __attribute__ ((packed)); - __u16 hops __attribute__ ((packed)); - __u16 ticks __attribute__ ((packed)); - } rt[1] __attribute__ ((packed)); -}; - -#define IPX_BROADCAST_NODE "\xff\xff\xff\xff\xff\xff" -#define IPX_THIS_NODE "\0\0\0\0\0\0" - -#ifndef IPX_NODE_LEN -#define IPX_NODE_LEN (6) -#endif - -typedef unsigned long IPXNet; -typedef unsigned short IPXPort; -typedef unsigned char IPXNode[IPX_NODE_LEN]; - - -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); - -static __inline__ void -ipx_assign_node(IPXNode dest, IPXNode src) { - memcpy(dest, src, IPX_NODE_LEN); -} - -#endif diff --git a/util/ncplib_user.c b/util/ncplib.c similarity index 79% rename from util/ncplib_user.c rename to util/ncplib.c index 4f08c16..aaa6c28 100644 --- a/util/ncplib_user.c +++ b/util/ncplib.c @@ -1,5 +1,4 @@ -#include "ncplib_user.h" -#include "nwcrypt.h" +#include "ncplib.h" typedef __u8 byte; typedef __u16 word; @@ -17,7 +16,93 @@ extern pid_t wait(int *); #include #include #include -#include "ipxutil.h" +#include + +/* I know it's terrible to include a .c file here, but I want to keep + the file nwcrypt.c intact and separate for legal reasons */ +#include "nwcrypt.c" + +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",ntohl(net)); +} + +void +ipx_fprint_port(FILE* file,IPXPort port) +{ + fprintf(file,"%04X",ntohs(port)); +} + +void +ipx_fprint_saddr(FILE* file,struct sockaddr_ipx* sipx) +{ + ipx_fprint_network(file,sipx->sipx_network); + fprintf(file,":"); + ipx_fprint_node(file,sipx->sipx_node); + fprintf(file,":"); + ipx_fprint_port(file,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); +} + +int +ipx_sscanf_node(char *buf, unsigned char node[6]) +{ + 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 i; + } + + for (i=0; i<6; i++) { + node[i] = n[i]; + } + return 6; +} + +void +ipx_assign_node(IPXNode dest, IPXNode src) { + memcpy(dest, src, IPX_NODE_LEN); +} #define ncp_printf printf @@ -79,17 +164,57 @@ ncp_ioctl_request(struct ncp_server *server, int function) { return result; } +static int +ipx_recvfrom(int sock, void *buf, int len, unsigned int flags, + struct sockaddr_ipx *sender, int *addrlen, int timeout) +{ + fd_set rd, wr, ex; + struct timeval tv; + int result; + + FD_ZERO(&rd); FD_ZERO(&wr); FD_ZERO(&ex); + FD_SET(sock, &rd); + + tv.tv_sec = timeout; + tv.tv_usec = 0; + + if ((result = select(sock+1, &rd, &wr, &ex, &tv)) == -1) { + return result; + } + + if (FD_ISSET(sock, &rd)) { + result = recvfrom(sock, buf, len, flags, + (struct sockaddr *)sender, addrlen); + } + else + { + result = -1; + errno = ETIMEDOUT; + } + return result; +} + +static int +ipx_recv(int sock, void *buf, int len, unsigned int flags, int timeout) +{ + struct sockaddr_ipx sender; + int addrlen = sizeof(sender); + + return ipx_recvfrom(sock, buf, len, flags, &sender, &addrlen, timeout); +} + + static int do_ncp_call(struct ncp_server *server, int request_size) { struct ncp_request_header request = *((struct ncp_request_header *)(&(server->ncp_data))); - fd_set rd, wr, ex; - struct timeval tv; - int result; int retries = 3; + int len; + struct ncp_reply_header *r = + (struct ncp_reply_header *)&(server->ncp_data); while (retries > 0) { retries -= 1; @@ -104,37 +229,21 @@ do_ncp_call(struct ncp_server *server, int request_size) } re_select: - FD_ZERO(&rd); FD_ZERO(&wr); FD_ZERO(&ex); - FD_SET(server->ncp_sock, &rd); - - tv.tv_sec = 3; - tv.tv_usec = 0; - - if (select(server->ncp_sock+1, &rd, &wr, &ex, &tv) == -1) { - perror("select"); - return -1; - } - - if (FD_ISSET(server->ncp_sock, &rd)) { - int len = recv(server->ncp_sock, - server->ncp_data, NCP_PACKET_SIZE, - 0); - struct ncp_reply_header *r = - (struct ncp_reply_header *)&(server->ncp_data); + len = ipx_recv(server->ncp_sock, + server->ncp_data, NCP_PACKET_SIZE, 0, 1); - if ( (len == sizeof(*r)) - && (r->type == NCP_POSITIVE_ACK)) { - goto re_select; - } - if ( (len >= sizeof(*r)) - && (r->type == NCP_REPLY) - && ( (request.type == NCP_ALLOC_SLOT_REQUEST) - || ( (r->sequence == request.sequence) - && (r->conn_low == request.conn_low) - && (r->conn_high == request.conn_high)))) { - server->reply_size = len; - break; - } + if ( (len == sizeof(*r)) + && (r->type == NCP_POSITIVE_ACK)) { + goto re_select; + } + if ( (len >= sizeof(*r)) + && (r->type == NCP_REPLY) + && ( (request.type == NCP_ALLOC_SLOT_REQUEST) + || ( (r->sequence == request.sequence) + && (r->conn_low == request.conn_low) + && (r->conn_high == request.conn_high)))) { + server->reply_size = len; + break; } } return 0; @@ -189,8 +298,6 @@ install_wdog(struct ncp_server *server) int pid; int sock = server->wdog_sock; - fd_set rd, wr, ex; - struct timeval tv; char buf[1024]; struct sockaddr_ipx sender; int sizeofaddr = sizeof(struct sockaddr_ipx); @@ -209,17 +316,10 @@ install_wdog(struct ncp_server *server) while (1) { - FD_ZERO(&rd); FD_ZERO(&wr); FD_ZERO(&ex); - FD_SET(sock, &rd); - /* every 120 seconds we look if our parent is still alive */ - tv.tv_sec = 120; - tv.tv_usec = 0; - - if (select(sock+1, &rd, &wr, &ex, &tv) == -1) { - continue; - } + pktsize = ipx_recvfrom(sock, buf, sizeof(buf), 0, + &sender, &sizeofaddr, 120); if (getppid() != parent_pid) { /* our parent has died, so nothing to do @@ -227,31 +327,121 @@ install_wdog(struct ncp_server *server) exit(0); } - if (FD_ISSET(sock, &rd)) { - pktsize = recvfrom(sock, buf, sizeof(buf), 0, - (struct sockaddr *)&sender, - &sizeofaddr); - if (pktsize < 0) { - perror("recvfrom"); - continue; - } - if ( (pktsize != 2) - || (buf[1] != '?')) { - continue; - } - buf[1] = 'Y'; - pktsize = sendto(sock, buf, 2, 0, - (struct sockaddr *)&sender, - sizeof(sender)); - if (pktsize < 0) { - perror("send"); - } + if ( (pktsize != 2) + || (buf[1] != '?')) { + continue; } + + buf[1] = 'Y'; + pktsize = sendto(sock, buf, 2, 0, + (struct sockaddr *)&sender, + sizeof(sender)); } } +static int +ipx_make_reachable(IPXNet network) +{ + struct rtentry rt_def; + /* Router */ + struct sockaddr_ipx *sr = (struct sockaddr_ipx *)&rt_def.rt_gateway; + /* Target */ + struct sockaddr_ipx *st = (struct sockaddr_ipx *)&rt_def.rt_dst; + + struct ipx_rip_packet rip; + struct sockaddr_ipx addr; + int addrlen; + int sock; + int opt; + int res=-1; + int i; + int packets; + + if (geteuid() != 0) { + errno = EPERM; + return -1; + } + + memset(&rip, 0, sizeof(rip)); + + sock = socket(AF_IPX, SOCK_DGRAM, PF_IPX); + + if (sock == -1) { + return -1; + } + + opt=1; + /* Permit broadcast output */ + if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &opt,sizeof(opt)) != 0){ + goto finished; + } + + memset(&addr, 0, sizeof(addr)); + addr.sipx_family=AF_IPX; + addr.sipx_network=htonl(0x0); + addr.sipx_port=htons(0x0); + addr.sipx_type=IPX_RIP_PTYPE; + + if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) != 0) { + goto finished; + } + + addr.sipx_family = AF_IPX; + addr.sipx_network = htonl(0x0); + addr.sipx_port = htons(IPX_RIP_PORT); + addr.sipx_type = IPX_RIP_PTYPE; + ipx_assign_node(addr.sipx_node, IPX_BROADCAST_NODE); + + rip.operation = htons(IPX_RIP_REQUEST); + rip.rt[0].network = htonl(network); + + if (sendto(sock, &rip, sizeof(rip), 0, + (struct sockaddr *)&addr, sizeof(addr)) < 0) { + goto finished; + } + + packets = 3; + do + { + int len; + + if (packets == 0) { + goto finished; + } + + addrlen = sizeof(struct sockaddr_ipx); + + len = ipx_recvfrom(sock, &rip, sizeof(rip),0, sr, &addrlen, 1); + if (len < sizeof(rip)) { + packets = packets - 1; + continue; + } + } while (ntohs(rip.operation) != IPX_RIP_RESPONSE); + + if (rip.rt[0].network != htonl(network)) { + goto finished; + } + + rt_def.rt_flags = RTF_GATEWAY; + st->sipx_network = htonl(network); + sr->sipx_family = st->sipx_family = AF_IPX; + i = 0; + do { + res = ioctl(sock, SIOCADDRT, &rt_def); + i++; + } while ((i < 5) && (res < 0) && (errno == EAGAIN)); + + finished: + close(sock); + + if (res != 0) { + errno = ENETUNREACH; + } + return res; +} + int -ncp_connect(struct ncp_server *server) +ncp_connect_addr(struct ncp_server *server, const struct sockaddr_ipx *target) { struct ncp_request_header *h = (struct ncp_request_header *)&(server->ncp_data); @@ -263,6 +453,7 @@ ncp_connect(struct ncp_server *server) int ncp_port, wdog_port; server->is_connected = NOT_CONNECTED; + server->silent = 1; ncp_sock = socket(AF_IPX, SOCK_DGRAM, PF_IPX); if (ncp_sock == -1) { @@ -323,6 +514,7 @@ ncp_connect(struct ncp_server *server) h->type = NCP_ALLOC_SLOT_REQUEST; server->sequence = 0; + server->addr = *target; h->sequence = server->sequence; h->conn_low = 0xff; h->conn_high = 0xff; @@ -330,10 +522,17 @@ ncp_connect(struct ncp_server *server) h->function = 0; if (do_ncp_call(server, sizeof(*h)) != 0) { - int saved_errno = errno; - close(ncp_sock); close(wdog_sock); - errno = saved_errno; - return -1; + + if ( (errno != ENETUNREACH) + || (ipx_make_reachable(htonl(target->sipx_network)) != 0) + || (do_ncp_call(server, sizeof(*h)) != 0)) { + + int saved_errno = errno; + + close(ncp_sock); close(wdog_sock); + errno = saved_errno; + return -1; + } } install_wdog(server); @@ -346,6 +545,107 @@ ncp_connect(struct ncp_server *server) return 0; } +static int +ipx_sap_find_nearest(int server_type, struct sockaddr_ipx *result) +{ + struct sockaddr_ipx addr; + char data[1024]; + int sock; + int opt; + int res = -1; + int saved_errno; + int packets; + int len; + + struct sap_server_ident *ident; + + sock=socket(AF_IPX,SOCK_DGRAM,PF_IPX); + if (sock==-1) { + return -1; + } + + opt=1; + /* Permit broadcast output */ + if(setsockopt(sock,SOL_SOCKET,SO_BROADCAST, &opt,sizeof(opt))==-1) + { + goto finished; + } + + memset(&addr, 0, sizeof(addr)); + addr.sipx_family=AF_IPX; + addr.sipx_network=htonl(0x0); + addr.sipx_port=htons(0x0); + addr.sipx_type=IPX_SAP_PTYPE; + + if(bind(sock,(struct sockaddr*)&addr,sizeof(addr))==-1) + { + goto finished; + } + + *(unsigned short *)data = htons(IPX_SAP_NEAREST_QUERY); + *(unsigned short *)&(data[2]) = htons(server_type); + + memset(&addr, 0, sizeof(addr)); + addr.sipx_family=AF_IPX; + addr.sipx_network=htonl(0x0); + ipx_assign_node(addr.sipx_node, IPX_BROADCAST_NODE); + addr.sipx_port=htons(IPX_SAP_PORT); + addr.sipx_type=IPX_SAP_PTYPE; + + if (sendto(sock, data, 4, 0, + (struct sockaddr *)&addr, sizeof(addr)) < 0) + { + goto finished; + } + + packets = 5; + do + { + len = ipx_recv(sock, data, 1024, 0, 1); + if (len < 66) { + packets = packets - 1; + continue; + } + } while (ntohs(*((__u16 *)data)) != IPX_SAP_NEAREST_RESPONSE); + + ident = (struct sap_server_ident *)(data+2); + + result->sipx_family = AF_IPX; + result->sipx_network = ident->server_network; + result->sipx_port = ident->server_port; + ipx_assign_node(result->sipx_node, ident->server_node); + + res = 0; + + finished: + saved_errno = errno; + close(sock); + errno = saved_errno; + return res; +} + + +static int +ncp_connect_any(struct ncp_server *server) +{ + struct sockaddr_ipx addr; + + if (ipx_sap_find_nearest(IPX_SAP_FILE_SERVER, &addr) != 0) { + return -1; + } + + return ncp_connect_addr(server, &addr); +} + +int +ncp_connect(struct ncp_server *server, const char *name) +{ + if (name == NULL) { + return ncp_connect_any(server); + } + return -1; +} + static int ncp_user_disconnect(struct ncp_server *server) { @@ -610,6 +910,35 @@ ncp_get_bindery_object_id(struct ncp_server *server, return 0; } +int +ncp_scan_bindery_object(struct ncp_server *server, + __u32 last_id, __u16 object_type, char *search_string, + struct ncp_bindery_object *target) +{ + int result; + ncp_init_request_s(server, 55); + ncp_add_dword(server, htonl(last_id)); + ncp_add_word(server, htons(object_type)); + ncp_add_pstring(server, search_string); + + if ((result = ncp_request(server, 23)) != 0) { + ncp_unlock_server(server); + return result; + } + + target->object_id = ntohl(ncp_reply_dword(server, 0)); + target->object_type = ntohs(ncp_reply_word(server, 4)); + memcpy(target->object_name, ncp_reply_data(server, 6), + NCP_BINDERY_NAME_LEN); + target->object_flags = ncp_reply_byte(server, 54); + target->object_security = ncp_reply_byte(server, 55); + target->object_has_prop = ncp_reply_byte(server, 56); + + ncp_unlock_server(server); + return 0; +} + + int ncp_read_property_value(struct ncp_server *server, int object_type, char *object_name, diff --git a/util/ncplib_user.h b/util/ncplib.h similarity index 70% rename from util/ncplib_user.h rename to util/ncplib.h index 6541cd2..a97cb28 100644 --- a/util/ncplib_user.h +++ b/util/ncplib.h @@ -6,6 +6,68 @@ #include #include +typedef unsigned long IPXNet; +typedef unsigned short IPXPort; +typedef unsigned char IPXNode[IPX_NODE_LEN]; + +#define IPX_RIP_PTYPE (0x01) +#define IPX_SAP_PTYPE (0x04) +#define IPX_SAP_PORT (0x0452) +#define IPX_RIP_PORT (0x0453) + +#define IPX_SAP_GENERAL_QUERY (0x0001) +#define IPX_SAP_GENERAL_RESPONSE (0x0002) +#define IPX_SAP_NEAREST_QUERY (0x0003) +#define IPX_SAP_NEAREST_RESPONSE (0x0004) + +#define IPX_SAP_FILE_SERVER (0x0004) + +struct sap_query { + unsigned short query_type; /* net order */ + unsigned short server_type; /* net order */ +}; + +struct sap_server_ident { + unsigned short server_type __attribute__ ((packed)); + char server_name[48] __attribute__ ((packed)); + IPXNet server_network __attribute__ ((packed)); + IPXNode server_node __attribute__ ((packed)); + IPXPort server_port __attribute__ ((packed)); + unsigned short intermediate_network __attribute__ ((packed)); +}; + +#define IPX_RIP_REQUEST (0x1) +#define IPX_RIP_RESPONSE (0x2) + +struct ipx_rip_packet { + __u16 operation __attribute__ ((packed)); + struct ipx_rt_def { + __u32 network __attribute__ ((packed)); + __u16 hops __attribute__ ((packed)); + __u16 ticks __attribute__ ((packed)); + } rt[1] __attribute__ ((packed)); +}; + +#define IPX_BROADCAST_NODE "\xff\xff\xff\xff\xff\xff" +#define IPX_THIS_NODE "\0\0\0\0\0\0" + +#ifndef IPX_NODE_LEN +#define IPX_NODE_LEN (6) +#endif + +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); +int +ipx_sscanf_node(char *buf, unsigned char node[IPX_NODE_LEN]); +void +ipx_assign_node(IPXNode dest, IPXNode src); + enum connect_state { NOT_CONNECTED = 0, CONN_MOUNTED, @@ -43,7 +105,10 @@ int ncp_connect_mount(struct ncp_server *server, const char *mount_point); int -ncp_connect(struct ncp_server *server); +ncp_connect_addr(struct ncp_server *server, const struct sockaddr_ipx *target); + +int +ncp_connect(struct ncp_server *server, const char *server_name); int ncp_disconnect(struct ncp_server *server); @@ -59,6 +124,10 @@ ncp_get_bindery_object_id(struct ncp_server *server, int object_type, char *object_name, struct ncp_bindery_object *target); int +ncp_scan_bindery_object(struct ncp_server *server, + __u32 last_id, __u16 object_type, char *search_string, + struct ncp_bindery_object *target); +int ncp_read_property_value(struct ncp_server *server, int object_type, char *object_name, int segment, char *prop_name, diff --git a/util/ncpmount.c b/util/ncpmount.c index 9bda3dc..59b4e0f 100644 --- a/util/ncpmount.c +++ b/util/ncpmount.c @@ -28,15 +28,13 @@ extern pid_t waitpid(pid_t, int *, int); #include #include #include -#include #include #include #include #include #include -#include "ipxutil.h" -#include "ncplib_user.h" +#include "ncplib.h" static char *progname; @@ -77,105 +75,34 @@ help(void) "\n"); } -struct sap_query { - unsigned short query_type; /* net order */ - unsigned short server_type; /* net order */ -}; - -struct sap_server_ident { - unsigned short server_type __attribute__ ((packed)); - char server_name[48] __attribute__ ((packed)); - IPXNet server_network __attribute__ ((packed)); - IPXNode server_node __attribute__ ((packed)); - IPXPort server_port __attribute__ ((packed)); - unsigned short intermediate_network __attribute__ ((packed)); -}; - -void -ipx_fprint_node(FILE* file,IPXNode node) +int +ipx_sap_find_server(char *name, int server_type, int timeout, + struct sockaddr_ipx *result) { - 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",ntohl(net)); -} - -void -ipx_fprint_port(FILE* file,IPXPort port) -{ - fprintf(file,"%04X",ntohs(port)); -} - -void -ipx_fprint_saddr(FILE* file,struct sockaddr_ipx* sipx) -{ - ipx_fprint_network(file,sipx->sipx_network); - fprintf(file,":"); - ipx_fprint_node(file,sipx->sipx_node); - fprintf(file,":"); - ipx_fprint_port(file,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); -} - -static int -ipx_make_reachable(__u32 network) -{ - struct rtentry rt_def; - /* Router */ - struct sockaddr_ipx *sr = (struct sockaddr_ipx *)&rt_def.rt_gateway; - /* Target */ - struct sockaddr_ipx *st = (struct sockaddr_ipx *)&rt_def.rt_dst; - - fd_set rd, wr, ex; - struct timeval tv; - - struct ipx_rip_packet rip; struct sockaddr_ipx addr; - int addrlen; + char data[1024]; int sock; int opt; - int res=-1; - int i; + int res = -1; + int name_len = strlen(name); + fd_set rd, wr, ex; + struct timeval tv; + struct sap_server_ident *ident; - sock = socket(AF_IPX, SOCK_DGRAM, PF_IPX); + struct ncp_server server; + struct nw_property prop; + struct prop_net_address *n_addr = (struct prop_net_address *)∝ - if (sock == -1) { + + if (name_len > 48) { return -1; } + sock=socket(AF_IPX,SOCK_DGRAM,PF_IPX); + if (sock==-1) { + return -1; + } + opt=1; /* Permit broadcast output */ if(setsockopt(sock,SOL_SOCKET,SO_BROADCAST, &opt,sizeof(opt))==-1) @@ -188,7 +115,7 @@ ipx_make_reachable(__u32 network) addr.sipx_family=AF_IPX; addr.sipx_network=htonl(0x0); addr.sipx_port=htons(0x0); - addr.sipx_type=IPX_RIP_PTYPE; + addr.sipx_type=IPX_SAP_PTYPE; if(bind(sock,(struct sockaddr*)&addr,sizeof(addr))==-1) { @@ -196,153 +123,18 @@ ipx_make_reachable(__u32 network) goto finished; } - addr.sipx_family = AF_IPX; - addr.sipx_network = htonl(0x0); - addr.sipx_port = htons(IPX_RIP_PORT); - addr.sipx_type = IPX_RIP_PTYPE; - ipx_assign_node(addr.sipx_node, IPX_BROADCAST_NODE); - - rip.operation = htons(IPX_RIP_REQUEST); - rip.rt[0].network = htonl(network); - - if (sendto(sock, &rip, sizeof(rip), 0, - (struct sockaddr *)&addr, sizeof(addr)) < 0) { - perror("sendto"); - goto finished; - } - - do - { - - FD_ZERO(&rd); FD_ZERO(&wr); FD_ZERO(&ex); - FD_SET(sock, &rd); - - tv.tv_sec = 3; - tv.tv_usec = 0; - - if (select(sock+1, &rd, &wr, &ex, &tv) == -1) - { - goto finished; - } - - if (FD_ISSET(sock, &rd)) - { - int len; - - addrlen = sizeof(struct sockaddr_ipx); - - len = recvfrom(sock, &rip, sizeof(rip), 0, - (struct sockaddr *)sr, &addrlen); - - if (len < sizeof(rip)) - { - continue; - } - } - else - { - goto finished; - } - } while (ntohs(rip.operation) != IPX_RIP_RESPONSE); - - if (rip.rt[0].network != htonl(network)) { - goto finished; - } - - rt_def.rt_flags = RTF_GATEWAY; - st->sipx_network = htonl(network); - sr->sipx_family = st->sipx_family = AF_IPX; - i = 0; - do { - res = ioctl(sock, SIOCADDRT, &rt_def); - i++; - } while ((i < 5) && (res < 0) && (errno == EAGAIN)); - - if (res != 0) { - - switch (errno) { - case ENETUNREACH: - fprintf(stderr, - "%s: Router network (%08lX) not reachable.\n", - progname, htonl(sr->sipx_network)); - break; - default: - perror("ioctl"); - break; - } - goto finished; - } - - finished: - close(sock); - return res; -} - -int -ipx_sap_find_server(char *name, int server_type, int timeout, - struct sockaddr_ipx *result) -{ - struct sockaddr_ipx ipxs; - char data[1024]; - int sock; - int opt; - int res = -1; - int name_len = strlen(name); - fd_set rd, wr, ex; - struct timeval tv; - struct sap_server_ident *ident; - - struct ncp_server server; - struct nw_property prop; - struct net_address - { - __u32 network __attribute__ ((packed)); - __u8 node[6] __attribute__ ((packed)); - __u16 port __attribute__ ((packed)); - } *n_addr = (struct net_address *)∝ - - - if (name_len > 48) { - return -1; - } - - sock=socket(AF_IPX,SOCK_DGRAM,PF_IPX); - if (sock==-1) { - return -1; - } - - opt=1; - /* Permit broadcast output */ - if(setsockopt(sock,SOL_SOCKET,SO_BROADCAST, &opt,sizeof(opt))==-1) - { - perror("setsockopt"); - goto finished; - } - - memset(&ipxs, 0, sizeof(ipxs)); - ipxs.sipx_family=AF_IPX; - ipxs.sipx_network=htonl(0x0); - ipxs.sipx_port=htons(0x0); - ipxs.sipx_type=IPX_SAP_PTYPE; - - if(bind(sock,(struct sockaddr*)&ipxs,sizeof(ipxs))==-1) - { - perror("bind"); - goto finished; - } - *(unsigned short *)data = htons(IPX_SAP_NEAREST_QUERY); *(unsigned short *)&(data[2]) = htons(server_type); - memset(&ipxs, 0, sizeof(ipxs)); - ipxs.sipx_family=AF_IPX; - ipxs.sipx_network=htonl(0x0); - ipx_assign_node(ipxs.sipx_node, IPX_BROADCAST_NODE); - ipxs.sipx_port=htons(IPX_SAP_PORT); - ipxs.sipx_type=IPX_SAP_PTYPE; + memset(&addr, 0, sizeof(addr)); + addr.sipx_family=AF_IPX; + addr.sipx_network=htonl(0x0); + ipx_assign_node(addr.sipx_node, IPX_BROADCAST_NODE); + addr.sipx_port=htons(IPX_SAP_PORT); + addr.sipx_type=IPX_SAP_PTYPE; if (sendto(sock, data, 4, 0, - (struct sockaddr *)&ipxs, sizeof(ipxs)) < 0) + (struct sockaddr *)&addr, sizeof(addr)) < 0) { perror("sendto"); goto finished; @@ -385,18 +177,13 @@ ipx_sap_find_server(char *name, int server_type, int timeout, route to the server's internal network. Because this one request is not very expensive, we always do it. */ - server.addr.sipx_family = AF_IPX; - server.addr.sipx_network = ident->server_network; - server.addr.sipx_port = ident->server_port; - ipx_assign_node(server.addr.sipx_node, ident->server_node); + addr.sipx_family = AF_IPX; + addr.sipx_network = ident->server_network; + addr.sipx_port = ident->server_port; + ipx_assign_node(addr.sipx_node, ident->server_node); - if (ncp_connect(&server) != 0) - { - if ( (errno != ENETUNREACH) - || (ipx_make_reachable(ntohl(server.addr.sipx_network))!=0) - || (ncp_connect(&server) != 0)) { - goto finished; - } + if (ncp_connect_addr(&server, &addr) != 0) { + goto finished; } if (ncp_read_property_value(&server, NCP_BINDERY_FSERVER, @@ -407,8 +194,7 @@ ipx_sap_find_server(char *name, int server_type, int timeout, goto finished; } - if (ncp_disconnect(&server) != 0) - { + if (ncp_disconnect(&server) != 0) { goto finished; } @@ -420,19 +206,8 @@ ipx_sap_find_server(char *name, int server_type, int timeout, /* Now we connect to the ultimate target, again with a test for reachability. This time nothing is done except connecting. */ - server.addr = *result; - - if (ncp_connect(&server) != 0) - { - if ( (errno != ENETUNREACH) - || (ipx_make_reachable(ntohl(server.addr.sipx_network))!=0) - || (ncp_connect(&server) != 0)) { - goto finished; - } - } - - if (ncp_disconnect(&server) != 0) - { + if ( (ncp_connect_addr(&server, result) != 0) + || (ncp_disconnect(&server) != 0)) { goto finished; } @@ -444,24 +219,6 @@ ipx_sap_find_server(char *name, int server_type, int timeout, return res; } -int -ipx_sscanf_node(char *buf, unsigned char node[6]) -{ - 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 i; - } - - for (i=0; i<6; i++) { - node[i] = n[i]; - } - return 6; -} - static int parse_args(int argc, char *argv[], struct ncp_mount_data *data, int *got_password, int *upcase_password) @@ -664,7 +421,8 @@ main(int argc, char *argv[]) exit(1); } - memset(&data, 0, sizeof(struct ncp_mount_data)); + memset(&data, 0, sizeof(data)); + memset(&serv, 0, sizeof(serv)); memset(hostname, '\0', MAXHOSTNAMELEN+1); gethostname(hostname, MAXHOSTNAMELEN); @@ -832,9 +590,6 @@ main(int argc, char *argv[]) if (ncp_login_user(server, data.username, data.password) != 0) { fprintf(stderr, "login failed\n"); - fprintf(stderr, - "should try to type the username and\n" - "password in UPPERCASE.\n"); close(server->mount_fid); umount(mount_point); return -1; diff --git a/util/ncptest.c b/util/ncptest.c index 33da516..8bd5c01 100644 --- a/util/ncptest.c +++ b/util/ncptest.c @@ -35,8 +35,7 @@ extern pid_t waitpid(pid_t, int *, int); #include #include #include -#include "ncplib_user.h" -#include "ipxutil.h" +#include "ncplib.h" static char *progname; @@ -49,79 +48,6 @@ str_upper(char *name) } } -struct sap_query { - unsigned short query_type; /* net order */ - unsigned short server_type; /* net order */ -}; - -struct sap_server_ident { - unsigned short server_type __attribute__ ((packed)); - char server_name[48] __attribute__ ((packed)); - IPXNet server_network __attribute__ ((packed)); - IPXNode server_node __attribute__ ((packed)); - IPXPort server_port __attribute__ ((packed)); - unsigned short intermediate_network __attribute__ ((packed)); -}; - -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",ntohl(net)); -} - -void -ipx_fprint_port(FILE* file,IPXPort port) -{ - fprintf(file,"%04X",ntohs(port)); -} - -void -ipx_fprint_saddr(FILE* file,struct sockaddr_ipx* sipx) -{ - ipx_fprint_network(file,sipx->sipx_network); - fprintf(file,":"); - ipx_fprint_node(file,sipx->sipx_node); - fprintf(file,":"); - ipx_fprint_port(file,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); -} - int ipx_sap_find_server(char *_name, int server_type, int timeout, struct sockaddr_ipx *result) @@ -237,25 +163,6 @@ ipx_sap_find_server(char *_name, int server_type, int timeout, return res; } -int -ipx_sscanf_node(char *buf, unsigned char node[6]) -{ - 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 i; - } - - for (i=0; i<6; i++) { - node[i] = n[i]; - } - return 6; -} - - void test_filesearch(struct ncp_server *server) { @@ -560,21 +467,21 @@ test_print(struct ncp_server *server) j.j.TargetServerID = 0xffffffff; /* any server */ memset(&(j.j.TargetExecTime), 0xff, sizeof(j.j.TargetExecTime)); /* at once */ - j.j.JobType = 0xffff; + j.j.JobType = htons(0); strcpy(j.j.JobTextDescription, "Test Job"); memset(&pj, 0, sizeof(pj)); pj.Version = 0; - pj.TabSize = 0; - pj.Copies = 1; + pj.TabSize = 8; + pj.Copies = htons(1); pj.CtrlFlags = 0; - pj.Lines = 0; - pj.Rows = 0; - strcpy(pj.FormName, ""); - strcpy(pj.Banner, ""); - strcpy(pj.FnameBanner, ""); - strcpy(pj.FnameHeader, ""); + pj.Lines = htons(66); + pj.Rows = htons(80); + strcpy(pj.FormName, "test"); + strcpy(pj.BannerName, "BannerName"); + strcpy(pj.FnameBanner, "BannerFile"); + strcpy(pj.FnameHeader, "HeaderName"); strcpy(pj.Path, ""); memcpy(j.j.ClientRecordArea, &pj, sizeof(pj)); @@ -584,7 +491,8 @@ test_print(struct ncp_server *server) return; } - if (ncp_write(server, j.file_handle, 0, 5, "hallo", &written) != 0) { + if (ncp_write(server, j.file_handle, 0, 5, "hallo, wie geht's?", + &written) != 0) { printf("write error\n"); return; } @@ -597,29 +505,37 @@ test_print(struct ncp_server *server) return; } - - +void +test_slist(struct ncp_server *server) +{ + struct ncp_bindery_object obj; + + obj.object_id = 0xffffffff; + + while (ncp_scan_bindery_object(server, obj.object_id, + 0xffff, "*", + &obj) == 0) { + printf("%s\n", obj.object_name); + } + return; +} int main(int argc, char **argv) { struct ncp_server serv; struct ncp_server *server = &serv; + struct sockaddr_ipx addr; progname = argv[0]; - if (argc != 2) { - printf("usage: %s server\n", argv[0]); - exit(1); - } - - if (ipx_sap_find_server(argv[1], IPX_SAP_FILE_SERVER, - 3, &(serv.addr)) != 0) { + if (ipx_sap_find_server("nw311", IPX_SAP_FILE_SERVER, + 3, &addr) != 0) { printf("could not find server %s\n", argv[1]); exit(1); } - if (ncp_connect(server) != 0) { + if (ncp_connect_addr(server, &addr) != 0) { printf("could not connect\n"); exit(1); } @@ -629,7 +545,7 @@ main(int argc, char **argv) exit(1); } - getchar(); + test_slist(server); ncp_disconnect(server); diff --git a/util/nwcrypt.c b/util/nwcrypt.c index d12e1c2..9c403bd 100644 --- a/util/nwcrypt.c +++ b/util/nwcrypt.c @@ -89,9 +89,8 @@ typedef unsigned char buf32[32]; typedef unsigned char buf16[16]; typedef unsigned char buf8[8]; typedef unsigned char buf4[4]; -typedef unsigned char u8; -static u8 encrypttable[256] = +static unsigned char encrypttable[256] = {0x7,0x8,0x0,0x8,0x6,0x4,0xE,0x4,0x5,0xC,0x1,0x7,0xB,0xF,0xA,0x8, 0xF,0x8,0xC,0xC,0x9,0x4,0x1,0xE,0x4,0x6,0x2,0x4,0x0,0xA,0xB,0x9, 0x2,0xF,0xB,0x1,0xD,0x2,0x1,0x9,0x5,0xE,0x7,0x0,0x0,0x2,0x6,0x6, @@ -142,7 +141,7 @@ shuffle1(buf32 temp, unsigned char *target) } -void +static void shuffle(unsigned char *lon, const unsigned char *buf, int buflen, unsigned char *target) { @@ -191,7 +190,7 @@ shuffle(unsigned char *lon, const unsigned char *buf, int buflen, } -void +static void nw_encrypt(unsigned char *fra,unsigned char *buf,unsigned char *til) { buf32 k; diff --git a/util/nwcrypt.h b/util/nwcrypt.h deleted file mode 100644 index a2f4b64..0000000 --- a/util/nwcrypt.h +++ /dev/null @@ -1,5 +0,0 @@ -void -shuffle(unsigned char *lon, const unsigned char *buf, int buflen, - unsigned char *target); -void -nw_encrypt(unsigned char *fra,unsigned char *buf,unsigned char *til); diff --git a/util/slist.c b/util/slist.c new file mode 100644 index 0000000..8694679 --- /dev/null +++ b/util/slist.c @@ -0,0 +1,77 @@ +#include "ncplib.h" +#include +#include +#include +#include +#include + +void +main(int argc, char *argv[]) +{ + struct ncp_server server; + struct ncp_bindery_object obj; + int found = 0; + char default_pattern[2] = "*"; + char *pattern = default_pattern; + char *p; + + if (argc > 2) { + printf("usage: %s [pattern]\n", argv[0]); + exit(1); + } + + if (argc == 2) { + pattern = argv[1]; + } + + for (p = pattern; *p != '\0'; p++) { + *p = toupper(*p); + } + + memset(&server, 0, sizeof(server)); + + if (ncp_connect(&server, NULL) != 0) { + perror("ncp_connect"); + exit(1); + } + + if (isatty(1)) { + printf("\n%-52s%-10s%-12s\n" + "-----------------------------------------------" + "---------------------------\n", + "Known NetWare File Servers", + "Network", + "Node Address"); + } + + obj.object_id = 0xffffffff; + + while (ncp_scan_bindery_object(&server, obj.object_id, + NCP_BINDERY_FSERVER, pattern, + &obj) == 0) { + + struct nw_property prop; + struct prop_net_address *naddr + = (struct prop_net_address *)∝ + + found = 1; + + printf("%-52s", obj.object_name); + + if (ncp_read_property_value(&server, NCP_BINDERY_FSERVER, + obj.object_name, 1, "NET_ADDRESS", + &prop) == 0) { + ipx_print_network(naddr->network); + printf(" "); + ipx_print_node(naddr->node); + } + printf("\n"); + } + + if ((found == 0) && (isatty(1))) { + printf("No servers found\n"); + } + + ncp_disconnect(&server); +} +