Import ncpfs 0.9
This commit is contained in:
BIN
.downloads/ncpfs-0.9.tgz
Normal file
BIN
.downloads/ncpfs-0.9.tgz
Normal file
Binary file not shown.
8
Makefile
8
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
|
||||
|
||||
8
README
8
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.
|
||||
|
||||
|
||||
30
ipx-0.75/Makefile
Normal file
30
ipx-0.75/Makefile
Normal file
@@ -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
|
||||
|
||||
65
ipx-0.75/README
Normal file
65
ipx-0.75/README
Normal file
@@ -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.
|
||||
|
||||
303
ipx-0.75/ipx_interface.c
Normal file
303
ipx-0.75/ipx_interface.c
Normal file
@@ -0,0 +1,303 @@
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/ipx.h>
|
||||
#include <linux/if.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
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;
|
||||
}
|
||||
195
ipx-0.75/ipx_internal_net.c
Normal file
195
ipx-0.75/ipx_internal_net.c
Normal file
@@ -0,0 +1,195 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <strings.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/ipx.h>
|
||||
#include <linux/if.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
215
ipx-0.75/ipx_route.c
Normal file
215
ipx-0.75/ipx_route.c
Normal file
@@ -0,0 +1,215 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <strings.h>
|
||||
#include <netinet/in.h>
|
||||
#include <linux/ipx.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/route.h>
|
||||
|
||||
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;
|
||||
}
|
||||
52
ipx-0.75/ipxrcv.c
Normal file
52
ipx-0.75/ipxrcv.c
Normal file
@@ -0,0 +1,52 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <linux/ipx.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
46
ipx-0.75/ipxsend.c
Normal file
46
ipx-0.75/ipxsend.c
Normal file
@@ -0,0 +1,46 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <linux/ipx.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
68
ipx-0.75/rip.c
Normal file
68
ipx-0.75/rip.c
Normal file
@@ -0,0 +1,68 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <linux/ipx.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
96
ipx-0.75/sap.c
Normal file
96
ipx-0.75/sap.c
Normal file
@@ -0,0 +1,96 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <linux/ipx.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#define _LINUX_NCP_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/ipx.h>
|
||||
|
||||
#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));
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <linux/ncp_fs.h>
|
||||
#include <asm/segment.h>
|
||||
#include <linux/errno.h>
|
||||
#include "ncplib.h"
|
||||
#include "ncplib_kernel.h"
|
||||
|
||||
struct ncp_dirent {
|
||||
struct nw_info_struct i;
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include <linux/stat.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/ncp_fs.h>
|
||||
#include "ncplib.h"
|
||||
#include "ncplib_kernel.h"
|
||||
#include <linux/malloc.h>
|
||||
|
||||
static int
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#include <linux/locks.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/malloc.h>
|
||||
#include "ncplib.h"
|
||||
#include "ncplib_kernel.h"
|
||||
|
||||
extern int close_fp(struct file *filp);
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
|
||||
|
||||
#include "ncplib.h"
|
||||
#include "ncplib_kernel.h"
|
||||
|
||||
typedef __u8 byte;
|
||||
typedef __u16 word;
|
||||
@@ -11,6 +11,7 @@
|
||||
#error "Please use kernel 1.2.13"
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/ipx.h>
|
||||
|
||||
#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));
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
#include <linux/ncp_fs.h>
|
||||
#include <asm/segment.h>
|
||||
#include <linux/errno.h>
|
||||
#include "ncplib.h"
|
||||
#include "ncplib_kernel.h"
|
||||
|
||||
struct ncp_dirent {
|
||||
struct nw_info_struct i;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include <linux/stat.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/ncp_fs.h>
|
||||
#include "ncplib.h"
|
||||
#include "ncplib_kernel.h"
|
||||
#include <linux/malloc.h>
|
||||
|
||||
static int
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include <linux/locks.h>
|
||||
#include <linux/fcntl.h>
|
||||
#include <linux/malloc.h>
|
||||
#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);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "ncplib.h"
|
||||
#include "ncplib_kernel.h"
|
||||
|
||||
typedef __u8 byte;
|
||||
typedef __u16 word;
|
||||
61
man/ipx_interface.8
Normal file
61
man/ipx_interface.8
Normal file
@@ -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 <greg.page@caldera.com>
|
||||
32
man/ipx_internal_net.8
Normal file
32
man/ipx_internal_net.8
Normal file
@@ -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 <greg.page@caldera.com>
|
||||
24
man/ipx_route.8
Normal file
24
man/ipx_route.8
Normal file
@@ -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 <greg.page@caldera.com>
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
44
man/slist.1
Normal file
44
man/slist.1
Normal file
@@ -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 <lendecke@namu01.gwdg.de>
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
BIN
util/ipx.tar
BIN
util/ipx.tar
Binary file not shown.
@@ -1,76 +0,0 @@
|
||||
|
||||
/*
|
||||
|
||||
IPX support library
|
||||
|
||||
Copyright (C) 1994, 1995 Ales Dryak <e-mail: A.Dryak@sh.cvut.cz>
|
||||
|
||||
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 <string.h>
|
||||
#include <linux/ipx.h>
|
||||
|
||||
#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
|
||||
@@ -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 <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include "ipxutil.h"
|
||||
#include <linux/route.h>
|
||||
|
||||
/* 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,
|
||||
@@ -6,6 +6,68 @@
|
||||
#include <linux/ncp_fs.h>
|
||||
#include <linux/ipx.h>
|
||||
|
||||
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,
|
||||
323
util/ncpmount.c
323
util/ncpmount.c
@@ -28,15 +28,13 @@ extern pid_t waitpid(pid_t, int *, int);
|
||||
#include <sys/mount.h>
|
||||
#include <mntent.h>
|
||||
#include <linux/ipx.h>
|
||||
#include <linux/route.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <linux/fs.h>
|
||||
#include <linux/ncp.h>
|
||||
#include <linux/ncp_fs.h>
|
||||
#include <linux/ncp_mount.h>
|
||||
#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;
|
||||
|
||||
146
util/ncptest.c
146
util/ncptest.c
@@ -35,8 +35,7 @@ extern pid_t waitpid(pid_t, int *, int);
|
||||
#include <linux/ncp.h>
|
||||
#include <linux/ncp_fs.h>
|
||||
#include <linux/ncp_mount.h>
|
||||
#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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
77
util/slist.c
Normal file
77
util/slist.c
Normal file
@@ -0,0 +1,77 @@
|
||||
#include "ncplib.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user