build standalone ipx utilities without ncpfs private headers

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

423
src/ipx_cmd.c Normal file
View 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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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
View 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
View 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
View 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
View 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 */