build standalone ipx utilities without ncpfs private headers
This commit is contained in:
380
INSTALL
380
INSTALL
@@ -0,0 +1,380 @@
|
||||
Installation Instructions
|
||||
*************************
|
||||
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
The following shell commands:
|
||||
|
||||
test -f configure || ./bootstrap
|
||||
./configure
|
||||
make
|
||||
make install
|
||||
|
||||
should configure, build, and install this package. The first line,
|
||||
which bootstraps, is intended for developers; when building from
|
||||
distribution tarballs it does nothing and can be skipped. A package
|
||||
might name the bootstrapping script differently; if the name is
|
||||
‘autogen.sh’, for example, the first line should say ‘./autogen.sh’
|
||||
instead of ‘./bootstrap’.
|
||||
|
||||
The following more-detailed instructions are generic; see the
|
||||
‘README’ file for instructions specific to this package. Some packages
|
||||
provide this ‘INSTALL’ file but do not implement all of the features
|
||||
documented below. The lack of an optional feature in a given package is
|
||||
not necessarily a bug. More recommendations for GNU packages can be
|
||||
found in the GNU Coding Standards.
|
||||
|
||||
Many packages have scripts meant for developers instead of ordinary
|
||||
builders, as they may use developer tools that are less commonly
|
||||
installed, or they may access the network, which has privacy
|
||||
implications. These scripts attempt to bootstrap by building the
|
||||
‘configure’ script and related files, possibly using developer tools or
|
||||
the network. Because the output of bootstrapping is system-independent,
|
||||
it is normally run by a package developer so that its output can be put
|
||||
into the distribution tarball and ordinary builders and users need not
|
||||
bootstrap. Some packages have commands like ‘./autopull.sh’ and
|
||||
‘./autogen.sh’ that you can run instead of ‘./bootstrap’, for more
|
||||
fine-grained control over bootstrapping.
|
||||
|
||||
The ‘configure’ script attempts to guess correct values for various
|
||||
system-dependent variables used during compilation. It uses those
|
||||
values to create a ‘Makefile’ in each directory of the package. It may
|
||||
also create one or more ‘.h’ files containing system-dependent
|
||||
definitions. Finally, it creates a script ‘config.status’ that you can
|
||||
run in the future to recreate the current configuration, and a file
|
||||
‘config.log’ containing output useful for debugging ‘configure’.
|
||||
|
||||
It can also use an optional file (typically called ‘config.cache’ and
|
||||
enabled with ‘--cache-file=config.cache’ or simply ‘-C’) that saves the
|
||||
results of its tests to speed up reconfiguring. Caching is disabled by
|
||||
default to prevent problems with accidental use of stale cache files.
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how ‘configure’ could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the ‘README’ so they can
|
||||
be considered for the next release. If you are using the cache, and at
|
||||
some point ‘config.cache’ contains results you don’t want to keep, you
|
||||
may remove or edit it.
|
||||
|
||||
The ‘autoconf’ program generates ‘configure’ from the file
|
||||
‘configure.ac’. Normally you should edit ‘configure.ac’ instead of
|
||||
editing ‘configure’ directly.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. ‘cd’ to the directory containing the package’s source code.
|
||||
|
||||
2. If this is a developer checkout and file ‘configure’ does not yet
|
||||
exist, run the bootstrapping script (typically ‘./bootstrap’ or
|
||||
‘./autogen.sh’) to bootstrap and create the file. You may need
|
||||
special developer tools and network access to bootstrap, and the
|
||||
network access may have privacy implications.
|
||||
|
||||
3. Type ‘./configure’ to configure the package for your system. This
|
||||
might take a while. While running, ‘configure’ prints messages
|
||||
telling which features it is checking for.
|
||||
|
||||
4. Type ‘make’ to compile the package.
|
||||
|
||||
5. Optionally, type ‘make check’ to run any self-tests that come with
|
||||
the package, generally using the just-built uninstalled binaries.
|
||||
|
||||
6. Type ‘make install’ to install the programs and any data files and
|
||||
documentation. When installing into a prefix owned by root, it is
|
||||
recommended that the package be configured and built as a regular
|
||||
user, and only the ‘make install’ phase executed with root
|
||||
privileges.
|
||||
|
||||
7. Optionally, type ‘make installcheck’ to repeat any self-tests, but
|
||||
this time using the binaries in their final installed location.
|
||||
This target does not install anything. Running this target as a
|
||||
regular user, particularly if the prior ‘make install’ required
|
||||
root privileges, verifies that the installation completed
|
||||
correctly.
|
||||
|
||||
8. You can remove the program binaries and object files from the
|
||||
source code directory by typing ‘make clean’. To also remove the
|
||||
files that ‘configure’ created (so you can compile the package for
|
||||
a different kind of computer), type ‘make distclean’. There is
|
||||
also a ‘make maintainer-clean’ target, but that is intended mainly
|
||||
for the package’s developers. If you use it, you may have to
|
||||
bootstrap again.
|
||||
|
||||
9. If the package follows the GNU Coding Standards, you can type ‘make
|
||||
uninstall’ to remove the installed files.
|
||||
|
||||
Installation Prerequisites
|
||||
==========================
|
||||
|
||||
Installation requires a POSIX-like environment with a shell and at
|
||||
least the following standard utilities:
|
||||
|
||||
awk cat cp diff echo expr false ls mkdir mv printf pwd rm rmdir sed
|
||||
sort test tr
|
||||
|
||||
This package’s installation may need other standard utilities such as
|
||||
‘grep’, ‘make’, ‘sleep’ and ‘touch’, along with compilers like ‘gcc’.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that
|
||||
the ‘configure’ script does not know about. Run ‘./configure --help’
|
||||
for details on some of the pertinent environment variables.
|
||||
|
||||
You can give ‘configure’ initial values for configuration parameters
|
||||
by setting variables in the command line or in the environment. Here is
|
||||
an example:
|
||||
|
||||
./configure CC=gcc CFLAGS=-g LIBS=-lposix
|
||||
|
||||
See “Defining Variables” for more details.
|
||||
|
||||
Compiling For Multiple Architectures
|
||||
====================================
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each system in their own
|
||||
directory. To do this, you can use GNU ‘make’. ‘cd’ to the directory
|
||||
where you want the object files and executables to go and run the
|
||||
‘configure’ script. ‘configure’ automatically checks for the source
|
||||
code in the directory that ‘configure’ is in and in ‘..’. This is known
|
||||
as a “VPATH” build.
|
||||
|
||||
With a non-GNU ‘make’, it is safer to compile the package for one
|
||||
system at a time in the source code directory. After you have installed
|
||||
the package for one system, use ‘make distclean’ before reconfiguring
|
||||
for another system.
|
||||
|
||||
Some platforms, notably macOS, support “fat” or “universal” binaries,
|
||||
where a single binary can execute on different architectures. On these
|
||||
platforms you can configure and compile just once, with options specific
|
||||
to that platform.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, ‘make install’ installs the package’s commands under
|
||||
‘/usr/local/bin’, include files under ‘/usr/local/include’, etc. You
|
||||
can specify an installation prefix other than ‘/usr/local’ by giving
|
||||
‘configure’ the option ‘--prefix=PREFIX’, where PREFIX must be an
|
||||
absolute file name.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
pass the option ‘--exec-prefix=PREFIX’ to ‘configure’, the package uses
|
||||
PREFIX as the prefix for installing programs and libraries.
|
||||
Documentation and other data files still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like ‘--bindir=DIR’ to specify different values for particular
|
||||
kinds of files. Run ‘configure --help’ for a list of the directories
|
||||
you can set and what kinds of files go in them. In general, the default
|
||||
for these options is expressed in terms of ‘${prefix}’, so that
|
||||
specifying just ‘--prefix’ will affect all of the other directory
|
||||
specifications that were not explicitly provided.
|
||||
|
||||
The most portable way to affect installation locations is to pass the
|
||||
correct locations to ‘configure’; however, many packages provide one or
|
||||
both of the following shortcuts of passing variable assignments to the
|
||||
‘make install’ command line to change installation locations without
|
||||
having to reconfigure or recompile.
|
||||
|
||||
The first method involves providing an override variable for each
|
||||
affected directory. For example, ‘make install
|
||||
prefix=/alternate/directory’ will choose an alternate location for all
|
||||
directory configuration variables that were expressed in terms of
|
||||
‘${prefix}’. Any directories that were specified during ‘configure’,
|
||||
but not in terms of ‘${prefix}’, must each be overridden at install time
|
||||
for the entire installation to be relocated. The approach of makefile
|
||||
variable overrides for each directory variable is required by the GNU
|
||||
Coding Standards, and ideally causes no recompilation. However, some
|
||||
platforms have known limitations with the semantics of shared libraries
|
||||
that end up requiring recompilation when using this method, particularly
|
||||
noticeable in packages that use GNU Libtool.
|
||||
|
||||
The second method involves providing the ‘DESTDIR’ variable. For
|
||||
example, ‘make install DESTDIR=/alternate/directory’ will prepend
|
||||
‘/alternate/directory’ before all installation names. The approach of
|
||||
‘DESTDIR’ overrides is not required by the GNU Coding Standards, and
|
||||
does not work on platforms that have drive letters. On the other hand,
|
||||
it does better at avoiding recompilation issues, and works well even
|
||||
when some directory options were not specified in terms of ‘${prefix}’
|
||||
at ‘configure’ time.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving ‘configure’ the
|
||||
option ‘--program-prefix=PREFIX’ or ‘--program-suffix=SUFFIX’.
|
||||
|
||||
Some packages pay attention to ‘--enable-FEATURE’ and
|
||||
‘--disable-FEATURE’ options to ‘configure’, where FEATURE indicates an
|
||||
optional part of the package. They may also pay attention to
|
||||
‘--with-PACKAGE’ and ‘--without-PACKAGE’ options, where PACKAGE is
|
||||
something like ‘gnu-ld’. ‘./configure --help’ should mention the
|
||||
‘--enable-...’ and ‘--with-...’ options that the package recognizes.
|
||||
|
||||
Some packages offer the ability to configure how verbose the
|
||||
execution of ‘make’ will be. For these packages, running ‘./configure
|
||||
--enable-silent-rules’ sets the default to minimal output, which can be
|
||||
overridden with ‘make V=1’; while running ‘./configure
|
||||
--disable-silent-rules’ sets the default to verbose, which can be
|
||||
overridden with ‘make V=0’.
|
||||
|
||||
Specifying a System Type
|
||||
========================
|
||||
|
||||
By default ‘configure’ builds for the current system. To create
|
||||
binaries that can run on a different system type, specify a
|
||||
‘--host=TYPE’ option along with compiler variables that specify how to
|
||||
generate object code for TYPE. For example, to create binaries intended
|
||||
to run on a 64-bit ARM processor:
|
||||
|
||||
./configure --host=aarch64-linux-gnu \
|
||||
CC=aarch64-linux-gnu-gcc \
|
||||
CXX=aarch64-linux-gnu-g++
|
||||
|
||||
If done on a machine that can execute these binaries (e.g., via
|
||||
‘qemu-aarch64’, ‘$QEMU_LD_PREFIX’, and Linux’s ‘binfmt_misc’
|
||||
capability), the build behaves like a native build. Otherwise it is a
|
||||
cross-build: ‘configure’ will make cross-compilation guesses instead of
|
||||
running test programs, and ‘make check’ will not work.
|
||||
|
||||
A system type can either be a short name like ‘mingw64’, or a
|
||||
canonical name like ‘x86_64-pc-linux-gnu’. Canonical names have the
|
||||
form CPU-COMPANY-SYSTEM where SYSTEM is either OS or KERNEL-OS. To
|
||||
canonicalize and validate a system type, you can run the command
|
||||
‘config.sub’, which is often squirreled away in a subdirectory like
|
||||
‘build-aux’. For example:
|
||||
|
||||
$ build-aux/config.sub arm64-linux
|
||||
aarch64-unknown-linux-gnu
|
||||
$ build-aux/config.sub riscv-lnx
|
||||
Invalid configuration 'riscv-lnx': OS 'lnx' not recognized
|
||||
|
||||
You can look at the ‘config.sub’ file to see which types are recognized.
|
||||
If the file is absent, this package does not need the system type.
|
||||
|
||||
If ‘configure’ fails with the diagnostic “cannot guess build type”.
|
||||
‘config.sub’ did not recognize your system’s type. In this case, first
|
||||
fetch the newest versions of these files from the GNU config package
|
||||
(https://savannah.gnu.org/projects/config). If that fixes things,
|
||||
please report it to the maintainers of the package containing
|
||||
‘configure’. Otherwise, you can try the configure option ‘--build=TYPE’
|
||||
where TYPE comes close to your system type; also, please report the
|
||||
problem to <config-patches@gnu.org>.
|
||||
|
||||
For more details about configuring system types, see the Autoconf
|
||||
documentation.
|
||||
|
||||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for ‘configure’ scripts to share,
|
||||
you can create a site shell script called ‘config.site’ that gives
|
||||
default values for variables like ‘CC’, ‘cache_file’, and ‘prefix’.
|
||||
‘configure’ looks for ‘PREFIX/share/config.site’ if it exists, then
|
||||
‘PREFIX/etc/config.site’ if it exists. Or, you can set the
|
||||
‘CONFIG_SITE’ environment variable to the location of the site script.
|
||||
A warning: not all ‘configure’ scripts look for a site script.
|
||||
|
||||
Defining Variables
|
||||
==================
|
||||
|
||||
Variables not defined in a site shell script can be set in the
|
||||
environment passed to ‘configure’. However, some packages may run
|
||||
configure again during the build, and the customized values of these
|
||||
variables may be lost. In order to avoid this problem, you should set
|
||||
them in the ‘configure’ command line, using ‘VAR=value’. For example:
|
||||
|
||||
./configure CC=/usr/local2/bin/gcc
|
||||
|
||||
causes the specified ‘gcc’ to be used as the C compiler (unless it is
|
||||
overridden in the site shell script).
|
||||
|
||||
Unfortunately, this technique does not work for ‘CONFIG_SHELL’ due to an
|
||||
Autoconf limitation. Until the limitation is lifted, you can use this
|
||||
workaround:
|
||||
|
||||
CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||
|
||||
‘configure’ Invocation
|
||||
======================
|
||||
|
||||
‘configure’ recognizes the following options to control how it
|
||||
operates.
|
||||
|
||||
‘--help’
|
||||
‘-h’
|
||||
Print a summary of all of the options to ‘configure’, and exit.
|
||||
|
||||
‘--help=short’
|
||||
‘--help=recursive’
|
||||
Print a summary of the options unique to this package’s
|
||||
‘configure’, and exit. The ‘short’ variant lists options used only
|
||||
in the top level, while the ‘recursive’ variant lists options also
|
||||
present in any nested packages.
|
||||
|
||||
‘--version’
|
||||
‘-V’
|
||||
Print the version of Autoconf used to generate the ‘configure’
|
||||
script, and exit.
|
||||
|
||||
‘--cache-file=FILE’
|
||||
Enable the cache: use and save the results of the tests in FILE,
|
||||
traditionally ‘config.cache’. FILE defaults to ‘/dev/null’ to
|
||||
disable caching.
|
||||
|
||||
‘--config-cache’
|
||||
‘-C’
|
||||
Alias for ‘--cache-file=config.cache’.
|
||||
|
||||
‘--srcdir=DIR’
|
||||
Look for the package’s source code in directory DIR. Usually
|
||||
‘configure’ can determine that directory automatically.
|
||||
|
||||
‘--prefix=DIR’
|
||||
Use DIR as the installation prefix. See “Installation Names” for
|
||||
more details, including other options available for fine-tuning the
|
||||
installation locations.
|
||||
|
||||
‘--host=TYPE’
|
||||
Build binaries for system TYPE. See “Specifying a System Type”.
|
||||
|
||||
‘--enable-FEATURE’
|
||||
‘--disable-FEATURE’
|
||||
Enable or disable the optional FEATURE. See “Optional Features”.
|
||||
|
||||
‘--with-PACKAGE’
|
||||
‘--without-PACKAGE’
|
||||
Use or omit PACKAGE when building. See “Optional Features”.
|
||||
|
||||
‘--quiet’
|
||||
‘--silent’
|
||||
‘-q’
|
||||
Do not print messages saying which checks are being made. To
|
||||
suppress all normal output, redirect it to ‘/dev/null’ (any error
|
||||
messages will still be shown).
|
||||
|
||||
‘--no-create’
|
||||
‘-n’
|
||||
Run the configure checks, but stop before creating any output
|
||||
files.
|
||||
|
||||
‘configure’ also recognizes several environment variables, and accepts
|
||||
some other, less widely useful, options. Run ‘configure --help’ for
|
||||
more details.
|
||||
|
||||
Copyright notice
|
||||
================
|
||||
|
||||
Copyright © 1994–1996, 1999–2002, 2004–2017, 2020–2025 Free Software
|
||||
Foundation, Inc.
|
||||
|
||||
Copying and distribution of this file, with or without modification,
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
notice and this notice are preserved. This file is offered as-is,
|
||||
without warranty of any kind.
|
||||
|
||||
27
Makefile.am
27
Makefile.am
@@ -1,34 +1,53 @@
|
||||
AM_CFLAGS = -Wall -Wextra
|
||||
|
||||
bin_PROGRAMS = \
|
||||
sbin_PROGRAMS = \
|
||||
ipx_configure \
|
||||
ipx_interface \
|
||||
ipx_internal_net \
|
||||
ipx_route
|
||||
ipx_route \
|
||||
ipx_cmd \
|
||||
ipxdump \
|
||||
ipxparse
|
||||
|
||||
ipx_configure_SOURCES = \
|
||||
src/ipx_configure.c
|
||||
|
||||
ipx_interface_SOURCES = \
|
||||
src/ipxutil.c \
|
||||
src/ipx_interface.c
|
||||
|
||||
ipx_internal_net_SOURCES = \
|
||||
src/ipxutil.c \
|
||||
src/ipx_internal_net.c
|
||||
|
||||
ipx_route_SOURCES = \
|
||||
src/ipxutil.c \
|
||||
src/ipx_route.c
|
||||
|
||||
ipx_cmd_SOURCES = \
|
||||
src/ipx_cmd.c
|
||||
|
||||
ipxdump_SOURCES = \
|
||||
tools/ipxutil.c \
|
||||
tools/ipxdump.c
|
||||
|
||||
ipxparse_SOURCES = \
|
||||
tools/ipxutil.c \
|
||||
tools/ipxparse.c
|
||||
|
||||
man_MANS = \
|
||||
docs/ipx_configure.8 \
|
||||
docs/ipx_interface.8 \
|
||||
docs/ipx_internal_net.8 \
|
||||
docs/ipx_route.8
|
||||
docs/ipx_route.8 \
|
||||
docs/ipx_cmd.8
|
||||
|
||||
samples_files = \
|
||||
Samples/ipxrcv.c \
|
||||
Samples/ipxsend.c \
|
||||
Samples/rip.c \
|
||||
Samples/sap.c
|
||||
Samples/sap.c \
|
||||
Samples/samples.h
|
||||
|
||||
EXTRA_DIST = \
|
||||
$(man_MANS) \
|
||||
|
||||
45
README
45
README
@@ -68,3 +68,48 @@ There are three files in /proc/net/ipx that relate to IPX:
|
||||
interface contains the list of IPX interfaces.
|
||||
route contains the list of IPX routes.
|
||||
socket the list of IPX sockets in use.
|
||||
This is a VERY stupid packet sniffer for IPX ethernet packets.
|
||||
|
||||
=============================================
|
||||
! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
|
||||
! ! ! S E C U R I T Y W A R N I N G ! ! !
|
||||
! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
|
||||
=============================================
|
||||
|
||||
If you are using unencrypted passwords, and use this tool to send a
|
||||
dump to somebody else or store it on a computer, you might very well
|
||||
store passwords there. So, be VERY careful! This is exactly the kind
|
||||
of tools Novell designed the encrypted passwords for (or against).
|
||||
|
||||
|
||||
|
||||
I hacked it together to be able to help people with problems with
|
||||
ncpfs. The socket handling was taken from Statnet-2.0.
|
||||
|
||||
You can use it to watch commercial NetWare clients when they talk to
|
||||
servers. I divided the program into 2 parts, ipxdump and ipxparse.
|
||||
|
||||
ipxdump simply pumps all the IPX frames it receives to stdout.
|
||||
|
||||
If you use ipxdump to watch a workstation, you can use the simple
|
||||
filter function ipxdump provides. You can call ipxdump with the node
|
||||
address of the workstation you want to watch. This way only the
|
||||
packets this workstation sends and receives are monitored. As an
|
||||
example, I call ipxdump as
|
||||
|
||||
./ipxdump 00001B038B11
|
||||
|
||||
to look at my 286/10MHz test 'workstation'. ipxdump still generates
|
||||
huge amounts of data, so you should be very careful to start it just
|
||||
before you perform the operation (such as file creation for OS/2
|
||||
clients with NW4.1 as a server, or a 'dir' on a directory with long
|
||||
and short file names, or an encrypted password change ;-)) and stop it
|
||||
directly after that. And, please gzip -9 and uuencode it before you
|
||||
send it to anybody.
|
||||
|
||||
ipxparse will eventually take apart the dump that ipxdump
|
||||
generates. They can as well be used in a pipe. Currently ipxparse does
|
||||
not do anything sensible, but that will definitely change.
|
||||
|
||||
Volker Lendecke
|
||||
<lendecke@namu01.gwdg.de>
|
||||
@@ -1,22 +1,16 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <netipx/ipx.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
#include "samples.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct sockaddr_ipx sipx;
|
||||
int s;
|
||||
int rc;
|
||||
char msg[100];
|
||||
int len;
|
||||
struct sockaddr_ipx sipx;
|
||||
int s;
|
||||
int rct;
|
||||
char msg[100];
|
||||
socklen_t len;
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
if (s < 0)
|
||||
{
|
||||
perror("IPX: socket: ");
|
||||
exit(-1);
|
||||
}
|
||||
@@ -25,25 +19,25 @@ int main(int argc, char **argv)
|
||||
sipx.sipx_network = 0;
|
||||
sipx.sipx_port = htons(0x5000);
|
||||
sipx.sipx_type = 17;
|
||||
len = sizeof(sipx);
|
||||
rc = bind(s, (struct sockaddr *)&sipx, sizeof(sipx));
|
||||
if (rc < 0) {
|
||||
rc = bind(s, (struct sockaddr *) &sipx, sizeof(sipx));
|
||||
if (rc < 0)
|
||||
{
|
||||
perror("IPX: bind: ");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
msg[0] = '\0';
|
||||
rc = recvfrom(s, msg, sizeof(msg), 0, (struct sockaddr *)&sipx, &len);
|
||||
if (rc < 0) {
|
||||
len = sizeof(sipx);
|
||||
rc = recvfrom(s, msg, sizeof(msg), 0, (struct sockaddr *) &sipx, &len);
|
||||
if (rc < 0)
|
||||
{
|
||||
perror("IPX: recvfrom: ");
|
||||
}
|
||||
|
||||
printf("From %08lX:%02X%02X%02X%02X%02X%02X:%04X\n",
|
||||
(unsigned long)ntohl(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],
|
||||
ntohs(sipx.sipx_port));
|
||||
printf("From %08X:%02X%02X%02X%02X%02X%02X:%04X\n",
|
||||
(unsigned long)ntohl(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],
|
||||
ntohl(sipx.sipx_port));
|
||||
printf("\tGot \"%s\"\n", msg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,22 +1,16 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <netipx/ipx.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
#include "samples.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct sockaddr_ipx sipx;
|
||||
int s;
|
||||
int rc;
|
||||
char msg[100] = "Hello world!";
|
||||
int len = sizeof(sipx);
|
||||
struct sockaddr_ipx sipx;
|
||||
int s;
|
||||
int rc;
|
||||
char msg[100] = "Hello world!";
|
||||
socklen_t len = sizeof(sipx);
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
if (s < 0)
|
||||
{
|
||||
perror("IPX: socket: ");
|
||||
exit(-1);
|
||||
}
|
||||
@@ -26,13 +20,13 @@ int main(int argc, char **argv)
|
||||
sipx.sipx_port = 0;
|
||||
sipx.sipx_type = 17;
|
||||
|
||||
rc = bind(s, (struct sockaddr *)&sipx, sizeof(sipx));
|
||||
if (rc < 0) {
|
||||
rc = bind(s, (struct sockaddr *) &sipx, sizeof(sipx));
|
||||
if (rc < 0)
|
||||
{
|
||||
perror("IPX: bind: ");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
rc = getsockname(s, (struct sockaddr *)&sipx, &len);
|
||||
rc = getsockname(s, (struct sockaddr *) &sipx, &len);
|
||||
sipx.sipx_port = htons(0x5000);
|
||||
sipx.sipx_node[0] = 0xFF;
|
||||
sipx.sipx_node[1] = 0xFF;
|
||||
@@ -42,7 +36,7 @@ int main(int argc, char **argv)
|
||||
sipx.sipx_node[5] = 0xFF;
|
||||
|
||||
rc = sendto(s, msg, strlen(msg), 0, (struct sockaddr *)&sipx,
|
||||
sizeof(sipx));
|
||||
sizeof(sipx));
|
||||
if (rc < 0) {
|
||||
perror("IPX: send: ");
|
||||
exit(-1);
|
||||
|
||||
@@ -1,31 +1,24 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <netipx/ipx.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
#include "samples.h"
|
||||
|
||||
struct rip_data {
|
||||
struct rip_data
|
||||
{
|
||||
uint32_t rip_net;
|
||||
uint16_t rip_hops;
|
||||
uint16_t rip_ticks;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
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;
|
||||
struct sockaddr_ipx sipx;
|
||||
int result;
|
||||
int s;
|
||||
char msg[1024];
|
||||
char *bptr;
|
||||
struct rip_data *rp;
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
if (s < 0)
|
||||
{
|
||||
perror("IPX: socket: ");
|
||||
exit(-1);
|
||||
}
|
||||
@@ -33,33 +26,43 @@ main(int argc, char **argv)
|
||||
sipx.sipx_network = 0;
|
||||
sipx.sipx_port = htons(0x453);
|
||||
sipx.sipx_type = 17;
|
||||
result = bind(s, (struct sockaddr *)&sipx, sizeof(sipx));
|
||||
if (result < 0) {
|
||||
result = bind(s, (struct sockaddr *) &sipx, sizeof(sipx));
|
||||
if (result < 0)
|
||||
{
|
||||
perror("IPX: bind: ");
|
||||
exit(-1);
|
||||
}
|
||||
while (1)
|
||||
{
|
||||
socklen_t len;
|
||||
size_t rclen;
|
||||
|
||||
while (1) {
|
||||
len = sizeof(sipx);
|
||||
result = recvfrom(s, msg, sizeof(msg), 0,
|
||||
(struct sockaddr *)&sipx, &len);
|
||||
if (result < 0) {
|
||||
result = recvfrom(s, msg, sizeof(msg), 0,
|
||||
(struct sockaddr *) &sipx, &len);
|
||||
if (result < 0)
|
||||
{
|
||||
perror("IPX: recvfrom");
|
||||
exit(-1);
|
||||
}
|
||||
if (result < 2) {
|
||||
fprintf(stderr, "Received packet is too short to be RIP packet (%d bytes)\n", result);
|
||||
continue;
|
||||
}
|
||||
rclen = result - 2;
|
||||
bptr = msg;
|
||||
result -= 2;
|
||||
printf("RIP packet from: %08X:%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[6], sipx.sipx_node[5]);
|
||||
(u_int32_t)htonl(sipx.sipx_network),
|
||||
sipx.sipx_node[0], sipx.sipx_node[1],
|
||||
sipx.sipx_node[2], sipx.sipx_node[3],
|
||||
sipx.sipx_node[6], sipx.sipx_node[5]);
|
||||
bptr += 2;
|
||||
rp = (struct rip_data *) bptr;
|
||||
while (result >= sizeof(struct rip_data)) {
|
||||
printf("\tNET: %08X HOPS: %d\n", ntohl(rp->rip_net),
|
||||
ntohs(rp->rip_hops));
|
||||
result -= sizeof(struct rip_data);
|
||||
while (rclen >= sizeof(struct rip_data))
|
||||
{
|
||||
printf("\tNET: %08X HOPS: %d\n", (u_int32_t)ntohl(rp->rip_net),
|
||||
ntohs(rp->rip_hops));
|
||||
rclen -= sizeof(struct rip_data);
|
||||
rp++;
|
||||
}
|
||||
}
|
||||
|
||||
8
Samples/samples.h
Normal file
8
Samples/samples.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <netipx/ipx.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
103
Samples/sap.c
103
Samples/sap.c
@@ -1,93 +1,94 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <netipx/ipx.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
#include "samples.h"
|
||||
|
||||
|
||||
struct sap_data {
|
||||
uint16_t sap_type;
|
||||
char sap_name[48];
|
||||
uint32_t sap_net;
|
||||
uint8_t sap_node[6];
|
||||
uint16_t sap_sock;
|
||||
uint16_t sap_hops;
|
||||
struct sap_data
|
||||
{
|
||||
uint16_t sap_type;
|
||||
char sap_name[48];
|
||||
uint32_t sap_net;
|
||||
uint8_t sap_node[6];
|
||||
uint16_t sap_sock;
|
||||
uint16_t sap_hops;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
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;
|
||||
int s;
|
||||
int result;
|
||||
struct sockaddr_ipx sipx;
|
||||
char msg[1024];
|
||||
long val = 0;
|
||||
char *bptr;
|
||||
struct sap_data *sp;
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
if (s < 0)
|
||||
{
|
||||
perror("IPX: socket: ");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
result = setsockopt(s, SOL_SOCKET, SO_DEBUG, &val, 4);
|
||||
if (result < 0) {
|
||||
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) {
|
||||
result = bind(s, (struct sockaddr *) &sipx, sizeof(sipx));
|
||||
if (result < 0)
|
||||
{
|
||||
perror("IPX: bind: ");
|
||||
exit(-1);
|
||||
}
|
||||
while (1)
|
||||
{
|
||||
socklen_t len;
|
||||
size_t rclen;
|
||||
|
||||
while (1) {
|
||||
len = 1024;
|
||||
result = recvfrom(s, msg, sizeof(msg), 0,
|
||||
(struct sockaddr *)&sipx, &len);
|
||||
if (result < 0) {
|
||||
result = recvfrom(s, msg, sizeof(msg), 0,
|
||||
(struct sockaddr *) &sipx, &len);
|
||||
if (result < 0)
|
||||
{
|
||||
perror("IPX: recvfrom: ");
|
||||
exit(-1);
|
||||
}
|
||||
if (result < 2) {
|
||||
fprintf(stderr, "Received packet is too short to be SAP packet (%d bytes)\n", result);
|
||||
continue;
|
||||
}
|
||||
rclen = result - 2;
|
||||
bptr = msg;
|
||||
result -= 2;
|
||||
printf("SAP: OP is %x %x\n", bptr[0], bptr[1]);
|
||||
printf("Length is %d\n", result);
|
||||
printf("Length is %zu\n", rclen);
|
||||
if (bptr[1] != 2)
|
||||
continue;
|
||||
|
||||
bptr += 2;
|
||||
sp = (struct sap_data *) bptr;
|
||||
while (result >= sizeof(struct sap_data)) {
|
||||
int i;
|
||||
|
||||
while (rclen >= 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));
|
||||
ntohs(sp->sap_type), ntohs(sp->sap_hops));
|
||||
printf("%x:%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);
|
||||
(u_int32_t)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));
|
||||
rclen -= sizeof(struct sap_data);
|
||||
sp++;
|
||||
}
|
||||
}
|
||||
|
||||
73
config.h
Normal file
73
config.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/* config.h. Generated from config.h.in by configure. */
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define to 1 if you have the 'bindtextdomain' function. */
|
||||
#define HAVE_BINDTEXTDOMAIN 1
|
||||
|
||||
/* Define to 1 if you have the 'gettext' function. */
|
||||
#define HAVE_GETTEXT 1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <libintl.h> header file. */
|
||||
#define HAVE_LIBINTL_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdio.h> header file. */
|
||||
#define HAVE_STDIO_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the 'textdomain' function. */
|
||||
#define HAVE_TEXTDOMAIN 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Define location of message catalogs */
|
||||
#define LOCALEDIR "/usr/share/locale"
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "ipx-utils"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT "pasis.ua@gmail.com"
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME "ipx-utils"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "ipx-utils 1.2"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "ipx-utils"
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#define PACKAGE_URL ""
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "1.2"
|
||||
|
||||
/* Define to 1 if all of the C89 standard headers exist (not just the ones
|
||||
required in a freestanding environment). This macro is provided for
|
||||
backward compatibility; new code need not use it. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "1.2"
|
||||
72
config.h.in
Normal file
72
config.h.in
Normal file
@@ -0,0 +1,72 @@
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define to 1 if you have the 'bindtextdomain' function. */
|
||||
#undef HAVE_BINDTEXTDOMAIN
|
||||
|
||||
/* Define to 1 if you have the 'gettext' function. */
|
||||
#undef HAVE_GETTEXT
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the <libintl.h> header file. */
|
||||
#undef HAVE_LIBINTL_H
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdio.h> header file. */
|
||||
#undef HAVE_STDIO_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the 'textdomain' function. */
|
||||
#undef HAVE_TEXTDOMAIN
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define location of message catalogs */
|
||||
#undef LOCALEDIR
|
||||
|
||||
/* Name of package */
|
||||
#undef PACKAGE
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#undef PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#undef PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#undef PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* Define to 1 if all of the C89 standard headers exist (not just the ones
|
||||
required in a freestanding environment). This macro is provided for
|
||||
backward compatibility; new code need not use it. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Version number of package */
|
||||
#undef VERSION
|
||||
72
config.h.in~
Normal file
72
config.h.in~
Normal file
@@ -0,0 +1,72 @@
|
||||
/* config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Define to 1 if you have the 'bindtextdomain' function. */
|
||||
#undef HAVE_BINDTEXTDOMAIN
|
||||
|
||||
/* Define to 1 if you have the 'gettext' function. */
|
||||
#undef HAVE_GETTEXT
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the <libintl.h> header file. */
|
||||
#undef HAVE_LIBINTL_H
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdio.h> header file. */
|
||||
#undef HAVE_STDIO_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have the 'textdomain' function. */
|
||||
#undef HAVE_TEXTDOMAIN
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define location of message catalogs */
|
||||
#undef LOCALEDIR
|
||||
|
||||
/* Name of package */
|
||||
#undef PACKAGE
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#undef PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#undef PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#undef PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* Define to 1 if all of the C89 standard headers exist (not just the ones
|
||||
required in a freestanding environment). This macro is provided for
|
||||
backward compatibility; new code need not use it. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Version number of package */
|
||||
#undef VERSION
|
||||
21
configure.ac
21
configure.ac
@@ -1,8 +1,29 @@
|
||||
|
||||
dnl Define a config.h string from a configure directory variable.
|
||||
AC_DEFUN([AC_DEFINE_DIR], [
|
||||
prefix_NONE=
|
||||
exec_prefix_NONE=
|
||||
test "x$prefix" = xNONE && prefix_NONE=yes && prefix=$ac_default_prefix
|
||||
test "x$exec_prefix" = xNONE && exec_prefix_NONE=yes && exec_prefix=$prefix
|
||||
ac_define_dir=`eval echo [$]$2`
|
||||
ac_define_dir=`eval echo [$]ac_define_dir`
|
||||
AC_DEFINE_UNQUOTED([$1], ["$ac_define_dir"], [$3])
|
||||
test "$prefix_NONE" && prefix=NONE
|
||||
test "$exec_prefix_NONE" && exec_prefix=NONE
|
||||
])
|
||||
|
||||
AC_INIT([ipx-utils], [1.2], [pasis.ua@gmail.com])
|
||||
AM_INIT_AUTOMAKE([subdir-objects])
|
||||
AC_CONFIG_SRCDIR([src/ipx_configure.c])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
|
||||
AC_CONFIG_FILES([Makefile])
|
||||
|
||||
AC_CHECK_HEADERS([libintl.h])
|
||||
AC_SEARCH_LIBS([gettext], [intl])
|
||||
AC_CHECK_FUNCS([gettext bindtextdomain textdomain])
|
||||
AC_DEFINE_DIR([LOCALEDIR], [localedir], [Define location of message catalogs])
|
||||
|
||||
AC_PROG_CC
|
||||
AM_PROG_CC_C_O
|
||||
|
||||
|
||||
7195
configure~
Executable file
7195
configure~
Executable file
File diff suppressed because it is too large
Load Diff
45
docs/ipx_cmd.8
Normal file
45
docs/ipx_cmd.8
Normal file
@@ -0,0 +1,45 @@
|
||||
.TH IPX_CMD 8 "IPX Utilities" "ipx_cmd"
|
||||
.SH NAME
|
||||
ipx_cmd \- bridge between Novell's SCMD driver and local IPX network
|
||||
.SH SYNOPSIS
|
||||
.B ipx_cmd
|
||||
\fB\-A\fP \fIserver name\fP
|
||||
[ \fB\-l\fP \fIlocal interface name\fP ]
|
||||
.SH DESCRIPTION
|
||||
.B ipx_cmd
|
||||
moves packets from \fItap\fP\fBN\fP to \fIserver\fP and vice versa.
|
||||
It is something like \fBIPX Tunnel\fP, but it uses Novell Netware 5
|
||||
server \fBCompatibility Mode Driver\fP (AKA \fBMigration Agent\fP) on the
|
||||
other end of wire. You must first configure your kernel \fItap\fP\fBN\fP
|
||||
device with IPX \fBEthernetII\fP frame and with network number set up on
|
||||
server (you can use kernel autodetection).
|
||||
.SH OPTIONS
|
||||
.TP
|
||||
\fB\-A\fP \fIserver name\fP
|
||||
This is IP name of compatibility mode server. You can use DNS name or dotted
|
||||
quad to specify server address.
|
||||
.TP
|
||||
\fB\-l\fP \fIlocal interface name\fP
|
||||
This allows you to specify, which of your IP addresses should be used as
|
||||
IP address of client side of CMD driver. You must configure your \fItap\fP\fBN\fP
|
||||
device with hardware address \fB7E:01:AA:BB:CC:DD\fP, where AA:BB:CC:DD is
|
||||
your IP address in hexa.
|
||||
.SH EXAMPLE
|
||||
If you are on server \fIplatan.vc.cvut.cz\fP (\fI147.32.240.81\fP) and your
|
||||
migration agent runs on server \fIboris.vc.cvut.cz\fP, you can configure
|
||||
your system with:
|
||||
|
||||
.RS 3
|
||||
insmod ethertap
|
||||
.br
|
||||
ifconfig tap0 hw ether 7E:01:93:20:F0:51 up
|
||||
.br
|
||||
ipx_interface add -p tap0 EtherII
|
||||
.br
|
||||
ipx_cmd -A boris.vc.cvut.cz -l 147.32.240.81 &
|
||||
.RE
|
||||
.SH BUGS
|
||||
This program was written to satisfy my own needs and should be really improved.
|
||||
At least it should configure \fItap\fP interface itself.
|
||||
.SH AUTHOR
|
||||
Petr Vandrovec <vandrove@vc.cvut.cz>
|
||||
423
src/ipx_cmd.c
Normal file
423
src/ipx_cmd.c
Normal file
@@ -0,0 +1,423 @@
|
||||
/*
|
||||
ipx_cmd.c - IPX Compatibility mode tunnel
|
||||
Copyright (C) 1999 Petr Vandrovec
|
||||
|
||||
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Revision history:
|
||||
|
||||
0.00 1999 Petr Vandrovec <vandrove@vc.cvut.cz>
|
||||
Initial revision.
|
||||
|
||||
1.00 1999, November 20 Petr Vandrovec <vandrove@vc.cvut.cz>
|
||||
Added license.
|
||||
|
||||
1.01 2001, June 16 Petr Vandrovec <vandrove@vc.cvut.cz>
|
||||
Cleanup some compilation warnings.
|
||||
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/types.h>
|
||||
#include <ncp/ext/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <netdb.h>
|
||||
#include <net/if_arp.h> /* TODO: linux/if_arp.h */
|
||||
#include <ncp/kernel/ipx.h>
|
||||
#include <ncp/kernel/if.h>
|
||||
#include <ncp/kernel/types.h>
|
||||
#include "netlink.h"
|
||||
|
||||
#include "nls.h"
|
||||
#define _(X) gettext(X)
|
||||
|
||||
#define NOVELL_SCMD_PORT (2645)
|
||||
|
||||
/* Move them to configure... */
|
||||
#ifndef AF_NETLINK
|
||||
#define AF_NETLINK 16
|
||||
#endif
|
||||
#ifndef PF_NETLINK
|
||||
#define PF_NETLINK AF_NETLINK
|
||||
#endif
|
||||
|
||||
/* we are doing EthernetII... Any objections? */
|
||||
struct {
|
||||
u_int16_t unknown __attribute__((packed));
|
||||
u_int8_t dst[6];
|
||||
u_int8_t src[6];
|
||||
u_int16_t type __attribute__((packed));
|
||||
u_int8_t ipx[16384];
|
||||
} __attribute__((packed)) buffer;
|
||||
|
||||
static int getiflist(int fd, struct ifconf* ifc) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
int err;
|
||||
|
||||
ifc->ifc_len = 65536; /* ignored */
|
||||
ifc->ifc_req = NULL;
|
||||
|
||||
err = ioctl(fd, SIOCGIFCONF, ifc);
|
||||
if (err < 0)
|
||||
continue;
|
||||
|
||||
if (!ifc->ifc_len)
|
||||
return 0;
|
||||
|
||||
ifc->ifc_req = (struct ifreq*)malloc(ifc->ifc_len);
|
||||
err = ioctl(fd, SIOCGIFCONF, ifc);
|
||||
if (!err)
|
||||
return 0;
|
||||
free(ifc->ifc_buf);
|
||||
}
|
||||
ifc->ifc_len = 0;
|
||||
ifc->ifc_req = NULL;
|
||||
return errno;
|
||||
}
|
||||
|
||||
static char* progname;
|
||||
|
||||
static int findtap(int fd_ipx, u_int32_t local) {
|
||||
int i;
|
||||
u_int8_t localhw[6];
|
||||
|
||||
localhw[0] = 0x7E;
|
||||
localhw[1] = 0x01;
|
||||
memcpy(localhw+2, &local, 4);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
struct ifreq ifr;
|
||||
int err;
|
||||
|
||||
sprintf(ifr.ifr_name, "tap%d", i);
|
||||
((struct sockaddr_ipx*)&ifr.ifr_addr)->sipx_type = IPX_FRAME_ETHERII;
|
||||
err = ioctl(fd_ipx, SIOCGIFHWADDR, &ifr);
|
||||
if (err >= 0) {
|
||||
if ((ifr.ifr_addr.sa_family == ARPHRD_ETHER) && !memcmp(ifr.ifr_addr.sa_data, localhw, 6)) {
|
||||
err = ioctl(fd_ipx, SIOCGIFADDR, &ifr);
|
||||
if (err >= 0) {
|
||||
if (!memcmp(((struct sockaddr_ipx*)&ifr.ifr_addr)->sipx_node, localhw, 6)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
static void usage(void) {
|
||||
fprintf(stderr, _("usage: %s -A migration_agent [-l local_ip]\n"), progname);
|
||||
return;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
int fd_ip;
|
||||
struct sockaddr_in localIP;
|
||||
int status;
|
||||
int fd_netlink;
|
||||
struct sockaddr_nl localNET;
|
||||
int arg;
|
||||
int maxfd;
|
||||
fd_set rcvset;
|
||||
int opt;
|
||||
char *server = NULL;
|
||||
struct hostent* hent;
|
||||
u_int32_t serveraddr;
|
||||
u_int32_t local = htonl(INADDR_ANY);
|
||||
int local_ok;
|
||||
struct ifconf ifc;
|
||||
struct ifreq* curr;
|
||||
struct ifreq* stop;
|
||||
int tapnum;
|
||||
int fd_ipx;
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
textdomain(PACKAGE);
|
||||
|
||||
{
|
||||
char* i;
|
||||
|
||||
i = strrchr(argv[0], '/');
|
||||
progname = i?i+1:argv[0];
|
||||
}
|
||||
|
||||
while ((opt = getopt(argc, argv, "A:l:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'A':
|
||||
server = optarg;
|
||||
break;
|
||||
case 'l':
|
||||
{
|
||||
hent = gethostbyname(optarg);
|
||||
if (!hent) {
|
||||
fprintf(stderr, _("%s: %s: "),
|
||||
progname,
|
||||
optarg);
|
||||
herror("");
|
||||
exit(99);
|
||||
}
|
||||
if (hent->h_addrtype != AF_INET) {
|
||||
fprintf(stderr, _("%s: Address of %s is not IP\n"),
|
||||
progname,
|
||||
optarg);
|
||||
exit(99);
|
||||
}
|
||||
if (hent->h_length != 4) {
|
||||
fprintf(stderr, _("%s: Address of %s is not 4 bytes long\n"),
|
||||
progname,
|
||||
optarg);
|
||||
exit(99);
|
||||
}
|
||||
memcpy(&local, hent->h_addr, 4);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
exit(99);
|
||||
}
|
||||
}
|
||||
|
||||
if (!server) {
|
||||
usage();
|
||||
exit(99);
|
||||
}
|
||||
|
||||
hent = gethostbyname(server);
|
||||
if (!hent) {
|
||||
fprintf(stderr, _("%s: %s: "),
|
||||
progname,
|
||||
server);
|
||||
herror("");
|
||||
exit(99);
|
||||
}
|
||||
if (hent->h_addrtype != AF_INET) {
|
||||
fprintf(stderr, _("%s: Address of %s is not IP\n"),
|
||||
progname,
|
||||
server);
|
||||
exit(99);
|
||||
}
|
||||
if (hent->h_length != 4) {
|
||||
fprintf(stderr, _("%s: Address of %s is not 4 bytes long\n"),
|
||||
progname,
|
||||
server);
|
||||
exit(99);
|
||||
}
|
||||
memcpy(&serveraddr, hent->h_addr, 4);
|
||||
|
||||
fd_ip = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (fd_ip == -1) {
|
||||
int err = errno;
|
||||
fprintf(stderr, _("%s: Cannot create UDP/IP socket: %s\n"),
|
||||
progname,
|
||||
strerror(err));
|
||||
return 1;
|
||||
}
|
||||
|
||||
status = getiflist(fd_ip, &ifc);
|
||||
if (status) {
|
||||
close(fd_ip);
|
||||
fprintf(stderr, _("%s: Cannot get list of local interfaces: %s\n"),
|
||||
progname,
|
||||
strerror(status));
|
||||
return 1;
|
||||
}
|
||||
curr = ifc.ifc_req;
|
||||
stop = (struct ifreq*)(((u_int8_t*)curr) + ifc.ifc_len);
|
||||
|
||||
local_ok = 0;
|
||||
while (curr < stop) {
|
||||
if (curr->ifr_addr.sa_family == AF_INET) {
|
||||
u_int32_t net = ((struct sockaddr_in*)&curr->ifr_addr)->sin_addr.s_addr;
|
||||
if (((ntohl(net) & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT) != IN_LOOPBACKNET) {
|
||||
if (local == htonl(INADDR_ANY))
|
||||
local = net;
|
||||
if (local == net)
|
||||
local_ok = 1;
|
||||
}
|
||||
}
|
||||
curr++;
|
||||
}
|
||||
free(ifc.ifc_req);
|
||||
if (!local_ok) {
|
||||
close(fd_ip);
|
||||
fprintf(stderr, _("%s: Cannot find local requested address\n"),
|
||||
progname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* TBD: enable SO_REUSEADDR? */
|
||||
localIP.sin_family = AF_INET;
|
||||
localIP.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
localIP.sin_port = htons(NOVELL_SCMD_PORT);
|
||||
status = bind(fd_ip, (struct sockaddr*)&localIP, sizeof(localIP));
|
||||
if (status) {
|
||||
int err = errno;
|
||||
close(fd_ip);
|
||||
fprintf(stderr, _("%s: Cannot bind requested address to IP socket: %s\n"),
|
||||
progname,
|
||||
strerror(err));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* OK, we have local IP address... Now find appropriate tap device */
|
||||
fd_ipx = socket(PF_IPX, SOCK_DGRAM, IPXPROTO_IPX);
|
||||
if (fd_ipx < 0) {
|
||||
int err = errno;
|
||||
close(fd_ip);
|
||||
fprintf(stderr, _("%s: Cannot create IPX socket: %s\n"),
|
||||
progname,
|
||||
strerror(err));
|
||||
return 1;
|
||||
}
|
||||
tapnum = findtap(fd_ipx, local);
|
||||
if (tapnum < 0) {
|
||||
close(fd_ipx);
|
||||
close(fd_ip);
|
||||
fprintf(stderr, _("%s: Cannot find ethertap interface: %s\n"),
|
||||
progname,
|
||||
strerror(-tapnum));
|
||||
return 1;
|
||||
}
|
||||
close(fd_ipx);
|
||||
|
||||
fd_netlink = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_TAPBASE+tapnum);
|
||||
if (fd_netlink == -1) {
|
||||
int err = errno;
|
||||
close(fd_ip);
|
||||
fprintf(stderr, _("%s: Cannot create NETLINK socket: %s\n"),
|
||||
progname,
|
||||
strerror(err));
|
||||
return 1;
|
||||
}
|
||||
localNET.nl_family = AF_NETLINK;
|
||||
localNET.nl_pid = serveraddr;
|
||||
localNET.nl_groups = ~0;
|
||||
status = bind(fd_netlink, (struct sockaddr*)&localNET, sizeof(localNET));
|
||||
if (status) {
|
||||
int err = errno;
|
||||
close(fd_netlink);
|
||||
close(fd_ip);
|
||||
fprintf(stderr, _("%s: Cannot bind requested address to NETLINK socket: %s\n"),
|
||||
progname,
|
||||
strerror(err));
|
||||
return 1;
|
||||
}
|
||||
arg = fcntl(fd_ip, F_GETFL);
|
||||
fcntl(fd_ip, F_SETFL, arg | O_NONBLOCK);
|
||||
arg = fcntl(fd_netlink, F_GETFL);
|
||||
fcntl(fd_netlink, F_SETFL, arg | O_NONBLOCK);
|
||||
maxfd = fd_ip;
|
||||
if (fd_netlink > maxfd)
|
||||
maxfd = fd_netlink;
|
||||
FD_ZERO(&rcvset);
|
||||
|
||||
printf("Running...\n");
|
||||
|
||||
while (1) {
|
||||
FD_SET(fd_ip, &rcvset);
|
||||
FD_SET(fd_netlink, &rcvset);
|
||||
status = select(maxfd+1, &rcvset, NULL, NULL, NULL);
|
||||
if (status > 0) {
|
||||
if (FD_ISSET(fd_ip, &rcvset)) {
|
||||
struct sockaddr_in remoteIP;
|
||||
socklen_t remoteIPlen = sizeof(remoteIP);
|
||||
status = recvfrom(fd_ip, buffer.ipx, sizeof(buffer.ipx), 0, (struct sockaddr*)&remoteIP, &remoteIPlen);
|
||||
if (status > 0) {
|
||||
if (remoteIP.sin_port != htons(NOVELL_SCMD_PORT)) {
|
||||
/* invalid source port... faked? */
|
||||
} else if (remoteIP.sin_addr.s_addr != serveraddr) {
|
||||
/* invalid server... faked? */
|
||||
} else if (status < 2 + 2 + 1 + 1 + 12 + 12) {
|
||||
/* too short... */
|
||||
} else {
|
||||
int ipxLen = ntohs(*(u_int16_t*)(buffer.ipx+2));
|
||||
if (ipxLen > status) {
|
||||
/* too big... */
|
||||
} else {
|
||||
/* looks OK... */
|
||||
status += 2 + 6 + 6 + 2;
|
||||
|
||||
buffer.unknown = 0;
|
||||
buffer.type = htons(0x8137);
|
||||
buffer.src[0] = 0x7E;
|
||||
buffer.src[1] = 0x01;
|
||||
memcpy(buffer.src+2, &remoteIP.sin_addr.s_addr, 4);
|
||||
buffer.dst[0] = 0x7E;
|
||||
buffer.dst[1] = 0x01;
|
||||
memcpy(buffer.dst+2, &local, 4);
|
||||
{
|
||||
struct sockaddr_nl remoteNETLINK;
|
||||
int e;
|
||||
|
||||
remoteNETLINK.nl_family = AF_NETLINK;
|
||||
remoteNETLINK.nl_pid = 0;
|
||||
remoteNETLINK.nl_groups = 0;
|
||||
e = sendto(fd_netlink, &buffer, status, 0, (struct sockaddr*)&remoteNETLINK, sizeof(remoteNETLINK));
|
||||
if (e < 0)
|
||||
sendto(fd_netlink, &buffer, status, 0, (struct sockaddr*)&remoteNETLINK, sizeof(remoteNETLINK));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (FD_ISSET(fd_netlink, &rcvset)) {
|
||||
struct sockaddr_in remoteNETLINK;
|
||||
socklen_t remoteNETLINKlen = sizeof(remoteNETLINK);
|
||||
status = recvfrom(fd_netlink, &buffer, sizeof(buffer), 0, (struct sockaddr*)&remoteNETLINK, &remoteNETLINKlen);
|
||||
if (status > 0) {
|
||||
if (status < 2 + 6 + 6 + 2 + 2 + 2 + 1 + 1 + 12 + 12) {
|
||||
/* too short... faked? */
|
||||
} else if (buffer.type != htons(0x8137)) {
|
||||
/* invalid frame */
|
||||
} else {
|
||||
int ipxLen = ntohs(*(u_int16_t*)(buffer.ipx+2));
|
||||
status -= 2 + 6 + 6 + 2;
|
||||
if (ipxLen > status) {
|
||||
/* too big... */
|
||||
} else {
|
||||
/* looks OK... */
|
||||
{
|
||||
struct sockaddr_in remoteIP;
|
||||
int e;
|
||||
|
||||
remoteIP.sin_family = AF_INET;
|
||||
remoteIP.sin_addr.s_addr = serveraddr;
|
||||
remoteIP.sin_port = htons(NOVELL_SCMD_PORT);
|
||||
e = sendto(fd_ip, buffer.ipx, status, 0, (struct sockaddr*)&remoteIP, sizeof(remoteIP));
|
||||
if (e < 0)
|
||||
sendto(fd_ip, buffer.ipx, status, 0, (struct sockaddr*)&remoteIP, sizeof(remoteIP));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
close(fd_netlink);
|
||||
close(fd_ip);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,131 +1,168 @@
|
||||
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
|
||||
*
|
||||
|
||||
* See file COPYING for details.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <getopt.h> /* must be before stdio/unistd, otherwise multiple declaration warning is shown */
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <getopt.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <netipx/ipx.h>
|
||||
#include <string.h>
|
||||
#include <ncp/kernel/ipx.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include "nls.h"
|
||||
|
||||
struct option options[] = {
|
||||
{ "auto_primary", required_argument, NULL, 1 },
|
||||
{ "auto_interface", required_argument, NULL, 2 },
|
||||
{ "help", no_argument, NULL, 3},
|
||||
{ NULL, 0, NULL, 0 }
|
||||
struct option options[] =
|
||||
{
|
||||
{ "auto_primary", required_argument, NULL, 'p'},
|
||||
{ "auto-primary", required_argument, NULL, 'p'},
|
||||
{ "auto_interface", required_argument, NULL, 'i'},
|
||||
{ "auto-interface", required_argument, NULL, 'i'},
|
||||
{ "help", no_argument, NULL, 'h'},
|
||||
{ NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
char *progname;
|
||||
static char *progname;
|
||||
|
||||
void
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: %s --auto_primary=[on|off]\n\
|
||||
Usage: %s --auto_interface=[on|off]\n\
|
||||
Usage: %s --help\n\
|
||||
Usage: %s\n", progname, progname, progname, progname);
|
||||
fprintf(stderr,
|
||||
_("Usage: %s --auto_primary=[on|off]\n"
|
||||
"Usage: %s --auto_interface=[on|off]\n"
|
||||
"Usage: %s --help\n"
|
||||
"Usage: %s\n"), progname, progname, progname, progname);
|
||||
}
|
||||
|
||||
int
|
||||
map_string_to_bool(char *optarg)
|
||||
static int
|
||||
map_string_to_bool(char *opt)
|
||||
{
|
||||
if ((strcasecmp(optarg, "ON") == 0) ||
|
||||
(strcasecmp(optarg, "TRUE") == 0) ||
|
||||
(strcasecmp(optarg, "SET") == 0) ||
|
||||
(strcasecmp(optarg, "YES") == 0)) {
|
||||
/* TODO: YES/NO VALUE FROM LIBC */
|
||||
if ((strcasecmp(opt, "ON") == 0) ||
|
||||
(strcasecmp(opt, "TRUE") == 0) ||
|
||||
(strcasecmp(opt, "SET") == 0) ||
|
||||
(strcasecmp(opt, "YES") == 0) ||
|
||||
(strcasecmp(opt, "1") == 0))
|
||||
{
|
||||
return 1;
|
||||
} else if ((strcasecmp(optarg, "OFF") == 0) ||
|
||||
(strcasecmp(optarg, "FALSE") == 0) ||
|
||||
(strcasecmp(optarg, "CLEAR") == 0) ||
|
||||
(strcasecmp(optarg, "NO") == 0)) {
|
||||
} else if ((strcasecmp(opt, "OFF") == 0) ||
|
||||
(strcasecmp(opt, "FALSE") == 0) ||
|
||||
(strcasecmp(opt, "CLEAR") == 0) ||
|
||||
(strcasecmp(opt, "NO") == 0) ||
|
||||
(strcasecmp(opt, "0") == 0))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int s;
|
||||
int result;
|
||||
char errmsg[80];
|
||||
char val;
|
||||
int option_index = 0;
|
||||
int got_auto_pri = 0;
|
||||
int got_auto_itf = 0;
|
||||
ipx_config_data data;
|
||||
int s;
|
||||
int result;
|
||||
int val;
|
||||
int got_auto_pri = 0;
|
||||
int got_auto_itf = 0;
|
||||
ipx_config_data data;
|
||||
|
||||
progname = argv[0];
|
||||
setlocale(LC_ALL, "");
|
||||
#if defined(HAVE_BINDTEXTDOMAIN) && defined(HAVE_TEXTDOMAIN)
|
||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
textdomain(PACKAGE);
|
||||
#endif
|
||||
|
||||
progname = argv[0];
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
sprintf(errmsg, "%s: socket", progname);
|
||||
perror(errmsg);
|
||||
if (s < 0)
|
||||
{
|
||||
int old_errno = errno;
|
||||
fprintf(stderr, _("%s: socket: %s\n"), progname, strerror(errno));
|
||||
if (old_errno == -EINVAL)
|
||||
{
|
||||
fprintf(stderr, _("Probably you have no IPX support in "
|
||||
"your kernel\n"));
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
while ((result = getopt_long(argc, argv, "", options,
|
||||
&option_index)) != -1) {
|
||||
switch (result) {
|
||||
case 1:
|
||||
while ((result = getopt_long(argc, argv, "hi:p:", options,
|
||||
NULL)) != -1)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
case 'p':
|
||||
if (got_auto_pri)
|
||||
break;
|
||||
got_auto_pri++;
|
||||
|
||||
|
||||
val = map_string_to_bool(optarg);
|
||||
if (val < 0) {
|
||||
if (val < 0)
|
||||
{
|
||||
usage();
|
||||
exit(-1);
|
||||
}
|
||||
{
|
||||
unsigned char v = val;
|
||||
|
||||
result = ioctl(s, SIOCAIPXPRISLT, &val);
|
||||
if (result < 0) {
|
||||
perror(errmsg);
|
||||
result = ioctl(s, SIOCAIPXPRISLT, &v);
|
||||
}
|
||||
if (result < 0)
|
||||
{
|
||||
fprintf(stderr, _("%s: ioctl: %s\n"), progname,
|
||||
strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (got_auto_itf)
|
||||
case 'i':
|
||||
if (got_auto_itf)
|
||||
break;
|
||||
got_auto_itf++;
|
||||
|
||||
val = map_string_to_bool(optarg);
|
||||
if (val < 0) {
|
||||
if (val < 0)
|
||||
{
|
||||
usage();
|
||||
exit(-1);
|
||||
}
|
||||
{
|
||||
unsigned char v = val;
|
||||
|
||||
result = ioctl(s, SIOCAIPXITFCRT, &val);
|
||||
if (result < 0) {
|
||||
perror(errmsg);
|
||||
result = ioctl(s, SIOCAIPXITFCRT, &v);
|
||||
}
|
||||
if (result < 0)
|
||||
{
|
||||
fprintf(stderr, _("%s: ioctl: %s\n"), progname,
|
||||
strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
case 'h':
|
||||
usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
result = ioctl(s, SIOCIPXCFGDATA, &data);
|
||||
if (result < 0) {
|
||||
perror(errmsg);
|
||||
exit(-1);
|
||||
if (result < 0)
|
||||
{
|
||||
fprintf(stderr, _("%s: ioctl: %s\n"), progname,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (argc == 1) {
|
||||
fprintf(stdout, "Auto Primary Select is %s\n\
|
||||
Auto Interface Create is %s\n",
|
||||
(data.ipxcfg_auto_select_primary) ? "ON" : "OFF",
|
||||
(data.ipxcfg_auto_create_interfaces) ? "ON" : "OFF");
|
||||
if (argc == 1)
|
||||
{
|
||||
fprintf(stdout, _("Auto Primary Select is %s\n"
|
||||
"Auto Interface Create is %s\n"),
|
||||
(data.ipxcfg_auto_select_primary) ? _("ON") : _("OFF"),
|
||||
(data.ipxcfg_auto_create_interfaces) ? _("ON") : _("OFF"));
|
||||
}
|
||||
exit(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
|
||||
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
|
||||
*
|
||||
|
||||
* See file COPYING for details.
|
||||
*/
|
||||
|
||||
@@ -10,389 +11,452 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netipx/ipx.h>
|
||||
#include <linux/if.h>
|
||||
#include <ncp/kernel/ipx.h>
|
||||
#include <ncp/kernel/if.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
static struct ifreq id;
|
||||
static char *progname;
|
||||
#include "ipxutil.h"
|
||||
|
||||
void
|
||||
#include "nls.h"
|
||||
|
||||
static struct ifreq id;
|
||||
static char *progname;
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s add [-p] device frame_type [net_number]\n\
|
||||
Usage: %s del device frame_type\n\
|
||||
Usage: %s delall\n\
|
||||
Usage: %s check device frame_type\n", progname, progname, progname, progname);
|
||||
exit(-1);
|
||||
fprintf(stderr,
|
||||
_("Usage: %s add [-p] device frame_type [net_number[:node]]\n"
|
||||
"Usage: %s del device frame_type\n"
|
||||
"Usage: %s delall\n"
|
||||
"Usage: %s check device frame_type\n"),
|
||||
progname, progname, progname, progname);
|
||||
}
|
||||
|
||||
struct frame_type {
|
||||
char *ft_name;
|
||||
unsigned char ft_val;
|
||||
} frame_types[] = {
|
||||
{"802.2", IPX_FRAME_8022},
|
||||
struct frame_type
|
||||
{
|
||||
const char *ft_name;
|
||||
unsigned char ft_val;
|
||||
}
|
||||
frame_types[] =
|
||||
{
|
||||
{
|
||||
"802.2", IPX_FRAME_8022
|
||||
}
|
||||
,
|
||||
#ifdef IPX_FRAME_TR_8022
|
||||
{"802.2TR", IPX_FRAME_TR_8022},
|
||||
{
|
||||
"802.2TR", IPX_FRAME_TR_8022
|
||||
}
|
||||
,
|
||||
#endif
|
||||
{"802.3", IPX_FRAME_8023},
|
||||
{"SNAP", IPX_FRAME_SNAP},
|
||||
{"EtherII", IPX_FRAME_ETHERII}
|
||||
{
|
||||
"802.3", IPX_FRAME_8023
|
||||
}
|
||||
,
|
||||
{
|
||||
"SNAP", IPX_FRAME_SNAP
|
||||
}
|
||||
,
|
||||
{
|
||||
"EtherII", IPX_FRAME_ETHERII
|
||||
}
|
||||
};
|
||||
|
||||
#define NFTYPES (sizeof(frame_types)/sizeof(struct frame_type))
|
||||
|
||||
int
|
||||
static int
|
||||
lookup_frame_type(char *frame)
|
||||
{
|
||||
size_t j;
|
||||
size_t j;
|
||||
|
||||
for (j = 0; (j < NFTYPES) &&
|
||||
(strcasecmp(frame_types[j].ft_name, frame));
|
||||
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 " : " ",
|
||||
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
|
||||
static 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;
|
||||
int c;
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
int i, fti = 0;
|
||||
int c;
|
||||
|
||||
sipx->sipx_special = IPX_SPECIAL_NONE;
|
||||
sipx->sipx_network = 0L;
|
||||
memset(sipx->sipx_node, 0, sizeof(sipx->sipx_node));
|
||||
sipx->sipx_type = IPX_FRAME_NONE;
|
||||
while ((c = getopt(argc, argv, "p")) > 0) {
|
||||
switch (c) {
|
||||
case 'p': sipx->sipx_special = IPX_PRIMARY; break;
|
||||
while ((c = getopt(argc, argv, "p")) > 0)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'p':
|
||||
sipx->sipx_special = IPX_PRIMARY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (((i = (argc - optind)) < 2) || (i > 3)) {
|
||||
if (((i = (argc - optind)) < 2) || (i > 3))
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = optind; i < argc; i++) {
|
||||
switch (i-optind) {
|
||||
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 */
|
||||
case 1: /* Frame Type - Required */
|
||||
fti = lookup_frame_type(argv[i]);
|
||||
if (fti < 0)
|
||||
exit(-1);
|
||||
if (fti < 0) {
|
||||
return -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);
|
||||
case 2: /* Network Number - Optional */
|
||||
sscanf_ipx_addr(sipx, argv[i], SSIPX_NETWORK | SSIPX_NODE);
|
||||
if (sipx->sipx_network == htonl(0xffffffffL))
|
||||
{
|
||||
fprintf(stderr,
|
||||
_("%s: Inappropriate network number %08lX\n"),
|
||||
progname, (unsigned long)ntohl(sipx->sipx_network));
|
||||
return -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);
|
||||
}
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0)
|
||||
{
|
||||
int old_errno = errno;
|
||||
fprintf(stderr, _("%s: socket: %s\n"), progname,
|
||||
strerror(errno));
|
||||
if (old_errno == -EINVAL)
|
||||
{
|
||||
fprintf(stderr, _("Probably you have no IPX support in "
|
||||
"your kernel\n"));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
i = 0;
|
||||
sipx->sipx_family = AF_IPX;
|
||||
sipx->sipx_action = IPX_CRTITF;
|
||||
do {
|
||||
do
|
||||
{
|
||||
result = ioctl(s, SIOCSIFADDR, &id);
|
||||
i++;
|
||||
} while ((i < 5) && (result < 0) && (errno == EAGAIN));
|
||||
}
|
||||
while ((i < 5) && (result < 0) && (errno == EAGAIN));
|
||||
|
||||
if (result == 0) exit(0);
|
||||
|
||||
switch (errno) {
|
||||
if (result == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (errno)
|
||||
{
|
||||
case EEXIST:
|
||||
fprintf(stderr, "%s: Primary network already selected.\n",
|
||||
fprintf(stderr, _("%s: Primary network already selected.\n"),
|
||||
progname);
|
||||
break;
|
||||
case EADDRINUSE:
|
||||
fprintf(stderr, "%s: Network number (%08X) already in use.\n",
|
||||
progname, htonl(sipx->sipx_network));
|
||||
fprintf(stderr, _("%s: Network number (%08X) already in use.\n"),
|
||||
progname, (u_int32_t)htonl(sipx->sipx_network));
|
||||
break;
|
||||
case EPROTONOSUPPORT:
|
||||
fprintf(stderr, "%s: Invalid frame type (%s).\n",
|
||||
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,
|
||||
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,
|
||||
fprintf(stderr, _("%s: Requested device (%s) is down.\n"), progname,
|
||||
id.ifr_name);
|
||||
break;
|
||||
case EINVAL:
|
||||
fprintf(stderr, "%s: Invalid device (%s).\n", progname,
|
||||
fprintf(stderr, _("%s: Invalid device (%s).\n"), progname,
|
||||
id.ifr_name);
|
||||
break;
|
||||
case EAGAIN:
|
||||
fprintf(stderr,
|
||||
"%s: Insufficient memory to create interface.\n",
|
||||
fprintf(stderr,
|
||||
_("%s: Insufficient memory to create interface.\n"),
|
||||
progname);
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
fprintf(stderr, _("%s: ioctl: %s\n"), progname,
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
exit(-1);
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
ipx_delall_interface(void)
|
||||
static int
|
||||
ipx_delall_interface(int argc __attribute__((unused)), char **argv __attribute__((unused)))
|
||||
{
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
char errmsg[80];
|
||||
char buffer[80];
|
||||
char device[20];
|
||||
char frame_type[20];
|
||||
int fti;
|
||||
FILE *fp;
|
||||
char *ret;
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
char buffer[80];
|
||||
char device[20];
|
||||
char frame_type[20];
|
||||
int fti;
|
||||
FILE *fp;
|
||||
char *ret;
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
sprintf(errmsg, "%s: socket", progname);
|
||||
perror(errmsg);
|
||||
exit(-1);
|
||||
if (s < 0)
|
||||
{
|
||||
fprintf(stderr, _("%s: socket: %s\n"), progname,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
fp = fopen("/proc/net/ipx_interface", "r");
|
||||
if (!fp) {
|
||||
fp = fopen("/proc/net/ipx/interface", "r");
|
||||
}
|
||||
|
||||
fp = fopen("/proc/net/ipx/interface", "r");
|
||||
if (fp == NULL)
|
||||
fp = fopen("/proc/net/ipx_interface", "r");
|
||||
if (fp == NULL) {
|
||||
{
|
||||
close(s);
|
||||
fprintf(stderr,
|
||||
"%s: Unable to open \"/proc/net/ipx_interface.\"\n",
|
||||
progname);
|
||||
exit(-1);
|
||||
_("%s: Unable to open \"%s.\"\n"),
|
||||
progname,
|
||||
"/proc/net/ipx_interface");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = fgets(buffer, 80, fp);
|
||||
if (ret == NULL) {
|
||||
fprintf(stderr,
|
||||
"%s: Unable to read \"/proc/net/ipx_interface.\"\n",
|
||||
progname);
|
||||
"%s: Unable to read \"/proc/net/ipx_interface.\"\n",
|
||||
progname);
|
||||
exit(-1);
|
||||
}
|
||||
while (fscanf(fp, "%s %s %s %s %s", buffer, buffer, buffer,
|
||||
device, frame_type) == 5) {
|
||||
device, frame_type) == 5)
|
||||
{
|
||||
|
||||
sipx->sipx_network = 0L;
|
||||
if (strcasecmp(device, "Internal") == 0) {
|
||||
if (strcasecmp(device, "Internal") == 0)
|
||||
{
|
||||
sipx->sipx_special = IPX_INTERNAL;
|
||||
} else {
|
||||
} else
|
||||
{
|
||||
sipx->sipx_special = IPX_SPECIAL_NONE;
|
||||
strcpy(id.ifr_name, device);
|
||||
fti = lookup_frame_type(frame_type);
|
||||
if (fti < 0) continue;
|
||||
if (fti < 0)
|
||||
continue;
|
||||
sipx->sipx_type = frame_types[fti].ft_val;
|
||||
}
|
||||
|
||||
sipx->sipx_action = IPX_DLTITF;
|
||||
sipx->sipx_family = AF_IPX;
|
||||
result = ioctl(s, SIOCSIFADDR, &id);
|
||||
if (result == 0) continue;
|
||||
switch (errno) {
|
||||
if (result == 0)
|
||||
continue;
|
||||
switch (errno)
|
||||
{
|
||||
case EPROTONOSUPPORT:
|
||||
fprintf(stderr, "%s: Invalid frame type (%s).\n",
|
||||
fprintf(stderr, _("%s: Invalid frame type (%s).\n"),
|
||||
progname, frame_type);
|
||||
break;
|
||||
case ENODEV:
|
||||
fprintf(stderr, "%s: No such device (%s).\n",
|
||||
fprintf(stderr, _("%s: No such device (%s).\n"),
|
||||
progname, device);
|
||||
break;
|
||||
case EINVAL:
|
||||
fprintf(stderr, "%s: No such IPX interface %s %s.\n",
|
||||
fprintf(stderr, _("%s: No such IPX interface %s %s.\n"),
|
||||
progname, device, frame_type);
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
fprintf(stderr, _("%s: ioctl: %s\n"), progname,
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
exit(0);
|
||||
fclose(fp);
|
||||
close(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
static 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();
|
||||
}
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
int fti;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
sipx->sipx_network = 0L;
|
||||
sipx->sipx_special = IPX_SPECIAL_NONE;
|
||||
strcpy(id.ifr_name, argv[1]);
|
||||
fti = lookup_frame_type(argv[2]);
|
||||
if (fti < 0)
|
||||
exit(-1);
|
||||
strcpy(id.ifr_name, argv[0]);
|
||||
fti = lookup_frame_type(argv[1]);
|
||||
if (fti < 0) {
|
||||
return -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);
|
||||
if (s < 0)
|
||||
{
|
||||
fprintf(stderr, _("%s: socket: %s\n"), progname,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
sipx->sipx_action = IPX_DLTITF;
|
||||
sipx->sipx_family = AF_IPX;
|
||||
result = ioctl(s, SIOCSIFADDR, &id);
|
||||
if (result == 0) exit(0);
|
||||
if (result == 0) {
|
||||
close(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (errno) {
|
||||
switch (errno)
|
||||
{
|
||||
case EPROTONOSUPPORT:
|
||||
fprintf(stderr, "%s: Invalid frame type (%s).\n",
|
||||
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,
|
||||
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,
|
||||
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);
|
||||
fprintf(stderr, _("%s: ioctl: %s\n"), progname,
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
exit(-1);
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
static 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();
|
||||
}
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
int fti;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
sipx->sipx_network = 0L;
|
||||
strcpy(id.ifr_name, argv[1]);
|
||||
fti = lookup_frame_type(argv[2]);
|
||||
if (fti < 0)
|
||||
exit(-1);
|
||||
strcpy(id.ifr_name, argv[0]);
|
||||
fti = lookup_frame_type(argv[1]);
|
||||
if (fti < 0) {
|
||||
return -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);
|
||||
if (s < 0)
|
||||
{
|
||||
fprintf(stderr, _("%s: socket: %s\n"), progname,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
sipx->sipx_family = AF_IPX;
|
||||
result = ioctl(s, SIOCGIFADDR, &id);
|
||||
if (result == 0) {
|
||||
if (result == 0)
|
||||
{
|
||||
close(s);
|
||||
printf(
|
||||
"IPX Address for (%s, %s) is %08X:%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);
|
||||
_("IPX Address for (%s, %s) is %08X:%02X%02X%02X%02X%02X%02X.\n"),
|
||||
argv[1], frame_types[fti].ft_name,
|
||||
(u_int32_t)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]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (errno) {
|
||||
switch (errno)
|
||||
{
|
||||
case EPROTONOSUPPORT:
|
||||
fprintf(stderr, "%s: Invalid frame type (%s).\n",
|
||||
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,
|
||||
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,
|
||||
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);
|
||||
fprintf(stderr, _("%s: ioctl: %s\n"), progname,
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
exit(-1);
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
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], "delall", 6) == 0) {
|
||||
if (argc > 2) {
|
||||
usage();
|
||||
exit(-1);
|
||||
}
|
||||
ipx_delall_interface();
|
||||
} 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);
|
||||
}
|
||||
setlocale(LC_ALL, "");
|
||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
textdomain(PACKAGE);
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
if (strcasecmp(argv[1], "add") == 0)
|
||||
{
|
||||
for (i = 1; i < (argc - 1); i++)
|
||||
argv[i] = argv[i + 1];
|
||||
return ipx_add_interface(argc - 1, argv);
|
||||
} else if (strcasecmp(argv[1], "delall") == 0)
|
||||
{
|
||||
return ipx_delall_interface(argc - 2, argv + 2);
|
||||
} else if (strcasecmp(argv[1], "del") == 0)
|
||||
{
|
||||
return ipx_del_interface(argc - 2, argv + 2);
|
||||
} else if (strcasecmp(argv[1], "check") == 0)
|
||||
{
|
||||
return ipx_check_interface(argc - 2, argv + 2);
|
||||
}
|
||||
usage();
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
|
||||
*
|
||||
|
||||
* See file COPYING for details.
|
||||
*/
|
||||
|
||||
@@ -9,193 +9,176 @@
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netipx/ipx.h>
|
||||
#include <linux/if.h>
|
||||
#include <ncp/kernel/ipx.h>
|
||||
#include <ncp/kernel/if.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
static struct ifreq id;
|
||||
static char *progname;
|
||||
#include "ipxutil.h"
|
||||
|
||||
void
|
||||
#include "nls.h"
|
||||
|
||||
static struct ifreq id;
|
||||
static char *progname;
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s add net_number(hex) node(hex)\n\
|
||||
Usage: %s del\n", progname, progname);
|
||||
exit(-1);
|
||||
fprintf(stderr, _("Usage: %s add net_number(hex) node(hex)\n"
|
||||
"Usage: %s del\n"),
|
||||
progname, 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;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
static 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) {
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
unsigned long netnum;
|
||||
int i;
|
||||
|
||||
if (argc < 1)
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
|
||||
netnum = strtoul(argv[1], (char **)NULL, 16);
|
||||
if ((netnum == 0L) || (netnum == 0xffffffffL)) {
|
||||
fprintf(stderr, "%s: Inappropriate network number %08lX\n",
|
||||
i = sscanf_ipx_addr(sipx, argv[0], SSIPX_NETWORK|SSIPX_NODE);
|
||||
if (!(i & SSIPX_NETWORK)) {
|
||||
fprintf(stderr, _("%s: Invalid internal network address %s\n"),
|
||||
progname, argv[0]);
|
||||
return -1;
|
||||
}
|
||||
if (!(i & SSIPX_NODE)) {
|
||||
if (argc < 2)
|
||||
memcpy(sipx->sipx_node, "\0\0\0\0\0\1", IPX_NODE_LEN);
|
||||
else if (sscanf_ipx_addr(sipx, argv[1], SSIPX_NODE) != SSIPX_NODE) {
|
||||
fprintf(stderr, _("%s: Invalid internal network node %s\n"),
|
||||
progname, argv[1]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
netnum = ntohl(sipx->sipx_network);
|
||||
if ((netnum == 0L) || (netnum == 0xffffffffL))
|
||||
{
|
||||
fprintf(stderr, _("%s: Inappropriate network number %08lX\n"),
|
||||
progname, netnum);
|
||||
exit(-1);
|
||||
return -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);
|
||||
(memcmp(sipx->sipx_node, "\377\377\377\377\377\377", IPX_NODE_LEN) == 0))
|
||||
{
|
||||
fprintf(stderr, _("%s: Node is invalid.\n"), progname);
|
||||
return -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);
|
||||
if (s < 0)
|
||||
{
|
||||
fprintf(stderr, _("%s: socket: %s\n"), progname,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
sipx->sipx_family = AF_IPX;
|
||||
sipx->sipx_action = IPX_CRTITF;
|
||||
i = 0;
|
||||
do {
|
||||
do
|
||||
{
|
||||
result = ioctl(s, SIOCSIFADDR, &id);
|
||||
i++;
|
||||
} while ((i < 5) && (result < 0) && (errno == EAGAIN));
|
||||
}
|
||||
while ((i < 5) && (result < 0) && (errno == EAGAIN));
|
||||
|
||||
if (result == 0) exit(0);
|
||||
|
||||
switch (errno) {
|
||||
if (result == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (errno)
|
||||
{
|
||||
case EEXIST:
|
||||
fprintf(stderr, "%s: Primary network already selected.\n",
|
||||
fprintf(stderr, _("%s: Primary network already selected.\n"),
|
||||
progname);
|
||||
break;
|
||||
case EADDRINUSE:
|
||||
fprintf(stderr, "%s: Network number (%08X) already in use.\n",
|
||||
progname, htonl(sipx->sipx_network));
|
||||
fprintf(stderr, _("%s: Network number (%08X) already in use.\n"),
|
||||
progname, (u_int32_t)htonl(sipx->sipx_network));
|
||||
break;
|
||||
case EAGAIN:
|
||||
fprintf(stderr,
|
||||
"%s: Insufficient memory to create internal net.\n",
|
||||
fprintf(stderr,
|
||||
_("%s: Insufficient memory to create internal net.\n"),
|
||||
progname);
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
fprintf(stderr, _("%s: ioctl: %s\n"), progname,
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
exit(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
ipx_del_internal_net(int argc, char **argv)
|
||||
static int
|
||||
ipx_del_internal_net(int argc, char **argv __attribute__((unused)))
|
||||
{
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
char errmsg[80];
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
|
||||
(void)argv;
|
||||
if (argc != 1) {
|
||||
if (argc != 0)
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
|
||||
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);
|
||||
if (s < 0)
|
||||
{
|
||||
fprintf(stderr, _("%s: socket: %s\n"), progname,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
sipx->sipx_family = AF_IPX;
|
||||
sipx->sipx_action = IPX_DLTITF;
|
||||
result = ioctl(s, SIOCSIFADDR, &id);
|
||||
if (result == 0) exit(0);
|
||||
if (result == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (errno) {
|
||||
switch (errno)
|
||||
{
|
||||
case ENOENT:
|
||||
fprintf(stderr, "%s: No internal network configured.\n", progname);
|
||||
fprintf(stderr, _("%s: No internal network configured.\n"), progname);
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
fprintf(stderr, _("%s: ioctl: %s\n"), progname,
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
exit(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
textdomain(PACKAGE);
|
||||
|
||||
progname = argv[0];
|
||||
if (argc < 2) {
|
||||
if (argc < 2)
|
||||
{
|
||||
usage();
|
||||
exit(-1);
|
||||
return -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);
|
||||
if (strcasecmp(argv[1], "add") == 0)
|
||||
{
|
||||
return ipx_add_internal_net(argc - 2, argv + 2);
|
||||
} else if (strcasecmp(argv[1], "del") == 0)
|
||||
{
|
||||
return ipx_del_internal_net(argc - 2, argv + 2);
|
||||
}
|
||||
usage();
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
267
src/ipx_route.c
267
src/ipx_route.c
@@ -1,5 +1,6 @@
|
||||
|
||||
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
|
||||
*
|
||||
|
||||
* See file COPYING for details.
|
||||
*/
|
||||
|
||||
@@ -10,211 +11,209 @@
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netipx/ipx.h>
|
||||
#include <ncp/kernel/ipx.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/route.h>
|
||||
#include <ncp/kernel/route.h>
|
||||
|
||||
static struct rtentry rd;
|
||||
static char *progname;
|
||||
#include "ipxutil.h"
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
#include "nls.h"
|
||||
|
||||
void
|
||||
static struct rtentry rd;
|
||||
static char *progname;
|
||||
|
||||
static 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);
|
||||
fprintf(stderr,
|
||||
_("Usage: %s add network(hex) router_network(hex) router_node(hex)\n"
|
||||
"Usage: %s del network(hex)\n"),
|
||||
progname, progname);
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
ipx_add_route(int argc, char **argv)
|
||||
{
|
||||
/* Router */
|
||||
struct sockaddr_ipx *sr = (struct sockaddr_ipx *)&rd.rt_gateway;
|
||||
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)
|
||||
struct sockaddr_ipx *st = (struct sockaddr_ipx *) &rd.rt_dst;
|
||||
int s;
|
||||
int result;
|
||||
int val;
|
||||
int i;
|
||||
|
||||
if (argc < 2) {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
if (sscanf_ipx_addr(st, argv[0], SSIPX_NETWORK) != SSIPX_NETWORK) {
|
||||
fprintf(stderr, _("%s: Invalid network number %s\n"),
|
||||
progname, argv[0]);
|
||||
return -1;
|
||||
}
|
||||
if ((st->sipx_network == htonl(0xffffffffL)) ||
|
||||
(st->sipx_network == htonl(0L)))
|
||||
{
|
||||
fprintf(stderr, _("%s: Inappropriate network number %08lX\n"),
|
||||
progname, (unsigned long)ntohl(st->sipx_network));
|
||||
return -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);
|
||||
val = sscanf_ipx_addr(sr, argv[1], SSIPX_NETWORK|SSIPX_NODE);
|
||||
if (!(val & SSIPX_NETWORK)) {
|
||||
fprintf(stderr, _("%s: Invalid router address %s\n"),
|
||||
progname, argv[1]);
|
||||
return -1;
|
||||
}
|
||||
if (!(val & SSIPX_NODE)) {
|
||||
if ((argc < 3) ||
|
||||
(sscanf_ipx_addr(sr, argv[2], SSIPX_NODE) != SSIPX_NODE)) {
|
||||
fprintf(stderr, _("%s: Invalid router node %s\n"),
|
||||
progname, argv[2]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if ((sr->sipx_network == htonl(0xffffffffL)) ||
|
||||
(sr->sipx_network == htonl(0L)))
|
||||
{
|
||||
fprintf(stderr, _("%s: Inappropriate network number %08lX\n"),
|
||||
progname, (unsigned long)htonl(sr->sipx_network));
|
||||
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);
|
||||
(memcmp(sr->sipx_node, "\377\377\377\377\377\377", IPX_NODE_LEN) == 0))
|
||||
{
|
||||
char tmpnode[IPX_NODE_LEN*2+1];
|
||||
|
||||
for (i = 0; i < IPX_NODE_LEN; i++)
|
||||
sprintf(tmpnode+i*2, "%02X", sr->sipx_node[i]);
|
||||
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);
|
||||
if (s < 0)
|
||||
{
|
||||
fprintf(stderr, _("%s: socket: %s\n"), progname,
|
||||
strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
sr->sipx_family = st->sipx_family = AF_IPX;
|
||||
i = 0;
|
||||
do {
|
||||
do
|
||||
{
|
||||
result = ioctl(s, SIOCADDRT, &rd);
|
||||
i++;
|
||||
} while ((i < 5) && (result < 0) && (errno == EAGAIN));
|
||||
}
|
||||
while ((i < 5) && (result < 0) && (errno == EAGAIN));
|
||||
|
||||
if (result == 0) exit(0);
|
||||
if (result == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (errno) {
|
||||
switch (errno)
|
||||
{
|
||||
case ENETUNREACH:
|
||||
fprintf(stderr, "%s: Router network (%08X) not reachable.\n",
|
||||
progname, htonl(sr->sipx_network));
|
||||
fprintf(stderr, _("%s: Router network (%08X) not reachable.\n"),
|
||||
progname, (u_int32_t)htonl(sr->sipx_network));
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
fprintf(stderr, _("%s: ioctl: %s\n"), progname,
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
exit(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
ipx_del_route(int argc, char **argv)
|
||||
{
|
||||
/* Router */
|
||||
struct sockaddr_ipx *sr = (struct sockaddr_ipx *)&rd.rt_gateway;
|
||||
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();
|
||||
}
|
||||
struct sockaddr_ipx *st = (struct sockaddr_ipx *) &rd.rt_dst;
|
||||
int s;
|
||||
int result;
|
||||
unsigned long netnum;
|
||||
|
||||
if (argc != 1)
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
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);
|
||||
if (sscanf_ipx_addr(st, argv[0], SSIPX_NETWORK) != SSIPX_NETWORK) {
|
||||
fprintf(stderr, _("%s: Invalid network number %s\n"),
|
||||
progname, argv[0]);
|
||||
return -1;
|
||||
}
|
||||
netnum = ntohl(st->sipx_network);
|
||||
if ((netnum == 0xffffffffL) || (netnum == 0L))
|
||||
{
|
||||
fprintf(stderr, _("%s: Inappropriate network number %08lX.\n"),
|
||||
progname, netnum);
|
||||
return -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);
|
||||
if (s < 0)
|
||||
{
|
||||
fprintf(stderr, _("%s: socket: %s\n"), progname,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
result = ioctl(s, SIOCDELRT, &rd);
|
||||
if (result == 0) exit(0);
|
||||
if (result == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (errno) {
|
||||
switch (errno)
|
||||
{
|
||||
case ENOENT:
|
||||
fprintf(stderr, "%s: Route not found for network %08lX.\n",
|
||||
fprintf(stderr, _("%s: Route not found for network %08lX.\n"),
|
||||
progname, netnum);
|
||||
break;
|
||||
case EPERM:
|
||||
fprintf(stderr, "%s: Network %08lX is directly connected.\n",
|
||||
fprintf(stderr, _("%s: Network %08lX is directly connected.\n"),
|
||||
progname, netnum);
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
fprintf(stderr, _("%s: ioctl: %s\n"), progname,
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
exit(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
textdomain(PACKAGE);
|
||||
|
||||
progname = argv[0];
|
||||
if (argc < 2) {
|
||||
if (argc < 2)
|
||||
{
|
||||
usage();
|
||||
exit(-1);
|
||||
return -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);
|
||||
if (strcasecmp(argv[1], "add") == 0)
|
||||
{
|
||||
return ipx_add_route(argc - 2, argv + 2);
|
||||
} else if (strcasecmp(argv[1], "del") == 0)
|
||||
{
|
||||
return ipx_del_route(argc - 2, argv + 2);
|
||||
} else {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
93
src/ipxutil.c
Normal file
93
src/ipxutil.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Petr Vandrovec <vandrove@vc.cvut.cz>
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* See file COPYING for details.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <netinet/in.h>
|
||||
#include <ncp/kernel/ipx.h>
|
||||
#include <sys/types.h>
|
||||
#include "ipxutil.h"
|
||||
|
||||
/* caller must fill sockaddr_ipx with default values... */
|
||||
/* it parses string in form NETWORK:NODE/PORT into sockaddr_ipx structure */
|
||||
/* you can modify parser by flags: SSIPX_NETWORK = network present
|
||||
SSIPX_NODE = node present
|
||||
SSIPX_PORT = port present
|
||||
separators (:, /) are optional if preceeding parts are not expected */
|
||||
/* return value: SSIPX_NONE if nothing usable was found, otherwise
|
||||
combination of SSIPX_* reports, what was found and successfully parsed */
|
||||
int
|
||||
sscanf_ipx_addr(struct sockaddr_ipx *sipx, const char* addr, int flags) {
|
||||
u_int32_t netnum;
|
||||
char* ptr;
|
||||
int retval = SSIPX_NONE;
|
||||
|
||||
/* skip leading spaces... should we? */
|
||||
while (*addr && isspace(*addr))
|
||||
addr++;
|
||||
if (!*addr)
|
||||
return retval; /* nothing found */
|
||||
if (flags & SSIPX_NETWORK) {
|
||||
netnum = strtoul(addr, &ptr, 16);
|
||||
if (ptr != addr) {
|
||||
sipx->sipx_network = htonl(netnum);
|
||||
retval |= SSIPX_NETWORK; /* network was specified */
|
||||
addr = ptr;
|
||||
}
|
||||
}
|
||||
if (flags & SSIPX_NODE) {
|
||||
if ((*addr == ':') || !(flags & SSIPX_NETWORK)) {
|
||||
u_int16_t hi;
|
||||
u_int32_t lo;
|
||||
unsigned int c;
|
||||
const char* scn;
|
||||
/* node... */
|
||||
hi = 0;
|
||||
lo = 0;
|
||||
if (*addr == ':')
|
||||
addr++;
|
||||
scn = addr;
|
||||
while (isxdigit(c=*scn)) {
|
||||
scn++;
|
||||
hi = (hi << 4) | ((lo >> 28) & 0x0F);
|
||||
c -= '0';
|
||||
if (c > 9)
|
||||
c = (c + '0' - 'A' + 10) & 0x0F;
|
||||
lo = (lo << 4) | c;
|
||||
}
|
||||
if (addr != scn) {
|
||||
sipx->sipx_node[0] = hi >> 8;
|
||||
sipx->sipx_node[1] = hi;
|
||||
sipx->sipx_node[2] = lo >> 24;
|
||||
sipx->sipx_node[3] = lo >> 16;
|
||||
sipx->sipx_node[4] = lo >> 8;
|
||||
sipx->sipx_node[5] = lo;
|
||||
retval |= SSIPX_NODE;
|
||||
addr = scn;
|
||||
} /* else syntax error(node empty) */
|
||||
}
|
||||
}
|
||||
if (flags & SSIPX_PORT) {
|
||||
if ((*addr == '/') || (*addr == ':') ||
|
||||
!(flags & (SSIPX_NETWORK|SSIPX_NODE))) {
|
||||
u_int16_t sock;
|
||||
|
||||
/* socket... */
|
||||
if ((*addr == '/') || (*addr == ':'))
|
||||
addr++;
|
||||
sock = strtoul(addr, &ptr, 16);
|
||||
if (ptr != addr) {
|
||||
sipx->sipx_port = sock;
|
||||
retval |= SSIPX_PORT;
|
||||
addr = ptr;
|
||||
} /* else syntax error(socket empty) */
|
||||
}
|
||||
}
|
||||
/* if (*addr) syntax error(data after end of address) */
|
||||
return retval;
|
||||
}
|
||||
19
src/ipxutil.h
Normal file
19
src/ipxutil.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Petr Vandrovec <vandrove@vc.cvut.cz>
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* See file COPYING for details.
|
||||
*/
|
||||
|
||||
#ifndef __IPXUTIL_H__
|
||||
#define __IPXUTIL_H__
|
||||
|
||||
#define SSIPX_NONE 0
|
||||
#define SSIPX_NETWORK 1
|
||||
#define SSIPX_NODE 2
|
||||
#define SSIPX_PORT 4
|
||||
|
||||
int
|
||||
sscanf_ipx_addr(struct sockaddr_ipx *sipx, const char* addr, int flags);
|
||||
|
||||
#endif /* __IPXUTIL_H__ */
|
||||
89
src/netlink.h
Normal file
89
src/netlink.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/* this is Linux 2.3.3 kernel include file with:
|
||||
(1) removed __KERNEL__ part
|
||||
(2) __uXX -> u_intXX_t
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_NETLINK_H
|
||||
#define __LINUX_NETLINK_H
|
||||
|
||||
#define NETLINK_ROUTE 0 /* Routing/device hook */
|
||||
#define NETLINK_SKIP 1 /* Reserved for ENskip */
|
||||
#define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */
|
||||
#define NETLINK_FIREWALL 3 /* Firewalling hook */
|
||||
#define NETLINK_ARPD 8
|
||||
#define NETLINK_ROUTE6 11 /* af_inet6 route comm channel */
|
||||
#define NETLINK_IP6_FW 13
|
||||
#define NETLINK_TAPBASE 16 /* 16 to 31 are ethertap */
|
||||
|
||||
#define MAX_LINKS 32
|
||||
|
||||
struct sockaddr_nl
|
||||
{
|
||||
sa_family_t nl_family; /* AF_NETLINK */
|
||||
unsigned short nl_pad; /* zero */
|
||||
u_int32_t nl_pid; /* process pid */
|
||||
u_int32_t nl_groups; /* multicast groups mask */
|
||||
};
|
||||
|
||||
struct nlmsghdr
|
||||
{
|
||||
u_int32_t nlmsg_len; /* Length of message including header */
|
||||
u_int16_t nlmsg_type; /* Message content */
|
||||
u_int16_t nlmsg_flags; /* Additional flags */
|
||||
u_int32_t nlmsg_seq; /* Sequence number */
|
||||
u_int32_t nlmsg_pid; /* Sending process PID */
|
||||
};
|
||||
|
||||
/* Flags values */
|
||||
|
||||
#define NLM_F_REQUEST 1 /* It is request message. */
|
||||
#define NLM_F_MULTI 2 /* Multipart message, terminated by NLMSG_DONE */
|
||||
#define NLM_F_ACK 4 /* If succeed, reply with ack */
|
||||
#define NLM_F_ECHO 8 /* Echo this request */
|
||||
|
||||
/* Modifiers to GET request */
|
||||
#define NLM_F_ROOT 0x100 /* specify tree root */
|
||||
#define NLM_F_MATCH 0x200 /* return all matching */
|
||||
#define NLM_F_ATOMIC 0x400 /* atomic GET */
|
||||
#define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH)
|
||||
|
||||
/* Modifiers to NEW request */
|
||||
#define NLM_F_REPLACE 0x100 /* Override existing */
|
||||
#define NLM_F_EXCL 0x200 /* Do not touch, if it exists */
|
||||
#define NLM_F_CREATE 0x400 /* Create, if it does not exist */
|
||||
#define NLM_F_APPEND 0x800 /* Add to end of list */
|
||||
|
||||
/*
|
||||
4.4BSD ADD NLM_F_CREATE|NLM_F_EXCL
|
||||
4.4BSD CHANGE NLM_F_REPLACE
|
||||
|
||||
True CHANGE NLM_F_CREATE|NLM_F_REPLACE
|
||||
Append NLM_F_CREATE
|
||||
Check NLM_F_EXCL
|
||||
*/
|
||||
|
||||
#define NLMSG_ALIGNTO 4
|
||||
#define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) )
|
||||
#define NLMSG_LENGTH(len) ((len)+NLMSG_ALIGN(sizeof(struct nlmsghdr)))
|
||||
#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))
|
||||
#define NLMSG_DATA(nlh) ((void*)(((char*)nlh) + NLMSG_LENGTH(0)))
|
||||
#define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
|
||||
(struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
|
||||
#define NLMSG_OK(nlh,len) ((len) > 0 && (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \
|
||||
(nlh)->nlmsg_len <= (len))
|
||||
#define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len)))
|
||||
|
||||
#define NLMSG_NOOP 0x1 /* Nothing. */
|
||||
#define NLMSG_ERROR 0x2 /* Error */
|
||||
#define NLMSG_DONE 0x3 /* End of a dump */
|
||||
#define NLMSG_OVERRUN 0x4 /* Data lost */
|
||||
|
||||
struct nlmsgerr
|
||||
{
|
||||
int error;
|
||||
struct nlmsghdr msg;
|
||||
};
|
||||
|
||||
#define NET_MAJOR 36 /* Major 36 is reserved for networking */
|
||||
|
||||
#endif /* __LINUX_NETLINK_H */
|
||||
22
src/nls.h
Normal file
22
src/nls.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef IPX_UTILS_NLS_H
|
||||
#define IPX_UTILS_NLS_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_LIBINTL_H) && defined(HAVE_GETTEXT)
|
||||
# include <libintl.h>
|
||||
#else
|
||||
# define gettext(String) (String)
|
||||
#endif
|
||||
|
||||
#ifndef _
|
||||
# define _(String) gettext(String)
|
||||
#endif
|
||||
|
||||
#ifndef N_
|
||||
# define N_(String) (String)
|
||||
#endif
|
||||
|
||||
#endif /* IPX_UTILS_NLS_H */
|
||||
45
tools/README
Normal file
45
tools/README
Normal file
@@ -0,0 +1,45 @@
|
||||
This is a VERY stupid packet sniffer for IPX ethernet packets.
|
||||
|
||||
=============================================
|
||||
! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
|
||||
! ! ! S E C U R I T Y W A R N I N G ! ! !
|
||||
! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! !
|
||||
=============================================
|
||||
|
||||
If you are using unencrypted passwords, and use this tool to send a
|
||||
dump to somebody else or store it on a computer, you might very well
|
||||
store passwords there. So, be VERY careful! This is exactly the kind
|
||||
of tools Novell designed the encrypted passwords for (or against).
|
||||
|
||||
|
||||
|
||||
I hacked it together to be able to help people with problems with
|
||||
ncpfs. The socket handling was taken from Statnet-2.0.
|
||||
|
||||
You can use it to watch commercial NetWare clients when they talk to
|
||||
servers. I divided the program into 2 parts, ipxdump and ipxparse.
|
||||
|
||||
ipxdump simply pumps all the IPX frames it receives to stdout.
|
||||
|
||||
If you use ipxdump to watch a workstation, you can use the simple
|
||||
filter function ipxdump provides. You can call ipxdump with the node
|
||||
address of the workstation you want to watch. This way only the
|
||||
packets this workstation sends and receives are monitored. As an
|
||||
example, I call ipxdump as
|
||||
|
||||
./ipxdump 00001B038B11
|
||||
|
||||
to look at my 286/10MHz test 'workstation'. ipxdump still generates
|
||||
huge amounts of data, so you should be very careful to start it just
|
||||
before you perform the operation (such as file creation for OS/2
|
||||
clients with NW4.1 as a server, or a 'dir' on a directory with long
|
||||
and short file names, or an encrypted password change ;-)) and stop it
|
||||
directly after that. And, please gzip -9 and uuencode it before you
|
||||
send it to anybody.
|
||||
|
||||
ipxparse will eventually take apart the dump that ipxdump
|
||||
generates. They can as well be used in a pipe. Currently ipxparse does
|
||||
not do anything sensible, but that will definitely change.
|
||||
|
||||
Volker Lendecke
|
||||
<lendecke@namu01.gwdg.de>
|
||||
305
tools/ipxdump.c
Normal file
305
tools/ipxdump.c
Normal file
@@ -0,0 +1,305 @@
|
||||
/*
|
||||
ipxdump.c
|
||||
Copyright 1996 Volker Lendecke, Goettingen, Germany
|
||||
Copyright 1999, 2001 Petr Vandrovec, Prague, Czech Republic
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
Revision History:
|
||||
|
||||
1.01 1999, December, 15 Petr Vandrovec <vandrove@vc.cvut.cz>
|
||||
Use sigaction instead of signal, so ^C works
|
||||
immediately and not after next frame comes
|
||||
(bsd vs. sysv signal() semantic bug)
|
||||
|
||||
1.02 2001, July 15 Petr Vandrovec <vandrove@vc.cvut.cz>
|
||||
Add #include <stdlib> to fix some warnings.
|
||||
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <ncp/ext/socket.h>
|
||||
/* TBD */
|
||||
#include <netinet/in.h>
|
||||
#ifdef HAVE_NETINET_IF_ETHER_H
|
||||
#include <netinet/if_ether.h>
|
||||
#else
|
||||
#include <linux/if_ether.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <ncp/kernel/if.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
/* TBD */
|
||||
#include <netinet/ip.h>
|
||||
/* TBD */
|
||||
#include <netinet/tcp.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <signal.h>
|
||||
#include "ipxutil.h"
|
||||
|
||||
struct ipx_address
|
||||
{
|
||||
IPXNet net __attribute__((packed));
|
||||
IPXNode node __attribute__((packed));
|
||||
IPXPort sock __attribute__((packed));
|
||||
};
|
||||
|
||||
struct ipx_packet
|
||||
{
|
||||
unsigned short ipx_checksum __attribute__((packed));
|
||||
#define IPX_NO_CHECKSUM 0xFFFF
|
||||
unsigned short ipx_pktsize __attribute__((packed));
|
||||
unsigned char ipx_tctrl __attribute__((packed));
|
||||
unsigned char ipx_type __attribute__((packed));
|
||||
#define IPX_TYPE_UNKNOWN 0x00
|
||||
#define IPX_TYPE_RIP 0x01 /* may also be 0 */
|
||||
#define IPX_TYPE_SAP 0x04 /* may also be 0 */
|
||||
#define IPX_TYPE_SPX 0x05 /* Not yet implemented */
|
||||
#define IPX_TYPE_NCP 0x11 /* $lots for docs on this (SPIT) */
|
||||
#define IPX_TYPE_PPROP 0x14 /* complicated flood fill brdcast [Not supported] */
|
||||
struct ipx_address ipx_dest __attribute__((packed));
|
||||
struct ipx_address ipx_source __attribute__((packed));
|
||||
};
|
||||
|
||||
|
||||
void handle_frame(unsigned char *buf, int length, struct sockaddr *saddr);
|
||||
void handle_ipx(const char *frame, unsigned char *buf);
|
||||
|
||||
static int filter = 0;
|
||||
static int allframes = 0;
|
||||
static IPXNode filter_node;
|
||||
|
||||
static const char* progname;
|
||||
|
||||
static void usage(void) {
|
||||
fprintf(stderr, "usage: %s [-r] [-d device] [node]\n", progname);
|
||||
}
|
||||
|
||||
static int exit_request = 0;
|
||||
static void
|
||||
int_handler(int dummy)
|
||||
{
|
||||
exit_request = 1;
|
||||
(void)dummy;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
int sd;
|
||||
struct ifreq ifr, oldifr;
|
||||
const char *device = "eth0";
|
||||
struct sockaddr saddr;
|
||||
int sizeaddr;
|
||||
unsigned char buf[4096];
|
||||
int length;
|
||||
int opt;
|
||||
struct sigaction saint;
|
||||
|
||||
progname = strrchr(argv[0], '/');
|
||||
if (progname)
|
||||
progname++;
|
||||
else
|
||||
progname = argv[0];
|
||||
|
||||
saint.sa_handler = int_handler;
|
||||
saint.sa_flags = 0;
|
||||
sigemptyset(&saint.sa_mask);
|
||||
sigaction(SIGINT, &saint, NULL);
|
||||
|
||||
while ((opt = getopt(argc, argv, "rd:h")) != -1) {
|
||||
switch (opt) {
|
||||
case 'r':allframes = 1;
|
||||
break;
|
||||
case 'd':device = optarg;
|
||||
break;
|
||||
case 'h':usage();
|
||||
return 5;
|
||||
case ':':;
|
||||
case '?':break;
|
||||
default: printf("?? unknown option returned by getopt\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (optind < argc)
|
||||
{
|
||||
if (ipx_sscanf_node(argv[optind], filter_node) != 0)
|
||||
{
|
||||
usage();
|
||||
exit(1);
|
||||
}
|
||||
filter = 1;
|
||||
}
|
||||
setvbuf(stdout, NULL, _IOLBF, 0);
|
||||
// if ((sd = socket(AF_INET, SOCK_PACKET, htons(ETH_P_ALL))) < 0)
|
||||
if ((sd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0)
|
||||
{
|
||||
perror("Can't get socket");
|
||||
fprintf(stderr, "You must run %s as root\n", progname);
|
||||
exit(1);
|
||||
}
|
||||
/* SET PROMISC */
|
||||
|
||||
strcpy(oldifr.ifr_name, device);
|
||||
if (ioctl(sd, SIOCGIFFLAGS, &oldifr) < 0)
|
||||
{
|
||||
close(sd);
|
||||
perror("Can't get flags");
|
||||
exit(2);
|
||||
}
|
||||
/* This should be rewritten to cooperate with other net tools */
|
||||
ifr = oldifr;
|
||||
ifr.ifr_flags |= IFF_PROMISC;
|
||||
|
||||
if (ioctl(sd, SIOCSIFFLAGS, &ifr) < 0)
|
||||
{
|
||||
close(sd);
|
||||
perror("Can't set flags");
|
||||
exit(3);
|
||||
}
|
||||
while (exit_request == 0)
|
||||
{
|
||||
/* This is the main data-gathering loop; keep it small
|
||||
and fast */
|
||||
sizeaddr = sizeof(saddr);
|
||||
length = recvfrom(sd, buf, sizeof(buf), 0,
|
||||
&saddr, &sizeaddr);
|
||||
if (length < 0)
|
||||
continue;
|
||||
if (allframes) {
|
||||
unsigned char* ptr = buf;
|
||||
if (filter) {
|
||||
if (memcmp(filter_node, buf, 6)&&memcmp(filter_node, buf+6, 6))
|
||||
continue;
|
||||
}
|
||||
printf("raweth ");
|
||||
while (length--) printf("%02X", *ptr++);
|
||||
printf("\n");
|
||||
} else {
|
||||
handle_frame(buf, length, &saddr);
|
||||
}
|
||||
}
|
||||
|
||||
/* This should be rewritten to cooperate with other net tools */
|
||||
if (ioctl(sd, SIOCSIFFLAGS, &oldifr) < 0)
|
||||
{
|
||||
close(sd);
|
||||
perror("Can't set flags");
|
||||
exit(4);
|
||||
}
|
||||
close(sd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
handle_ipx(const char *frame, unsigned char *buf)
|
||||
{
|
||||
int i;
|
||||
struct ipx_packet *h = (struct ipx_packet *) buf;
|
||||
struct sockaddr_ipx s_addr;
|
||||
struct sockaddr_ipx d_addr;
|
||||
int length = ntohs(h->ipx_pktsize);
|
||||
|
||||
|
||||
memset(&s_addr, 0, sizeof(s_addr));
|
||||
memset(&d_addr, 0, sizeof(d_addr));
|
||||
|
||||
memcpy(s_addr.sipx_node, h->ipx_source.node, sizeof(s_addr.sipx_node));
|
||||
s_addr.sipx_port = h->ipx_source.sock;
|
||||
s_addr.sipx_network = h->ipx_source.net;
|
||||
|
||||
memcpy(d_addr.sipx_node, h->ipx_dest.node, sizeof(d_addr.sipx_node));
|
||||
d_addr.sipx_port = h->ipx_dest.sock;
|
||||
d_addr.sipx_network = h->ipx_dest.net;
|
||||
|
||||
if (filter != 0)
|
||||
{
|
||||
if ((memcmp(filter_node, s_addr.sipx_node,
|
||||
sizeof(filter_node)) != 0)
|
||||
&& (memcmp(filter_node, d_addr.sipx_node,
|
||||
sizeof(filter_node)) != 0))
|
||||
{
|
||||
/* Not for us */
|
||||
return;
|
||||
}
|
||||
}
|
||||
printf("%s ", frame);
|
||||
|
||||
for (i = 0; i < length; i++)
|
||||
{
|
||||
printf("%2.2X", buf[i]);
|
||||
}
|
||||
printf("\n");
|
||||
if (!isatty(STDOUT_FILENO))
|
||||
{
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
handle_other(unsigned char *buf, int length, struct sockaddr *saddr)
|
||||
{
|
||||
struct ethhdr *eth = (struct ethhdr *) buf;
|
||||
unsigned char *p = &(buf[sizeof(struct ethhdr)]);
|
||||
|
||||
if (ntohs(eth->h_proto) < 1536)
|
||||
{
|
||||
/* This is a magic hack to spot IPX packets. Older
|
||||
* Novell breaks the protocol design and runs IPX over
|
||||
* 802.3 without an 802.2 LLC layer. We look for FFFF
|
||||
* which isnt a used 802.2 SSAP/DSAP. This won't work
|
||||
* for fault tolerant netware but does for the rest.
|
||||
*/
|
||||
|
||||
if (*(unsigned short *) p == 0xffff)
|
||||
{
|
||||
handle_ipx("802.3", p);
|
||||
return;
|
||||
}
|
||||
if ((*(unsigned short *) p == htons(0xe0e0))
|
||||
&& (p[2] == 0x03))
|
||||
{
|
||||
handle_ipx("802.2", p + 3);
|
||||
return;
|
||||
}
|
||||
if (memcmp(p, "\252\252\003\000\000\000\201\067", 8) == 0)
|
||||
{
|
||||
handle_ipx("snap", p + 8);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
handle_frame(unsigned char *buf, int length, struct sockaddr *saddr)
|
||||
{
|
||||
/* Ethernet packet type ID field */
|
||||
unsigned short packet_type = ((struct ethhdr *) buf)->h_proto;
|
||||
switch (htons(packet_type))
|
||||
{
|
||||
case ETH_P_IPX:
|
||||
handle_ipx("EtherII", &(buf[sizeof(struct ethhdr)]));
|
||||
break;
|
||||
default:
|
||||
handle_other(buf, length, saddr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
1140
tools/ipxparse.c
Normal file
1140
tools/ipxparse.c
Normal file
File diff suppressed because it is too large
Load Diff
133
tools/ipxutil.c
Normal file
133
tools/ipxutil.c
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
IPX support library - general functions
|
||||
|
||||
Copyright (C) 1994, 1995 Ales Dryak <e-mail: A.Dryak@sh.cvut.cz>
|
||||
Copyright (C) 1996, Volker Lendecke <lendecke@namu01.gwdg.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <netinet/in.h>
|
||||
#include "ipxutil.h"
|
||||
|
||||
void
|
||||
ipx_fprint_node(FILE * file, IPXNode node)
|
||||
{
|
||||
fprintf(file, "%02X%02X%02X%02X%02X%02X",
|
||||
(unsigned char) node[0],
|
||||
(unsigned char) node[1],
|
||||
(unsigned char) node[2],
|
||||
(unsigned char) node[3],
|
||||
(unsigned char) node[4],
|
||||
(unsigned char) node[5]
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
ipx_fprint_network(FILE * file, IPXNet net)
|
||||
{
|
||||
fprintf(file, "%08lX", (unsigned long)net);
|
||||
}
|
||||
|
||||
void
|
||||
ipx_fprint_port(FILE * file, IPXPort port)
|
||||
{
|
||||
fprintf(file, "%04X", port);
|
||||
}
|
||||
|
||||
void
|
||||
ipx_fprint_saddr(FILE * file, struct sockaddr_ipx *sipx)
|
||||
{
|
||||
ipx_fprint_network(file, ntohl(sipx->sipx_network));
|
||||
fprintf(file, ":");
|
||||
ipx_fprint_node(file, sipx->sipx_node);
|
||||
fprintf(file, ":");
|
||||
ipx_fprint_port(file, ntohs(sipx->sipx_port));
|
||||
}
|
||||
|
||||
void
|
||||
ipx_print_node(IPXNode node)
|
||||
{
|
||||
ipx_fprint_node(stdout, node);
|
||||
}
|
||||
|
||||
void
|
||||
ipx_print_network(IPXNet net)
|
||||
{
|
||||
ipx_fprint_network(stdout, net);
|
||||
}
|
||||
|
||||
void
|
||||
ipx_print_port(IPXPort port)
|
||||
{
|
||||
ipx_fprint_port(stdout, port);
|
||||
}
|
||||
|
||||
void
|
||||
ipx_print_saddr(struct sockaddr_ipx *sipx)
|
||||
{
|
||||
ipx_fprint_saddr(stdout, sipx);
|
||||
}
|
||||
|
||||
void
|
||||
ipx_assign_node(IPXNode dest, IPXNode src)
|
||||
{
|
||||
memcpy(dest, src, sizeof(IPXNode));
|
||||
}
|
||||
|
||||
int
|
||||
ipx_node_equal(IPXNode n1, IPXNode n2)
|
||||
{
|
||||
return memcmp(n1, n2, sizeof(IPXNode)) == 0;
|
||||
}
|
||||
|
||||
int
|
||||
ipx_sscanf_node(char *buf, IPXNode node)
|
||||
{
|
||||
int i;
|
||||
int n[6];
|
||||
|
||||
if ((i = sscanf(buf, "%2x%2x%2x%2x%2x%2x",
|
||||
&(n[0]), &(n[1]), &(n[2]),
|
||||
&(n[3]), &(n[4]), &(n[5]))) != 6)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
node[i] = n[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ipx_sscanf_net(char *buf, IPXNet * target)
|
||||
{
|
||||
unsigned long net;
|
||||
|
||||
if (sscanf(buf, "%8lX", &net) == 1)
|
||||
{
|
||||
*target = net;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
IPXNode ipx_this_node =
|
||||
{0, 0, 0, 0, 0, 0};
|
||||
IPXNode ipx_broadcast_node =
|
||||
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
char ipx_err_string[IPX_MAX_ERROR + 1] = "no error detected";
|
||||
65
tools/ipxutil.h
Normal file
65
tools/ipxutil.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
|
||||
IPX support library
|
||||
|
||||
Copyright (C) 1994, 1995 Ales Dryak <e-mail: A.Dryak@sh.cvut.cz>
|
||||
Copyright (C) 1996, Volker Lendecke <lendecke@namu01.gwdg.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
*/
|
||||
#ifndef __IPXUTIL_H__
|
||||
|
||||
#define __IPXUTIL_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ncp/kernel/ipx.h>
|
||||
|
||||
#define IPX_MAX_ERROR (255)
|
||||
#define IPX_THIS_NET (0)
|
||||
#define IPX_THIS_NODE (ipx_this_node)
|
||||
#define IPX_BROADCAST (ipx_broadcast_node)
|
||||
#define IPX_AUTO_PORT (0)
|
||||
#define IPX_USER_PTYPE (0)
|
||||
#define IPX_IS_INTERNAL (1)
|
||||
|
||||
typedef u_int8_t IPXNode[6];
|
||||
typedef u_int32_t IPXNet;
|
||||
typedef u_int16_t IPXPort;
|
||||
typedef u_int16_t hop_t;
|
||||
typedef u_int16_t tick_t;
|
||||
|
||||
void ipx_print_node(IPXNode node);
|
||||
void ipx_print_network(IPXNet net);
|
||||
void ipx_print_port(IPXPort port);
|
||||
void ipx_print_saddr(struct sockaddr_ipx *sipx);
|
||||
|
||||
void ipx_fprint_node(FILE * file, IPXNode node);
|
||||
void ipx_fprint_network(FILE * file, IPXNet net);
|
||||
void ipx_fprint_port(FILE * file, IPXPort port);
|
||||
void ipx_fprint_saddr(FILE * file, struct sockaddr_ipx *sipx);
|
||||
|
||||
int ipx_sscanf_node(char *buf, IPXNode node);
|
||||
int ipx_sscanf_net(char *buf, IPXNet * target);
|
||||
|
||||
void ipx_assign_node(IPXNode dest, IPXNode src);
|
||||
int ipx_node_equal(IPXNode n1, IPXNode n2);
|
||||
|
||||
extern IPXNode ipx_this_node;
|
||||
extern IPXNode ipx_broadcast_node;
|
||||
|
||||
extern char ipx_err_string[IPX_MAX_ERROR + 1];
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user