Initial commit
Add original ipx-1.1.
This commit is contained in:
9
COPYING
Normal file
9
COPYING
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the original work is
|
||||||
|
properly attributed to Greg Page and Caldera, Inc.
|
||||||
|
Neither the name of Greg Page nor Caldera, Inc. may be used to
|
||||||
|
endorse or promote products derived from this software without
|
||||||
|
specific prior written permission.
|
||||||
|
This software is provided by Greg Page and Caldera, Inc. "AS IS"
|
||||||
|
and without any express or implied warranties.
|
||||||
|
|
||||||
26
Makefile
Normal file
26
Makefile
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
CFLAGS = -O2 -Wall
|
||||||
|
UTILS = ipx_configure ipx_interface ipx_internal_net ipx_route
|
||||||
|
CC=gcc
|
||||||
|
|
||||||
|
all: $(UTILS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f $(UTILS) *.o rip sap ipxrcv ipxsend
|
||||||
|
|
||||||
|
install: $(UTILS)
|
||||||
|
for i in $(UTILS); \
|
||||||
|
do \
|
||||||
|
install --strip $$i /sbin; \
|
||||||
|
install $$i.8 /usr/man/man8; \
|
||||||
|
done
|
||||||
|
install init.ipx /etc/rc.d/init.d/ipx
|
||||||
|
install -m 0644 config.ipx /etc/sysconfig/ipx
|
||||||
|
rm -f /etc/rc.d/rc2.d/S15ipx
|
||||||
|
ln -sf /etc/rc.d/init.d/ipx /etc/rc.d/rc2.d/S15ipx
|
||||||
|
rm -f /etc/rc.d/rc3.d/S15ipx
|
||||||
|
ln -sf /etc/rc.d/init.d/ipx /etc/rc.d/rc3.d/S15ipx
|
||||||
|
rm -f /etc/rc.d/rc5.d/S15ipx
|
||||||
|
ln -sf /etc/rc.d/init.d/ipx /etc/rc.d/rc5.d/S15ipx
|
||||||
|
rm -f /etc/rc.d/rc6.d/K55ipx
|
||||||
|
ln -sf /etc/rc.d/init.d/ipx /etc/rc.d/rc6.d/K55ipx
|
||||||
|
|
||||||
71
README
Normal file
71
README
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
This file contains a very short introduction to the IPX implementation
|
||||||
|
on Linux. Feel free to forward comments (especially suggested additions)
|
||||||
|
to greg@caldera.com.
|
||||||
|
|
||||||
|
--------------------------------------8<--------------------------------------
|
||||||
|
Since this mail address isn't valid anymore (2002-03-10), I took care of this
|
||||||
|
package myself and enhanced this to compile under recent kernel versions and
|
||||||
|
systems. Feel free to write me: poc@pocnet.net.
|
||||||
|
--------------------------------------8<--------------------------------------
|
||||||
|
|
||||||
|
The following are important definitions in understanding the descriptions
|
||||||
|
in this README file.
|
||||||
|
|
||||||
|
IPX Interface - This is the item to which IPX sockets are bound.
|
||||||
|
An IPX interface corresponds to an IPX Network Number which corresponds
|
||||||
|
to a physical device and frame type. A sample IPX Interface would be:
|
||||||
|
Network Number: 0x00ABCDEF
|
||||||
|
Device: Eth0
|
||||||
|
Frame Type: 802.2.
|
||||||
|
The particular interface is selected during binding by using the
|
||||||
|
Network Number (see sample code below).
|
||||||
|
|
||||||
|
Primary Interface - The interface that is selected by default when
|
||||||
|
binding a socket. This is selected when binding by using
|
||||||
|
a network number of 0 (see sample code below).
|
||||||
|
|
||||||
|
Internal Network - This is a special kind of IPX interface that does
|
||||||
|
not have a physical device or frame type. It is used to provide
|
||||||
|
a route-independent address for service providers. Internal network
|
||||||
|
numbers are optional; however, when one is present it is also the
|
||||||
|
Primary Interface.
|
||||||
|
|
||||||
|
This tar file contains the following IPX utilities:
|
||||||
|
|
||||||
|
ipx_interface.c
|
||||||
|
This program is used to create an IPX interface.
|
||||||
|
|
||||||
|
ipx_internal_net.c
|
||||||
|
This program is used to create an IPX Internal Network number.
|
||||||
|
|
||||||
|
ipx_route.c
|
||||||
|
This program creates an IPX route.
|
||||||
|
|
||||||
|
ipx_configure.c
|
||||||
|
This program is used to read/write two configuration parameters:
|
||||||
|
AUTO INTERFACE CREATE - IPX should/shouldn't automatically create
|
||||||
|
an IPX interface when it discovers one that has not been
|
||||||
|
registered via ipx_interface above.
|
||||||
|
AUTO PRIMARY SELECT - IPX should/shouldn't automatically select
|
||||||
|
a primary interface when it one an interface exists and
|
||||||
|
none are designated as the primary. Manual designation
|
||||||
|
is performed via ipx_interface.
|
||||||
|
|
||||||
|
By default, these are both turned off.
|
||||||
|
|
||||||
|
The following are sample IPX programs (found in directory Samples):
|
||||||
|
|
||||||
|
ipxrcv.c and ipxsend.c
|
||||||
|
ipxsend will send a single packet to an instance of ipxrcv running on the
|
||||||
|
same machine. It uses getsockname(2) to determine the address to which to
|
||||||
|
send the packet.
|
||||||
|
rip.c
|
||||||
|
rip passively monitors the rip traffic on the attached IPX network.
|
||||||
|
sap.c
|
||||||
|
sap passively monitors the sap traffic on the attached IPX network.
|
||||||
|
|
||||||
|
There are three files in /proc/net that relate to IPX.
|
||||||
|
ipx_interface contains the list of IPX interfaces.
|
||||||
|
ipx_route contains the list of IPX routes.
|
||||||
|
ipx contains the list of IPX sockets in use.
|
||||||
|
|
||||||
52
Samples/ipxrcv.c
Normal file
52
Samples/ipxrcv.c
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <linux/ipx.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct sockaddr_ipx sipx;
|
||||||
|
int s;
|
||||||
|
int result;
|
||||||
|
char msg[100];
|
||||||
|
int len;
|
||||||
|
|
||||||
|
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||||
|
if (s < 0) {
|
||||||
|
perror("IPX: socket: ");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
sipx.sipx_family = AF_IPX;
|
||||||
|
sipx.sipx_network = 0;
|
||||||
|
sipx.sipx_port = htons(0x5000);
|
||||||
|
sipx.sipx_type = 17;
|
||||||
|
len = sizeof(sipx);
|
||||||
|
result = bind(s, (struct sockaddr *)&sipx, sizeof(sipx));
|
||||||
|
if (result < 0) {
|
||||||
|
perror("IPX: bind: ");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
msg[0] = '\0';
|
||||||
|
result = recvfrom(s, msg, sizeof(msg), 0, (struct sockaddr *)&sipx,
|
||||||
|
&len);
|
||||||
|
if (result < 0) {
|
||||||
|
perror("IPX: recvfrom: ");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("From %08lX:%02X%02X%02X%02X%02X%02X:%04X\n",
|
||||||
|
htonl(sipx.sipx_network),
|
||||||
|
sipx.sipx_node[0], sipx.sipx_node[1],
|
||||||
|
sipx.sipx_node[2], sipx.sipx_node[3],
|
||||||
|
sipx.sipx_node[4], sipx.sipx_node[5],
|
||||||
|
htons(sipx.sipx_port));
|
||||||
|
printf("\tGot \"%s\"\n", msg);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
46
Samples/ipxsend.c
Normal file
46
Samples/ipxsend.c
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <linux/ipx.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct sockaddr_ipx sipx;
|
||||||
|
int s;
|
||||||
|
int result;
|
||||||
|
char msg[100] = "Hi Mom";
|
||||||
|
int len = sizeof(sipx);
|
||||||
|
|
||||||
|
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||||
|
if (s < 0) {
|
||||||
|
perror("IPX: socket: ");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
sipx.sipx_family = AF_IPX;
|
||||||
|
sipx.sipx_network = 0;
|
||||||
|
sipx.sipx_port = 0;
|
||||||
|
sipx.sipx_type = 17;
|
||||||
|
|
||||||
|
result = bind(s, (struct sockaddr *)&sipx, sizeof(sipx));
|
||||||
|
if (result < 0) {
|
||||||
|
perror("IPX: bind: ");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = getsockname(s, (struct sockaddr *)&sipx, &len);
|
||||||
|
sipx.sipx_port = htons(0x5000);
|
||||||
|
result = sendto(s, msg, sizeof(msg), 0, (struct sockaddr *)&sipx,
|
||||||
|
sizeof(sipx));
|
||||||
|
if (result < 0) {
|
||||||
|
perror("IPX: send: ");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
68
Samples/rip.c
Normal file
68
Samples/rip.c
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <linux/ipx.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
struct rip_data {
|
||||||
|
unsigned long rip_net;
|
||||||
|
unsigned short rip_hops __attribute__ ((packed));
|
||||||
|
unsigned short rip_ticks __attribute__ ((packed));
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct sockaddr_ipx sipx;
|
||||||
|
int result;
|
||||||
|
int s;
|
||||||
|
char msg[1024];
|
||||||
|
int len;
|
||||||
|
char *bptr;
|
||||||
|
struct rip_data *rp;
|
||||||
|
|
||||||
|
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||||
|
if (s < 0) {
|
||||||
|
perror("IPX: socket: ");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
sipx.sipx_family = AF_IPX;
|
||||||
|
sipx.sipx_network = 0;
|
||||||
|
sipx.sipx_port = htons(0x453);
|
||||||
|
sipx.sipx_type = 17;
|
||||||
|
result = bind(s, (struct sockaddr *)&sipx, sizeof(sipx));
|
||||||
|
if (result < 0) {
|
||||||
|
perror("IPX: bind: ");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
len = sizeof(sipx);
|
||||||
|
result = recvfrom(s, msg, sizeof(msg), 0,
|
||||||
|
(struct sockaddr *)&sipx, &len);
|
||||||
|
if (result < 0) {
|
||||||
|
perror("IPX: recvfrom");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
bptr = msg;
|
||||||
|
result -= 2;
|
||||||
|
printf("RIP packet from: %08lX:%02X%02X%02X%02X%02X%02X\n",
|
||||||
|
htonl(sipx.sipx_network),
|
||||||
|
sipx.sipx_node[0], sipx.sipx_node[1],
|
||||||
|
sipx.sipx_node[2], sipx.sipx_node[3],
|
||||||
|
sipx.sipx_node[6], sipx.sipx_node[5]);
|
||||||
|
bptr += 2;
|
||||||
|
rp = (struct rip_data *) bptr;
|
||||||
|
while (result >= sizeof(struct rip_data)) {
|
||||||
|
printf("\tNET: %08lX HOPS: %d\n", ntohl(rp->rip_net),
|
||||||
|
ntohs(rp->rip_hops));
|
||||||
|
result -= sizeof(struct rip_data);
|
||||||
|
rp++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
96
Samples/sap.c
Normal file
96
Samples/sap.c
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <linux/ipx.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct sap_data {
|
||||||
|
unsigned short sap_type __attribute__ ((packed));
|
||||||
|
char sap_name[48] __attribute__ ((packed));
|
||||||
|
unsigned long sap_net __attribute__ ((packed));
|
||||||
|
unsigned char sap_node[6] __attribute__ ((packed));
|
||||||
|
unsigned short sap_sock __attribute__ ((packed));
|
||||||
|
unsigned short sap_hops __attribute__ ((packed));
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int s;
|
||||||
|
int result;
|
||||||
|
struct sockaddr_ipx sipx;
|
||||||
|
char msg[1024];
|
||||||
|
long val = 0;
|
||||||
|
int len;
|
||||||
|
char *bptr;
|
||||||
|
struct sap_data *sp;
|
||||||
|
|
||||||
|
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||||
|
if (s < 0) {
|
||||||
|
perror("IPX: socket: ");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = setsockopt(s, SOL_SOCKET, SO_DEBUG, &val, 4);
|
||||||
|
if (result < 0) {
|
||||||
|
perror("IPX: setsockopt: ");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sipx.sipx_family = PF_IPX;
|
||||||
|
sipx.sipx_network = 0L;
|
||||||
|
sipx.sipx_port = htons(0x452);
|
||||||
|
sipx.sipx_type = 17;
|
||||||
|
|
||||||
|
result = bind(s, (struct sockaddr *)&sipx, sizeof(sipx));
|
||||||
|
if (result < 0) {
|
||||||
|
perror("IPX: bind: ");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
len = 1024;
|
||||||
|
result = recvfrom(s, msg, sizeof(msg), 0,
|
||||||
|
(struct sockaddr *)&sipx, &len);
|
||||||
|
if (result < 0) {
|
||||||
|
perror("IPX: recvfrom: ");
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
bptr = msg;
|
||||||
|
result -= 2;
|
||||||
|
printf("SAP: OP is %x %x\n", bptr[0], bptr[1]);
|
||||||
|
printf("Length is %d\n", result);
|
||||||
|
if (bptr[1] != 2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bptr += 2;
|
||||||
|
sp = (struct sap_data *) bptr;
|
||||||
|
while (result >= sizeof(struct sap_data)) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
sp->sap_name[32] = '\0';
|
||||||
|
for (i = 31; (i > 0) && (sp->sap_name[i] == '_'); i--);
|
||||||
|
i++;
|
||||||
|
sp->sap_name[i] = '\0';
|
||||||
|
printf("NAME: %s TYPE: %x HOPS: %x\n", sp->sap_name,
|
||||||
|
ntohs(sp->sap_type), ntohs(sp->sap_hops));
|
||||||
|
printf("%lx:%x %x %x %x %x %x: %x\n",
|
||||||
|
ntohl(sp->sap_net),
|
||||||
|
sp->sap_node[0],
|
||||||
|
sp->sap_node[1],
|
||||||
|
sp->sap_node[2],
|
||||||
|
sp->sap_node[3],
|
||||||
|
sp->sap_node[4],
|
||||||
|
sp->sap_node[5],
|
||||||
|
ntohs(sp->sap_sock));
|
||||||
|
result -= sizeof(struct sap_data);
|
||||||
|
sp++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
7
config.ipx
Normal file
7
config.ipx
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
IPX_AUTO_PRIMARY=on
|
||||||
|
IPX_AUTO_INTERFACE=on
|
||||||
|
IPX_CONFIGURED=no
|
||||||
|
IPX_DEVICE=eth0
|
||||||
|
IPX_FRAME=802.2
|
||||||
|
IPX_INTERNAL_NET=no
|
||||||
|
IPX_NETNUM=0
|
||||||
41
init.ipx
Normal file
41
init.ipx
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# ipx Bring up/down IPX networking
|
||||||
|
#
|
||||||
|
|
||||||
|
# Source function library.
|
||||||
|
. /etc/rc.d/init.d/functions
|
||||||
|
|
||||||
|
. /etc/sysconfig/network
|
||||||
|
. /etc/sysconfig/ipx
|
||||||
|
|
||||||
|
# Check that networking is up.
|
||||||
|
[ ${NETWORKING} = "no" ] && exit 0
|
||||||
|
|
||||||
|
# See how we were called.
|
||||||
|
case "$1" in
|
||||||
|
start)
|
||||||
|
if [ ${IPX_CONFIGURED} = "yes" ]; then
|
||||||
|
if [ ${IPX_INTERNAL_NET} = "yes" ]; then
|
||||||
|
/sbin/ipx_internal_net add ${IPX_NETNUM}
|
||||||
|
else
|
||||||
|
/sbin/ipx_interface add -p ${IPX_DEVICE} \
|
||||||
|
${IPX_FRAME} ${IPX_NETNUM}
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
ipx_configure \
|
||||||
|
--auto_primary=${IPX_AUTO_PRIMARY} \
|
||||||
|
--auto_interface=${IPX_AUTO_INTERFACE}
|
||||||
|
touch /var/lock/subsys/ipx
|
||||||
|
;;
|
||||||
|
stop)
|
||||||
|
ipx_configure --auto_primary=off --auto_interface=off
|
||||||
|
ipx_interface delall
|
||||||
|
rm -f /var/lock/subsys/ipx
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Usage: network {start|stop}"
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
|
|
||||||
|
exit 0
|
||||||
42
ipx_configure.8
Normal file
42
ipx_configure.8
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
.TH IPX_CONFIGURE 8 "IPX Utilities" "Caldera, Inc."
|
||||||
|
.SH NAME
|
||||||
|
ipx_configure \- query/configure IPX behavior
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B ipx_configure
|
||||||
|
[\-\-help]
|
||||||
|
[\-\-auto_interface=[on|off]]
|
||||||
|
[\-\-auto_primary=[on|off]]
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B ipx_configure
|
||||||
|
queries or configures IPX behavior with respect to automatic IPX
|
||||||
|
interface detection. IPX can be configured to automatically create
|
||||||
|
interfaces as they are detected. It can also be configured to
|
||||||
|
automatically select a primary interface when none is explicitly
|
||||||
|
selected. By default, it is configured to
|
||||||
|
.B NOT
|
||||||
|
have this behavior.
|
||||||
|
Without arguments,
|
||||||
|
.B ipx_configure
|
||||||
|
returns the current configuration state. The behavior with
|
||||||
|
arguments is described in the section
|
||||||
|
.B OPTIONS.
|
||||||
|
.SS OPTIONS
|
||||||
|
.TP
|
||||||
|
.I "\-\-auto_interface=[on|off]"
|
||||||
|
This argument either turns on or off the behavior of automatically creating
|
||||||
|
interfaces.
|
||||||
|
.TP
|
||||||
|
.I "\-\-auto_primary=[on|off]"
|
||||||
|
This argument either turns on or off the behavior of automatically selecting
|
||||||
|
a primary interface.
|
||||||
|
.TP
|
||||||
|
.I "\-\-help"
|
||||||
|
Print out information about utility.
|
||||||
|
.SH FILES
|
||||||
|
.I /proc/net/ipx_interface
|
||||||
|
.SH BUGS
|
||||||
|
This functionality really belongs in
|
||||||
|
.B
|
||||||
|
ifconfig(8).
|
||||||
|
.SH AUTHOR
|
||||||
|
Greg Page <greg.page@caldera.com>
|
||||||
130
ipx_configure.c
Normal file
130
ipx_configure.c
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* See file COPYING for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <netipx/ipx.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/ioctl.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 }
|
||||||
|
};
|
||||||
|
|
||||||
|
char *progname;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
map_string_to_bool(char *optarg)
|
||||||
|
{
|
||||||
|
if ((strcasecmp(optarg, "ON") == 0) ||
|
||||||
|
(strcasecmp(optarg, "TRUE") == 0) ||
|
||||||
|
(strcasecmp(optarg, "SET") == 0) ||
|
||||||
|
(strcasecmp(optarg, "YES") == 0)) {
|
||||||
|
return 1;
|
||||||
|
} else if ((strcasecmp(optarg, "OFF") == 0) ||
|
||||||
|
(strcasecmp(optarg, "FALSE") == 0) ||
|
||||||
|
(strcasecmp(optarg, "CLEAR") == 0) ||
|
||||||
|
(strcasecmp(optarg, "NO") == 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;
|
||||||
|
|
||||||
|
progname = argv[0];
|
||||||
|
|
||||||
|
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||||
|
if (s < 0) {
|
||||||
|
sprintf(errmsg, "%s: socket", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(errmsg, "%s: ioctl", progname);
|
||||||
|
while ((result = getopt_long(argc, argv, "", options,
|
||||||
|
&option_index)) != -1) {
|
||||||
|
switch (result) {
|
||||||
|
case 1:
|
||||||
|
if (got_auto_pri)
|
||||||
|
break;
|
||||||
|
got_auto_pri++;
|
||||||
|
|
||||||
|
val = map_string_to_bool(optarg);
|
||||||
|
if (val < 0) {
|
||||||
|
usage();
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = ioctl(s, SIOCAIPXPRISLT, &val);
|
||||||
|
if (result < 0) {
|
||||||
|
perror(errmsg);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (got_auto_itf)
|
||||||
|
break;
|
||||||
|
got_auto_itf++;
|
||||||
|
|
||||||
|
val = map_string_to_bool(optarg);
|
||||||
|
if (val < 0) {
|
||||||
|
usage();
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
result = ioctl(s, SIOCAIPXITFCRT, &val);
|
||||||
|
if (result < 0) {
|
||||||
|
perror(errmsg);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
usage();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = ioctl(s, SIOCIPXCFGDATA, &data);
|
||||||
|
if (result < 0) {
|
||||||
|
perror(errmsg);
|
||||||
|
exit(-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");
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
67
ipx_interface.8
Normal file
67
ipx_interface.8
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
.TH IPX_INTERFACE 8 "IPX Utilities" "Caldera, Inc."
|
||||||
|
.SH NAME
|
||||||
|
ipx_interface \- add, delete, or display an IPX interface
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B ipx_interface
|
||||||
|
add [-p] device frame_type [network number]
|
||||||
|
.LP
|
||||||
|
.B ipx_interface
|
||||||
|
del device frame_type
|
||||||
|
.LP
|
||||||
|
.B ipx_interface
|
||||||
|
delall
|
||||||
|
.LP
|
||||||
|
.B ipx_interface
|
||||||
|
check device frame_type
|
||||||
|
.LP
|
||||||
|
.B ipx_interface
|
||||||
|
help
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B ipx_interface
|
||||||
|
adds, deletes, or displays IPX interfaces depending on the option selected.
|
||||||
|
.P
|
||||||
|
An IPX interface is the item to which IPX sockets are bound.
|
||||||
|
An IPX interface corresponds to an IPX Network Number which corresponds
|
||||||
|
to a physical device and frame type. A sample IPX Interface would be:
|
||||||
|
.LP
|
||||||
|
Network Number: 0x00ABCDEF
|
||||||
|
.LP
|
||||||
|
Device: Eth0
|
||||||
|
.LP
|
||||||
|
Frame Type: 802.2.
|
||||||
|
.P
|
||||||
|
There is a special IPX interface per host known as the
|
||||||
|
.B PRIMARY
|
||||||
|
or default interface.
|
||||||
|
.SS OPTIONS
|
||||||
|
.TP
|
||||||
|
.I add
|
||||||
|
This option is used to create an IPX interface. If the
|
||||||
|
.B -p
|
||||||
|
flag is used, the interface is made
|
||||||
|
.B
|
||||||
|
PRIMARY.
|
||||||
|
The network number can be optionally assigned. If it is not assigned, it
|
||||||
|
is set to 0 which indicates it should be detected from the traffic on the
|
||||||
|
network.
|
||||||
|
.TP
|
||||||
|
.I del
|
||||||
|
This option is used to delete an IPX interface.
|
||||||
|
.TP
|
||||||
|
.I delall
|
||||||
|
This option is used to delete all IPX interfaces.
|
||||||
|
.TP
|
||||||
|
.I check
|
||||||
|
This option is used to display the device, frame type, and network number
|
||||||
|
of an IPX interface.
|
||||||
|
.TP
|
||||||
|
.I help
|
||||||
|
This option displays information about the utility.
|
||||||
|
.SH FILES
|
||||||
|
.I /proc/net/ipx_interface /proc/net/ipx_route
|
||||||
|
.SH BUGS
|
||||||
|
This functionality really belongs in
|
||||||
|
.B
|
||||||
|
ifconfig(8).
|
||||||
|
.SH AUTHOR
|
||||||
|
Greg Page <greg.page@caldera.com>
|
||||||
387
ipx_interface.c
Normal file
387
ipx_interface.c
Normal file
@@ -0,0 +1,387 @@
|
|||||||
|
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* See file COPYING for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netipx/ipx.h>
|
||||||
|
#include <linux/if.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
static struct ifreq id;
|
||||||
|
static char *progname;
|
||||||
|
|
||||||
|
void
|
||||||
|
usage(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: %s add [-p] device frame_type [net_number]\n\
|
||||||
|
Usage: %s del device frame_type\n\
|
||||||
|
Usage: %s delall\n\
|
||||||
|
Usage: %s check device frame_type\n", progname, progname, progname, progname);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct frame_type {
|
||||||
|
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},
|
||||||
|
#endif
|
||||||
|
{"802.3", IPX_FRAME_8023},
|
||||||
|
{"SNAP", IPX_FRAME_SNAP},
|
||||||
|
{"EtherII", IPX_FRAME_ETHERII}
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NFTYPES (sizeof(frame_types)/sizeof(struct frame_type))
|
||||||
|
|
||||||
|
int
|
||||||
|
lookup_frame_type(char *frame)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
|
||||||
|
for (j = 0; (j < NFTYPES) &&
|
||||||
|
(strcasecmp(frame_types[j].ft_name, frame));
|
||||||
|
j++)
|
||||||
|
;
|
||||||
|
|
||||||
|
if (j != NFTYPES)
|
||||||
|
return j;
|
||||||
|
|
||||||
|
fprintf(stderr, "%s: Frame type must be", progname);
|
||||||
|
for (j = 0; j < NFTYPES; j++) {
|
||||||
|
fprintf(stderr, "%s%s",
|
||||||
|
(j == NFTYPES-1) ? " or " : " ",
|
||||||
|
frame_types[j].ft_name);
|
||||||
|
}
|
||||||
|
fprintf(stderr, ".\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ipx_add_interface(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||||
|
int s;
|
||||||
|
int result;
|
||||||
|
unsigned long netnum;
|
||||||
|
char errmsg[80];
|
||||||
|
int i, fti = 0;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
sipx->sipx_special = IPX_SPECIAL_NONE;
|
||||||
|
sipx->sipx_network = 0L;
|
||||||
|
sipx->sipx_type = IPX_FRAME_NONE;
|
||||||
|
while ((c = getopt(argc, argv, "p")) > 0) {
|
||||||
|
switch (c) {
|
||||||
|
case 'p': sipx->sipx_special = IPX_PRIMARY; break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((i = (argc - optind)) < 2) || (i > 3)) {
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = optind; i < argc; i++) {
|
||||||
|
switch (i-optind) {
|
||||||
|
case 0: /* Physical Device - Required */
|
||||||
|
strcpy(id.ifr_name, argv[i]);
|
||||||
|
break;
|
||||||
|
case 1: /* Frame Type - Required */
|
||||||
|
fti = lookup_frame_type(argv[i]);
|
||||||
|
if (fti < 0)
|
||||||
|
exit(-1);
|
||||||
|
sipx->sipx_type = frame_types[fti].ft_val;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: /* Network Number - Optional */
|
||||||
|
netnum = strtoul(argv[i], (char **)NULL, 16);
|
||||||
|
if (netnum == 0xffffffffL) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"%s: Inappropriate network number %08lX\n",
|
||||||
|
progname, netnum);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
sipx->sipx_network = htonl(netnum);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||||
|
if (s < 0) {
|
||||||
|
sprintf(errmsg, "%s: socket", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
sipx->sipx_family = AF_IPX;
|
||||||
|
sipx->sipx_action = IPX_CRTITF;
|
||||||
|
do {
|
||||||
|
result = ioctl(s, SIOCSIFADDR, &id);
|
||||||
|
i++;
|
||||||
|
} while ((i < 5) && (result < 0) && (errno == EAGAIN));
|
||||||
|
|
||||||
|
if (result == 0) exit(0);
|
||||||
|
|
||||||
|
switch (errno) {
|
||||||
|
case EEXIST:
|
||||||
|
fprintf(stderr, "%s: Primary network already selected.\n",
|
||||||
|
progname);
|
||||||
|
break;
|
||||||
|
case EADDRINUSE:
|
||||||
|
fprintf(stderr, "%s: Network number (%08X) already in use.\n",
|
||||||
|
progname, htonl(sipx->sipx_network));
|
||||||
|
break;
|
||||||
|
case EPROTONOSUPPORT:
|
||||||
|
fprintf(stderr, "%s: Invalid frame type (%s).\n",
|
||||||
|
progname, frame_types[fti].ft_name);
|
||||||
|
break;
|
||||||
|
case ENODEV:
|
||||||
|
fprintf(stderr, "%s: No such device (%s).\n", progname,
|
||||||
|
id.ifr_name);
|
||||||
|
break;
|
||||||
|
case ENETDOWN:
|
||||||
|
fprintf(stderr, "%s: Requested device (%s) is down.\n", progname,
|
||||||
|
id.ifr_name);
|
||||||
|
break;
|
||||||
|
case EINVAL:
|
||||||
|
fprintf(stderr, "%s: Invalid device (%s).\n", progname,
|
||||||
|
id.ifr_name);
|
||||||
|
break;
|
||||||
|
case EAGAIN:
|
||||||
|
fprintf(stderr,
|
||||||
|
"%s: Insufficient memory to create interface.\n",
|
||||||
|
progname);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sprintf(errmsg, "%s: ioctl", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ipx_delall_interface(int argc, char **argv)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||||
|
if (s < 0) {
|
||||||
|
sprintf(errmsg, "%s: socket", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fp = fopen("/proc/net/ipx_interface", "r");
|
||||||
|
if (fp == NULL) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"%s: Unable to open \"/proc/net/ipx_interface.\"\n",
|
||||||
|
progname);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
fgets(buffer, 80, fp);
|
||||||
|
while (fscanf(fp, "%s %s %s %s %s", buffer, buffer, buffer,
|
||||||
|
device, frame_type) == 5) {
|
||||||
|
|
||||||
|
sipx->sipx_network = 0L;
|
||||||
|
if (strcasecmp(device, "Internal") == 0) {
|
||||||
|
sipx->sipx_special = IPX_INTERNAL;
|
||||||
|
} else {
|
||||||
|
sipx->sipx_special = IPX_SPECIAL_NONE;
|
||||||
|
strcpy(id.ifr_name, device);
|
||||||
|
fti = lookup_frame_type(frame_type);
|
||||||
|
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) {
|
||||||
|
case EPROTONOSUPPORT:
|
||||||
|
fprintf(stderr, "%s: Invalid frame type (%s).\n",
|
||||||
|
progname, frame_type);
|
||||||
|
break;
|
||||||
|
case ENODEV:
|
||||||
|
fprintf(stderr, "%s: No such device (%s).\n",
|
||||||
|
progname, device);
|
||||||
|
break;
|
||||||
|
case EINVAL:
|
||||||
|
fprintf(stderr, "%s: No such IPX interface %s %s.\n",
|
||||||
|
progname, device, frame_type);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sprintf(errmsg, "%s: ioctl", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ipx_del_interface(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||||
|
int s;
|
||||||
|
int result;
|
||||||
|
char errmsg[80];
|
||||||
|
int fti;
|
||||||
|
|
||||||
|
if (argc != 3) {
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
sipx->sipx_network = 0L;
|
||||||
|
sipx->sipx_special = IPX_SPECIAL_NONE;
|
||||||
|
strcpy(id.ifr_name, argv[1]);
|
||||||
|
fti = lookup_frame_type(argv[2]);
|
||||||
|
if (fti < 0)
|
||||||
|
exit(-1);
|
||||||
|
sipx->sipx_type = frame_types[fti].ft_val;
|
||||||
|
|
||||||
|
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||||
|
if (s < 0) {
|
||||||
|
sprintf(errmsg, "%s: socket", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
sipx->sipx_action = IPX_DLTITF;
|
||||||
|
sipx->sipx_family = AF_IPX;
|
||||||
|
result = ioctl(s, SIOCSIFADDR, &id);
|
||||||
|
if (result == 0) exit(0);
|
||||||
|
|
||||||
|
switch (errno) {
|
||||||
|
case EPROTONOSUPPORT:
|
||||||
|
fprintf(stderr, "%s: Invalid frame type (%s).\n",
|
||||||
|
progname, frame_types[fti].ft_name);
|
||||||
|
break;
|
||||||
|
case ENODEV:
|
||||||
|
fprintf(stderr, "%s: No such device (%s).\n", progname,
|
||||||
|
id.ifr_name);
|
||||||
|
break;
|
||||||
|
case EINVAL:
|
||||||
|
fprintf(stderr, "%s: No such IPX interface %s %s.\n", progname,
|
||||||
|
id.ifr_name, frame_types[fti].ft_name);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sprintf(errmsg, "%s: ioctl", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ipx_check_interface(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||||
|
int s;
|
||||||
|
int result;
|
||||||
|
char errmsg[80];
|
||||||
|
int fti;
|
||||||
|
|
||||||
|
if (argc != 3) {
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
sipx->sipx_network = 0L;
|
||||||
|
strcpy(id.ifr_name, argv[1]);
|
||||||
|
fti = lookup_frame_type(argv[2]);
|
||||||
|
if (fti < 0)
|
||||||
|
exit(-1);
|
||||||
|
sipx->sipx_type = frame_types[fti].ft_val;
|
||||||
|
|
||||||
|
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||||
|
if (s < 0) {
|
||||||
|
sprintf(errmsg, "%s: socket", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
sipx->sipx_family = AF_IPX;
|
||||||
|
result = ioctl(s, SIOCGIFADDR, &id);
|
||||||
|
if (result == 0) {
|
||||||
|
printf(
|
||||||
|
"IPX Address for (%s, %s) is %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);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (errno) {
|
||||||
|
case EPROTONOSUPPORT:
|
||||||
|
fprintf(stderr, "%s: Invalid frame type (%s).\n",
|
||||||
|
progname, frame_types[fti].ft_name);
|
||||||
|
break;
|
||||||
|
case ENODEV:
|
||||||
|
fprintf(stderr, "%s: No such device (%s).\n", progname,
|
||||||
|
id.ifr_name);
|
||||||
|
break;
|
||||||
|
case EADDRNOTAVAIL:
|
||||||
|
fprintf(stderr, "%s: No such IPX interface %s %s.\n", progname,
|
||||||
|
id.ifr_name, frame_types[fti].ft_name);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sprintf(errmsg, "%s: ioctl", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
progname = argv[0];
|
||||||
|
if (argc < 2) {
|
||||||
|
usage();
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strncasecmp(argv[1], "add", 3) == 0) {
|
||||||
|
for (i = 1; i < (argc-1); i++)
|
||||||
|
argv[i] = argv[i+1];
|
||||||
|
ipx_add_interface(argc-1, argv);
|
||||||
|
} else if (strncasecmp(argv[1], "delall", 6) == 0) {
|
||||||
|
for (i = 1; i < (argc-1); i++)
|
||||||
|
argv[i] = argv[i+1];
|
||||||
|
ipx_delall_interface(argc-1, argv);
|
||||||
|
} else if (strncasecmp(argv[1], "del", 3) == 0) {
|
||||||
|
for (i = 1; i < (argc-1); i++)
|
||||||
|
argv[i] = argv[i+1];
|
||||||
|
ipx_del_interface(argc-1, argv);
|
||||||
|
} else if (strncasecmp(argv[1], "check", 5) == 0) {
|
||||||
|
for (i = 1; i < (argc-1); i++)
|
||||||
|
argv[i] = argv[i+1];
|
||||||
|
ipx_check_interface(argc-1, argv);
|
||||||
|
}
|
||||||
|
usage();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
32
ipx_internal_net.8
Normal file
32
ipx_internal_net.8
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
.TH IPX_INTERNAL_NET 8 "IPX Utilities" "Caldera, Inc."
|
||||||
|
.SH NAME
|
||||||
|
ipx_internal_net \- add or delete the IPX internal network
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B ipx_internal_net
|
||||||
|
add network_number node_number
|
||||||
|
.LP
|
||||||
|
.B ipx_internal_net
|
||||||
|
del
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B ipx_internal_net
|
||||||
|
adds or deletes the IPX internal network.
|
||||||
|
An IPX internal network is a special kind of IPX interface that does
|
||||||
|
not have a physical device or frame type. It is used to provide
|
||||||
|
a route-independent address for service providers. Internal networks
|
||||||
|
are optional; however, when one is present it is also the
|
||||||
|
Primary Interface. There can only be one internal network per host.
|
||||||
|
.SS OPTIONS
|
||||||
|
.TP
|
||||||
|
.I add
|
||||||
|
This option is used to create the IPX internal network.
|
||||||
|
.TP
|
||||||
|
.I del
|
||||||
|
This option is used to delete the IPX internal network.
|
||||||
|
.SH FILES
|
||||||
|
.I /proc/net/ipx_interface /proc/net/ipx_route
|
||||||
|
.SH BUGS
|
||||||
|
This functionality really belongs in
|
||||||
|
.B
|
||||||
|
ifconfig(8).
|
||||||
|
.SH AUTHOR
|
||||||
|
Greg Page <greg.page@caldera.com>
|
||||||
200
ipx_internal_net.c
Normal file
200
ipx_internal_net.c
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* See file COPYING for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netipx/ipx.h>
|
||||||
|
#include <linux/if.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
static struct ifreq id;
|
||||||
|
static char *progname;
|
||||||
|
|
||||||
|
void
|
||||||
|
usage(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: %s add net_number(hex) node(hex)\n\
|
||||||
|
Usage: %s del\n", progname, progname);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
map_char_to_val(char dig)
|
||||||
|
{
|
||||||
|
char digit = tolower(dig);
|
||||||
|
if ((digit >= '0') && (digit <= '9')) {
|
||||||
|
return digit - '0';
|
||||||
|
} else if ((digit >= 'a') && (digit <= 'f')) {
|
||||||
|
return (10 + (digit - 'a'));
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ipx_add_internal_net(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||||
|
int s;
|
||||||
|
int result;
|
||||||
|
unsigned long netnum;
|
||||||
|
char errmsg[80];
|
||||||
|
int nodelen;
|
||||||
|
char *node;
|
||||||
|
char tmpnode[13];
|
||||||
|
unsigned char *tout;
|
||||||
|
char *tin;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (argc != 3) {
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
netnum = strtoul(argv[1], (char **)NULL, 16);
|
||||||
|
if ((netnum == 0L) || (netnum == 0xffffffffL)) {
|
||||||
|
fprintf(stderr, "%s: Inappropriate network number %08lX\n",
|
||||||
|
progname, netnum);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
node = argv[2];
|
||||||
|
nodelen = strlen(node);
|
||||||
|
if (nodelen > 12) {
|
||||||
|
fprintf(stderr, "%s: Node length is too long (> 12).\n", progname);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; (i < nodelen) && isxdigit(node[i]); i++)
|
||||||
|
;
|
||||||
|
|
||||||
|
if (i < nodelen) {
|
||||||
|
fprintf(stderr, "%s: Invalid value in node, must be hex digits.\n",
|
||||||
|
progname);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(tmpnode, "000000000000");
|
||||||
|
memcpy(&(tmpnode[12-nodelen]), node, nodelen);
|
||||||
|
for (tin = tmpnode, tout = sipx->sipx_node; *tin != '\0'; tin += 2, tout++) {
|
||||||
|
*tout = (unsigned char) map_char_to_val(*tin);
|
||||||
|
*tout <<= 4;
|
||||||
|
*tout |= (unsigned char) map_char_to_val(*(tin+1));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((memcmp(sipx->sipx_node, "\0\0\0\0\0\0\0\0", IPX_NODE_LEN) == 0) ||
|
||||||
|
(memcmp(sipx->sipx_node, "\377\377\377\377\377\377", IPX_NODE_LEN) == 0)){
|
||||||
|
fprintf(stderr, "%s: Node is invalid.\n", progname);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sipx->sipx_network = htonl(netnum);
|
||||||
|
sipx->sipx_type = IPX_FRAME_NONE;
|
||||||
|
sipx->sipx_special = IPX_INTERNAL;
|
||||||
|
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||||
|
if (s < 0) {
|
||||||
|
sprintf(errmsg, "%s: socket", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sipx->sipx_family = AF_IPX;
|
||||||
|
sipx->sipx_action = IPX_CRTITF;
|
||||||
|
i = 0;
|
||||||
|
do {
|
||||||
|
result = ioctl(s, SIOCSIFADDR, &id);
|
||||||
|
i++;
|
||||||
|
} while ((i < 5) && (result < 0) && (errno == EAGAIN));
|
||||||
|
|
||||||
|
if (result == 0) exit(0);
|
||||||
|
|
||||||
|
switch (errno) {
|
||||||
|
case EEXIST:
|
||||||
|
fprintf(stderr, "%s: Primary network already selected.\n",
|
||||||
|
progname);
|
||||||
|
break;
|
||||||
|
case EADDRINUSE:
|
||||||
|
fprintf(stderr, "%s: Network number (%08X) already in use.\n",
|
||||||
|
progname, htonl(sipx->sipx_network));
|
||||||
|
break;
|
||||||
|
case EAGAIN:
|
||||||
|
fprintf(stderr,
|
||||||
|
"%s: Insufficient memory to create internal net.\n",
|
||||||
|
progname);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sprintf(errmsg, "%s: ioctl", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ipx_del_internal_net(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||||
|
int s;
|
||||||
|
int result;
|
||||||
|
char errmsg[80];
|
||||||
|
|
||||||
|
if (argc != 1) {
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
sipx->sipx_network = 0L;
|
||||||
|
sipx->sipx_special = IPX_INTERNAL;
|
||||||
|
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||||
|
if (s < 0) {
|
||||||
|
sprintf(errmsg, "%s: socket", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
sipx->sipx_family = AF_IPX;
|
||||||
|
sipx->sipx_action = IPX_DLTITF;
|
||||||
|
result = ioctl(s, SIOCSIFADDR, &id);
|
||||||
|
if (result == 0) exit(0);
|
||||||
|
|
||||||
|
switch (errno) {
|
||||||
|
case ENOENT:
|
||||||
|
fprintf(stderr, "%s: No internal network configured.\n", progname);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sprintf(errmsg, "%s: ioctl", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
progname = argv[0];
|
||||||
|
if (argc < 2) {
|
||||||
|
usage();
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strncasecmp(argv[1], "add", 3) == 0) {
|
||||||
|
for (i = 1; i < (argc-1); i++)
|
||||||
|
argv[i] = argv[i+1];
|
||||||
|
ipx_add_internal_net(argc-1, argv);
|
||||||
|
} else if (strncasecmp(argv[1], "del", 3) == 0) {
|
||||||
|
for (i = 1; i < (argc-1); i++)
|
||||||
|
argv[i] = argv[i+1];
|
||||||
|
ipx_del_internal_net(argc-1, argv);
|
||||||
|
}
|
||||||
|
usage();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
24
ipx_route.8
Normal file
24
ipx_route.8
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
.TH IPX_ROUTE 8 "IPX Utilities" "Caldera, Inc."
|
||||||
|
.SH NAME
|
||||||
|
ipx_route \- add or delete IPX route
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B ipx_route
|
||||||
|
add target_network router_network router_node
|
||||||
|
.LP
|
||||||
|
.B ipx_route
|
||||||
|
del target_network
|
||||||
|
.SH DESCRIPTION
|
||||||
|
.B ipx_route
|
||||||
|
adds or deletes an IPX route.
|
||||||
|
The kernel IPX stores only one route per target network at a time.
|
||||||
|
.SS OPTIONS
|
||||||
|
.TP
|
||||||
|
.I add
|
||||||
|
This option is used to set up the route to a target network.
|
||||||
|
.TP
|
||||||
|
.I del
|
||||||
|
This option is used to delete the route to a target network.
|
||||||
|
.SH FILES
|
||||||
|
.I /proc/net/ipx_interface /proc/net/ipx_route
|
||||||
|
.SH AUTHOR
|
||||||
|
Greg Page <greg.page@caldera.com>
|
||||||
220
ipx_route.c
Normal file
220
ipx_route.c
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* See file COPYING for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netipx/ipx.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <linux/route.h>
|
||||||
|
|
||||||
|
static struct rtentry rd;
|
||||||
|
static char *progname;
|
||||||
|
|
||||||
|
int
|
||||||
|
map_char_to_val(char dig)
|
||||||
|
{
|
||||||
|
char digit = tolower(dig);
|
||||||
|
if ((digit >= '0') && (digit <= '9')) {
|
||||||
|
return digit - '0';
|
||||||
|
} else if ((digit >= 'a') && (digit <= 'f')) {
|
||||||
|
return (10 + (digit - 'a'));
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
usage(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"Usage: %s add network(hex) router_network(hex) router_node(hex)\n\
|
||||||
|
Usage: %s del network(hex)\n", progname, progname);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ipx_add_route(int argc, char **argv)
|
||||||
|
{
|
||||||
|
/* Router */
|
||||||
|
struct sockaddr_ipx *sr = (struct sockaddr_ipx *)&rd.rt_gateway;
|
||||||
|
/* Target */
|
||||||
|
struct sockaddr_ipx *st = (struct sockaddr_ipx *)&rd.rt_dst;
|
||||||
|
int s;
|
||||||
|
int result;
|
||||||
|
int nodelen;
|
||||||
|
int i;
|
||||||
|
unsigned long netnum;
|
||||||
|
char errmsg[80];
|
||||||
|
char *node;
|
||||||
|
char *tin;
|
||||||
|
char tmpnode[13];
|
||||||
|
unsigned char *tout;
|
||||||
|
|
||||||
|
if (argc != 4)
|
||||||
|
usage();
|
||||||
|
|
||||||
|
/* Network Number */
|
||||||
|
netnum = strtoul(argv[1], (char **)NULL, 16);
|
||||||
|
if ((netnum == 0xffffffffL) || (netnum == 0L)) {
|
||||||
|
fprintf(stderr, "%s: Inappropriate network number %08lX\n",
|
||||||
|
progname, netnum);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
rd.rt_flags = RTF_GATEWAY;
|
||||||
|
st->sipx_network = htonl(netnum);
|
||||||
|
|
||||||
|
/* Router Network Number */
|
||||||
|
netnum = strtoul(argv[2], (char **)NULL, 16);
|
||||||
|
if ((netnum == 0xffffffffL) || (netnum == 0L)) {
|
||||||
|
fprintf(stderr, "%s: Inappropriate network number %08lX\n",
|
||||||
|
progname, netnum);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
sr->sipx_network = htonl(netnum);
|
||||||
|
|
||||||
|
/* Router Node */
|
||||||
|
node = argv[3];
|
||||||
|
nodelen = strlen(node);
|
||||||
|
if (nodelen > 12) {
|
||||||
|
fprintf(stderr, "%s: Node length is too long (> 12).\n",
|
||||||
|
progname);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; (i < nodelen) && isxdigit(node[i]); i++)
|
||||||
|
;
|
||||||
|
|
||||||
|
if (i < nodelen) {
|
||||||
|
fprintf(stderr, "%s: Invalid value in node, must be hex digits.\n",
|
||||||
|
progname);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(tmpnode, "000000000000");
|
||||||
|
memcpy(&(tmpnode[12-nodelen]), node, nodelen);
|
||||||
|
for (tin = tmpnode, tout = sr->sipx_node; *tin != '\0'; tin += 2, tout++) {
|
||||||
|
*tout = (unsigned char) map_char_to_val(*tin);
|
||||||
|
*tout <<= 4;
|
||||||
|
*tout |= (unsigned char) map_char_to_val(*(tin+1));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((memcmp(sr->sipx_node, "\0\0\0\0\0\0\0\0", IPX_NODE_LEN) == 0) ||
|
||||||
|
(memcmp(sr->sipx_node, "\377\377\377\377\377\377", IPX_NODE_LEN) == 0)){
|
||||||
|
fprintf(stderr, "%s: Node (%s) is invalid.\n", progname, tmpnode);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||||
|
if (s < 0) {
|
||||||
|
sprintf(errmsg, "%s: socket", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
sr->sipx_family = st->sipx_family = AF_IPX;
|
||||||
|
i = 0;
|
||||||
|
do {
|
||||||
|
result = ioctl(s, SIOCADDRT, &rd);
|
||||||
|
i++;
|
||||||
|
} while ((i < 5) && (result < 0) && (errno == EAGAIN));
|
||||||
|
|
||||||
|
if (result == 0) exit(0);
|
||||||
|
|
||||||
|
switch (errno) {
|
||||||
|
case ENETUNREACH:
|
||||||
|
fprintf(stderr, "%s: Router network (%08X) not reachable.\n",
|
||||||
|
progname, htonl(sr->sipx_network));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sprintf(errmsg, "%s: ioctl", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
ipx_del_route(int argc, char **argv)
|
||||||
|
{
|
||||||
|
/* Router */
|
||||||
|
struct sockaddr_ipx *sr = (struct sockaddr_ipx *)&rd.rt_gateway;
|
||||||
|
/* Target */
|
||||||
|
struct sockaddr_ipx *st = (struct sockaddr_ipx *)&rd.rt_dst;
|
||||||
|
int s;
|
||||||
|
int result;
|
||||||
|
unsigned long netnum;
|
||||||
|
char errmsg[80];
|
||||||
|
|
||||||
|
if (argc != 2) {
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
rd.rt_flags = RTF_GATEWAY;
|
||||||
|
/* Network Number */
|
||||||
|
netnum = strtoul(argv[1], (char **)NULL, 16);
|
||||||
|
if ((netnum == 0xffffffffL) || (netnum == 0L)) {
|
||||||
|
fprintf(stderr, "%s: Inappropriate network number %08lX.\n",
|
||||||
|
progname, netnum);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
st->sipx_network = htonl(netnum);
|
||||||
|
|
||||||
|
st->sipx_family = sr->sipx_family = AF_IPX;
|
||||||
|
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||||
|
if (s < 0) {
|
||||||
|
sprintf(errmsg, "%s: socket", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
result = ioctl(s, SIOCDELRT, &rd);
|
||||||
|
if (result == 0) exit(0);
|
||||||
|
|
||||||
|
switch (errno) {
|
||||||
|
case ENOENT:
|
||||||
|
fprintf(stderr, "%s: Route not found for network %08lX.\n",
|
||||||
|
progname, netnum);
|
||||||
|
break;
|
||||||
|
case EPERM:
|
||||||
|
fprintf(stderr, "%s: Network %08lX is directly connected.\n",
|
||||||
|
progname, netnum);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sprintf(errmsg, "%s: ioctl", progname);
|
||||||
|
perror(errmsg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
progname = argv[0];
|
||||||
|
if (argc < 2) {
|
||||||
|
usage();
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strncasecmp(argv[1], "add", 3) == 0) {
|
||||||
|
for (i = 1; i < (argc-1); i++)
|
||||||
|
argv[i] = argv[i+1];
|
||||||
|
ipx_add_route(argc-1, argv);
|
||||||
|
} else if (strncasecmp(argv[1], "del", 3) == 0) {
|
||||||
|
for (i = 1; i < (argc-1); i++)
|
||||||
|
argv[i] = argv[i+1];
|
||||||
|
ipx_del_route(argc-1, argv);
|
||||||
|
}
|
||||||
|
usage();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user