build standalone ipx utilities without ncpfs private headers
This commit is contained in:
423
src/ipx_cmd.c
Normal file
423
src/ipx_cmd.c
Normal file
@@ -0,0 +1,423 @@
|
||||
/*
|
||||
ipx_cmd.c - IPX Compatibility mode tunnel
|
||||
Copyright (C) 1999 Petr Vandrovec
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Revision history:
|
||||
|
||||
0.00 1999 Petr Vandrovec <vandrove@vc.cvut.cz>
|
||||
Initial revision.
|
||||
|
||||
1.00 1999, November 20 Petr Vandrovec <vandrove@vc.cvut.cz>
|
||||
Added license.
|
||||
|
||||
1.01 2001, June 16 Petr Vandrovec <vandrove@vc.cvut.cz>
|
||||
Cleanup some compilation warnings.
|
||||
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/types.h>
|
||||
#include <ncp/ext/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <netdb.h>
|
||||
#include <net/if_arp.h> /* TODO: linux/if_arp.h */
|
||||
#include <ncp/kernel/ipx.h>
|
||||
#include <ncp/kernel/if.h>
|
||||
#include <ncp/kernel/types.h>
|
||||
#include "netlink.h"
|
||||
|
||||
#include "nls.h"
|
||||
#define _(X) gettext(X)
|
||||
|
||||
#define NOVELL_SCMD_PORT (2645)
|
||||
|
||||
/* Move them to configure... */
|
||||
#ifndef AF_NETLINK
|
||||
#define AF_NETLINK 16
|
||||
#endif
|
||||
#ifndef PF_NETLINK
|
||||
#define PF_NETLINK AF_NETLINK
|
||||
#endif
|
||||
|
||||
/* we are doing EthernetII... Any objections? */
|
||||
struct {
|
||||
u_int16_t unknown __attribute__((packed));
|
||||
u_int8_t dst[6];
|
||||
u_int8_t src[6];
|
||||
u_int16_t type __attribute__((packed));
|
||||
u_int8_t ipx[16384];
|
||||
} __attribute__((packed)) buffer;
|
||||
|
||||
static int getiflist(int fd, struct ifconf* ifc) {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 32; i++) {
|
||||
int err;
|
||||
|
||||
ifc->ifc_len = 65536; /* ignored */
|
||||
ifc->ifc_req = NULL;
|
||||
|
||||
err = ioctl(fd, SIOCGIFCONF, ifc);
|
||||
if (err < 0)
|
||||
continue;
|
||||
|
||||
if (!ifc->ifc_len)
|
||||
return 0;
|
||||
|
||||
ifc->ifc_req = (struct ifreq*)malloc(ifc->ifc_len);
|
||||
err = ioctl(fd, SIOCGIFCONF, ifc);
|
||||
if (!err)
|
||||
return 0;
|
||||
free(ifc->ifc_buf);
|
||||
}
|
||||
ifc->ifc_len = 0;
|
||||
ifc->ifc_req = NULL;
|
||||
return errno;
|
||||
}
|
||||
|
||||
static char* progname;
|
||||
|
||||
static int findtap(int fd_ipx, u_int32_t local) {
|
||||
int i;
|
||||
u_int8_t localhw[6];
|
||||
|
||||
localhw[0] = 0x7E;
|
||||
localhw[1] = 0x01;
|
||||
memcpy(localhw+2, &local, 4);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
struct ifreq ifr;
|
||||
int err;
|
||||
|
||||
sprintf(ifr.ifr_name, "tap%d", i);
|
||||
((struct sockaddr_ipx*)&ifr.ifr_addr)->sipx_type = IPX_FRAME_ETHERII;
|
||||
err = ioctl(fd_ipx, SIOCGIFHWADDR, &ifr);
|
||||
if (err >= 0) {
|
||||
if ((ifr.ifr_addr.sa_family == ARPHRD_ETHER) && !memcmp(ifr.ifr_addr.sa_data, localhw, 6)) {
|
||||
err = ioctl(fd_ipx, SIOCGIFADDR, &ifr);
|
||||
if (err >= 0) {
|
||||
if (!memcmp(((struct sockaddr_ipx*)&ifr.ifr_addr)->sipx_node, localhw, 6)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return -EADDRNOTAVAIL;
|
||||
}
|
||||
|
||||
static void usage(void) {
|
||||
fprintf(stderr, _("usage: %s -A migration_agent [-l local_ip]\n"), progname);
|
||||
return;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
int fd_ip;
|
||||
struct sockaddr_in localIP;
|
||||
int status;
|
||||
int fd_netlink;
|
||||
struct sockaddr_nl localNET;
|
||||
int arg;
|
||||
int maxfd;
|
||||
fd_set rcvset;
|
||||
int opt;
|
||||
char *server = NULL;
|
||||
struct hostent* hent;
|
||||
u_int32_t serveraddr;
|
||||
u_int32_t local = htonl(INADDR_ANY);
|
||||
int local_ok;
|
||||
struct ifconf ifc;
|
||||
struct ifreq* curr;
|
||||
struct ifreq* stop;
|
||||
int tapnum;
|
||||
int fd_ipx;
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
textdomain(PACKAGE);
|
||||
|
||||
{
|
||||
char* i;
|
||||
|
||||
i = strrchr(argv[0], '/');
|
||||
progname = i?i+1:argv[0];
|
||||
}
|
||||
|
||||
while ((opt = getopt(argc, argv, "A:l:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'A':
|
||||
server = optarg;
|
||||
break;
|
||||
case 'l':
|
||||
{
|
||||
hent = gethostbyname(optarg);
|
||||
if (!hent) {
|
||||
fprintf(stderr, _("%s: %s: "),
|
||||
progname,
|
||||
optarg);
|
||||
herror("");
|
||||
exit(99);
|
||||
}
|
||||
if (hent->h_addrtype != AF_INET) {
|
||||
fprintf(stderr, _("%s: Address of %s is not IP\n"),
|
||||
progname,
|
||||
optarg);
|
||||
exit(99);
|
||||
}
|
||||
if (hent->h_length != 4) {
|
||||
fprintf(stderr, _("%s: Address of %s is not 4 bytes long\n"),
|
||||
progname,
|
||||
optarg);
|
||||
exit(99);
|
||||
}
|
||||
memcpy(&local, hent->h_addr, 4);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
exit(99);
|
||||
}
|
||||
}
|
||||
|
||||
if (!server) {
|
||||
usage();
|
||||
exit(99);
|
||||
}
|
||||
|
||||
hent = gethostbyname(server);
|
||||
if (!hent) {
|
||||
fprintf(stderr, _("%s: %s: "),
|
||||
progname,
|
||||
server);
|
||||
herror("");
|
||||
exit(99);
|
||||
}
|
||||
if (hent->h_addrtype != AF_INET) {
|
||||
fprintf(stderr, _("%s: Address of %s is not IP\n"),
|
||||
progname,
|
||||
server);
|
||||
exit(99);
|
||||
}
|
||||
if (hent->h_length != 4) {
|
||||
fprintf(stderr, _("%s: Address of %s is not 4 bytes long\n"),
|
||||
progname,
|
||||
server);
|
||||
exit(99);
|
||||
}
|
||||
memcpy(&serveraddr, hent->h_addr, 4);
|
||||
|
||||
fd_ip = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (fd_ip == -1) {
|
||||
int err = errno;
|
||||
fprintf(stderr, _("%s: Cannot create UDP/IP socket: %s\n"),
|
||||
progname,
|
||||
strerror(err));
|
||||
return 1;
|
||||
}
|
||||
|
||||
status = getiflist(fd_ip, &ifc);
|
||||
if (status) {
|
||||
close(fd_ip);
|
||||
fprintf(stderr, _("%s: Cannot get list of local interfaces: %s\n"),
|
||||
progname,
|
||||
strerror(status));
|
||||
return 1;
|
||||
}
|
||||
curr = ifc.ifc_req;
|
||||
stop = (struct ifreq*)(((u_int8_t*)curr) + ifc.ifc_len);
|
||||
|
||||
local_ok = 0;
|
||||
while (curr < stop) {
|
||||
if (curr->ifr_addr.sa_family == AF_INET) {
|
||||
u_int32_t net = ((struct sockaddr_in*)&curr->ifr_addr)->sin_addr.s_addr;
|
||||
if (((ntohl(net) & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT) != IN_LOOPBACKNET) {
|
||||
if (local == htonl(INADDR_ANY))
|
||||
local = net;
|
||||
if (local == net)
|
||||
local_ok = 1;
|
||||
}
|
||||
}
|
||||
curr++;
|
||||
}
|
||||
free(ifc.ifc_req);
|
||||
if (!local_ok) {
|
||||
close(fd_ip);
|
||||
fprintf(stderr, _("%s: Cannot find local requested address\n"),
|
||||
progname);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* TBD: enable SO_REUSEADDR? */
|
||||
localIP.sin_family = AF_INET;
|
||||
localIP.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
localIP.sin_port = htons(NOVELL_SCMD_PORT);
|
||||
status = bind(fd_ip, (struct sockaddr*)&localIP, sizeof(localIP));
|
||||
if (status) {
|
||||
int err = errno;
|
||||
close(fd_ip);
|
||||
fprintf(stderr, _("%s: Cannot bind requested address to IP socket: %s\n"),
|
||||
progname,
|
||||
strerror(err));
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* OK, we have local IP address... Now find appropriate tap device */
|
||||
fd_ipx = socket(PF_IPX, SOCK_DGRAM, IPXPROTO_IPX);
|
||||
if (fd_ipx < 0) {
|
||||
int err = errno;
|
||||
close(fd_ip);
|
||||
fprintf(stderr, _("%s: Cannot create IPX socket: %s\n"),
|
||||
progname,
|
||||
strerror(err));
|
||||
return 1;
|
||||
}
|
||||
tapnum = findtap(fd_ipx, local);
|
||||
if (tapnum < 0) {
|
||||
close(fd_ipx);
|
||||
close(fd_ip);
|
||||
fprintf(stderr, _("%s: Cannot find ethertap interface: %s\n"),
|
||||
progname,
|
||||
strerror(-tapnum));
|
||||
return 1;
|
||||
}
|
||||
close(fd_ipx);
|
||||
|
||||
fd_netlink = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_TAPBASE+tapnum);
|
||||
if (fd_netlink == -1) {
|
||||
int err = errno;
|
||||
close(fd_ip);
|
||||
fprintf(stderr, _("%s: Cannot create NETLINK socket: %s\n"),
|
||||
progname,
|
||||
strerror(err));
|
||||
return 1;
|
||||
}
|
||||
localNET.nl_family = AF_NETLINK;
|
||||
localNET.nl_pid = serveraddr;
|
||||
localNET.nl_groups = ~0;
|
||||
status = bind(fd_netlink, (struct sockaddr*)&localNET, sizeof(localNET));
|
||||
if (status) {
|
||||
int err = errno;
|
||||
close(fd_netlink);
|
||||
close(fd_ip);
|
||||
fprintf(stderr, _("%s: Cannot bind requested address to NETLINK socket: %s\n"),
|
||||
progname,
|
||||
strerror(err));
|
||||
return 1;
|
||||
}
|
||||
arg = fcntl(fd_ip, F_GETFL);
|
||||
fcntl(fd_ip, F_SETFL, arg | O_NONBLOCK);
|
||||
arg = fcntl(fd_netlink, F_GETFL);
|
||||
fcntl(fd_netlink, F_SETFL, arg | O_NONBLOCK);
|
||||
maxfd = fd_ip;
|
||||
if (fd_netlink > maxfd)
|
||||
maxfd = fd_netlink;
|
||||
FD_ZERO(&rcvset);
|
||||
|
||||
printf("Running...\n");
|
||||
|
||||
while (1) {
|
||||
FD_SET(fd_ip, &rcvset);
|
||||
FD_SET(fd_netlink, &rcvset);
|
||||
status = select(maxfd+1, &rcvset, NULL, NULL, NULL);
|
||||
if (status > 0) {
|
||||
if (FD_ISSET(fd_ip, &rcvset)) {
|
||||
struct sockaddr_in remoteIP;
|
||||
socklen_t remoteIPlen = sizeof(remoteIP);
|
||||
status = recvfrom(fd_ip, buffer.ipx, sizeof(buffer.ipx), 0, (struct sockaddr*)&remoteIP, &remoteIPlen);
|
||||
if (status > 0) {
|
||||
if (remoteIP.sin_port != htons(NOVELL_SCMD_PORT)) {
|
||||
/* invalid source port... faked? */
|
||||
} else if (remoteIP.sin_addr.s_addr != serveraddr) {
|
||||
/* invalid server... faked? */
|
||||
} else if (status < 2 + 2 + 1 + 1 + 12 + 12) {
|
||||
/* too short... */
|
||||
} else {
|
||||
int ipxLen = ntohs(*(u_int16_t*)(buffer.ipx+2));
|
||||
if (ipxLen > status) {
|
||||
/* too big... */
|
||||
} else {
|
||||
/* looks OK... */
|
||||
status += 2 + 6 + 6 + 2;
|
||||
|
||||
buffer.unknown = 0;
|
||||
buffer.type = htons(0x8137);
|
||||
buffer.src[0] = 0x7E;
|
||||
buffer.src[1] = 0x01;
|
||||
memcpy(buffer.src+2, &remoteIP.sin_addr.s_addr, 4);
|
||||
buffer.dst[0] = 0x7E;
|
||||
buffer.dst[1] = 0x01;
|
||||
memcpy(buffer.dst+2, &local, 4);
|
||||
{
|
||||
struct sockaddr_nl remoteNETLINK;
|
||||
int e;
|
||||
|
||||
remoteNETLINK.nl_family = AF_NETLINK;
|
||||
remoteNETLINK.nl_pid = 0;
|
||||
remoteNETLINK.nl_groups = 0;
|
||||
e = sendto(fd_netlink, &buffer, status, 0, (struct sockaddr*)&remoteNETLINK, sizeof(remoteNETLINK));
|
||||
if (e < 0)
|
||||
sendto(fd_netlink, &buffer, status, 0, (struct sockaddr*)&remoteNETLINK, sizeof(remoteNETLINK));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (FD_ISSET(fd_netlink, &rcvset)) {
|
||||
struct sockaddr_in remoteNETLINK;
|
||||
socklen_t remoteNETLINKlen = sizeof(remoteNETLINK);
|
||||
status = recvfrom(fd_netlink, &buffer, sizeof(buffer), 0, (struct sockaddr*)&remoteNETLINK, &remoteNETLINKlen);
|
||||
if (status > 0) {
|
||||
if (status < 2 + 6 + 6 + 2 + 2 + 2 + 1 + 1 + 12 + 12) {
|
||||
/* too short... faked? */
|
||||
} else if (buffer.type != htons(0x8137)) {
|
||||
/* invalid frame */
|
||||
} else {
|
||||
int ipxLen = ntohs(*(u_int16_t*)(buffer.ipx+2));
|
||||
status -= 2 + 6 + 6 + 2;
|
||||
if (ipxLen > status) {
|
||||
/* too big... */
|
||||
} else {
|
||||
/* looks OK... */
|
||||
{
|
||||
struct sockaddr_in remoteIP;
|
||||
int e;
|
||||
|
||||
remoteIP.sin_family = AF_INET;
|
||||
remoteIP.sin_addr.s_addr = serveraddr;
|
||||
remoteIP.sin_port = htons(NOVELL_SCMD_PORT);
|
||||
e = sendto(fd_ip, buffer.ipx, status, 0, (struct sockaddr*)&remoteIP, sizeof(remoteIP));
|
||||
if (e < 0)
|
||||
sendto(fd_ip, buffer.ipx, status, 0, (struct sockaddr*)&remoteIP, sizeof(remoteIP));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
close(fd_netlink);
|
||||
close(fd_ip);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,131 +1,168 @@
|
||||
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
|
||||
*
|
||||
|
||||
* See file COPYING for details.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <getopt.h> /* must be before stdio/unistd, otherwise multiple declaration warning is shown */
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <getopt.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <netipx/ipx.h>
|
||||
#include <string.h>
|
||||
#include <ncp/kernel/ipx.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include "nls.h"
|
||||
|
||||
struct option options[] = {
|
||||
{ "auto_primary", required_argument, NULL, 1 },
|
||||
{ "auto_interface", required_argument, NULL, 2 },
|
||||
{ "help", no_argument, NULL, 3},
|
||||
{ NULL, 0, NULL, 0 }
|
||||
struct option options[] =
|
||||
{
|
||||
{ "auto_primary", required_argument, NULL, 'p'},
|
||||
{ "auto-primary", required_argument, NULL, 'p'},
|
||||
{ "auto_interface", required_argument, NULL, 'i'},
|
||||
{ "auto-interface", required_argument, NULL, 'i'},
|
||||
{ "help", no_argument, NULL, 'h'},
|
||||
{ NULL, 0, NULL, 0}
|
||||
};
|
||||
|
||||
char *progname;
|
||||
static char *progname;
|
||||
|
||||
void
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: %s --auto_primary=[on|off]\n\
|
||||
Usage: %s --auto_interface=[on|off]\n\
|
||||
Usage: %s --help\n\
|
||||
Usage: %s\n", progname, progname, progname, progname);
|
||||
fprintf(stderr,
|
||||
_("Usage: %s --auto_primary=[on|off]\n"
|
||||
"Usage: %s --auto_interface=[on|off]\n"
|
||||
"Usage: %s --help\n"
|
||||
"Usage: %s\n"), progname, progname, progname, progname);
|
||||
}
|
||||
|
||||
int
|
||||
map_string_to_bool(char *optarg)
|
||||
static int
|
||||
map_string_to_bool(char *opt)
|
||||
{
|
||||
if ((strcasecmp(optarg, "ON") == 0) ||
|
||||
(strcasecmp(optarg, "TRUE") == 0) ||
|
||||
(strcasecmp(optarg, "SET") == 0) ||
|
||||
(strcasecmp(optarg, "YES") == 0)) {
|
||||
/* TODO: YES/NO VALUE FROM LIBC */
|
||||
if ((strcasecmp(opt, "ON") == 0) ||
|
||||
(strcasecmp(opt, "TRUE") == 0) ||
|
||||
(strcasecmp(opt, "SET") == 0) ||
|
||||
(strcasecmp(opt, "YES") == 0) ||
|
||||
(strcasecmp(opt, "1") == 0))
|
||||
{
|
||||
return 1;
|
||||
} else if ((strcasecmp(optarg, "OFF") == 0) ||
|
||||
(strcasecmp(optarg, "FALSE") == 0) ||
|
||||
(strcasecmp(optarg, "CLEAR") == 0) ||
|
||||
(strcasecmp(optarg, "NO") == 0)) {
|
||||
} else if ((strcasecmp(opt, "OFF") == 0) ||
|
||||
(strcasecmp(opt, "FALSE") == 0) ||
|
||||
(strcasecmp(opt, "CLEAR") == 0) ||
|
||||
(strcasecmp(opt, "NO") == 0) ||
|
||||
(strcasecmp(opt, "0") == 0))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int s;
|
||||
int result;
|
||||
char errmsg[80];
|
||||
char val;
|
||||
int option_index = 0;
|
||||
int got_auto_pri = 0;
|
||||
int got_auto_itf = 0;
|
||||
ipx_config_data data;
|
||||
int s;
|
||||
int result;
|
||||
int val;
|
||||
int got_auto_pri = 0;
|
||||
int got_auto_itf = 0;
|
||||
ipx_config_data data;
|
||||
|
||||
progname = argv[0];
|
||||
setlocale(LC_ALL, "");
|
||||
#if defined(HAVE_BINDTEXTDOMAIN) && defined(HAVE_TEXTDOMAIN)
|
||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
textdomain(PACKAGE);
|
||||
#endif
|
||||
|
||||
progname = argv[0];
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
sprintf(errmsg, "%s: socket", progname);
|
||||
perror(errmsg);
|
||||
if (s < 0)
|
||||
{
|
||||
int old_errno = errno;
|
||||
fprintf(stderr, _("%s: socket: %s\n"), progname, strerror(errno));
|
||||
if (old_errno == -EINVAL)
|
||||
{
|
||||
fprintf(stderr, _("Probably you have no IPX support in "
|
||||
"your kernel\n"));
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
while ((result = getopt_long(argc, argv, "", options,
|
||||
&option_index)) != -1) {
|
||||
switch (result) {
|
||||
case 1:
|
||||
while ((result = getopt_long(argc, argv, "hi:p:", options,
|
||||
NULL)) != -1)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
case 'p':
|
||||
if (got_auto_pri)
|
||||
break;
|
||||
got_auto_pri++;
|
||||
|
||||
|
||||
val = map_string_to_bool(optarg);
|
||||
if (val < 0) {
|
||||
if (val < 0)
|
||||
{
|
||||
usage();
|
||||
exit(-1);
|
||||
}
|
||||
{
|
||||
unsigned char v = val;
|
||||
|
||||
result = ioctl(s, SIOCAIPXPRISLT, &val);
|
||||
if (result < 0) {
|
||||
perror(errmsg);
|
||||
result = ioctl(s, SIOCAIPXPRISLT, &v);
|
||||
}
|
||||
if (result < 0)
|
||||
{
|
||||
fprintf(stderr, _("%s: ioctl: %s\n"), progname,
|
||||
strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (got_auto_itf)
|
||||
case 'i':
|
||||
if (got_auto_itf)
|
||||
break;
|
||||
got_auto_itf++;
|
||||
|
||||
val = map_string_to_bool(optarg);
|
||||
if (val < 0) {
|
||||
if (val < 0)
|
||||
{
|
||||
usage();
|
||||
exit(-1);
|
||||
}
|
||||
{
|
||||
unsigned char v = val;
|
||||
|
||||
result = ioctl(s, SIOCAIPXITFCRT, &val);
|
||||
if (result < 0) {
|
||||
perror(errmsg);
|
||||
result = ioctl(s, SIOCAIPXITFCRT, &v);
|
||||
}
|
||||
if (result < 0)
|
||||
{
|
||||
fprintf(stderr, _("%s: ioctl: %s\n"), progname,
|
||||
strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
case 'h':
|
||||
usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
result = ioctl(s, SIOCIPXCFGDATA, &data);
|
||||
if (result < 0) {
|
||||
perror(errmsg);
|
||||
exit(-1);
|
||||
if (result < 0)
|
||||
{
|
||||
fprintf(stderr, _("%s: ioctl: %s\n"), progname,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (argc == 1) {
|
||||
fprintf(stdout, "Auto Primary Select is %s\n\
|
||||
Auto Interface Create is %s\n",
|
||||
(data.ipxcfg_auto_select_primary) ? "ON" : "OFF",
|
||||
(data.ipxcfg_auto_create_interfaces) ? "ON" : "OFF");
|
||||
if (argc == 1)
|
||||
{
|
||||
fprintf(stdout, _("Auto Primary Select is %s\n"
|
||||
"Auto Interface Create is %s\n"),
|
||||
(data.ipxcfg_auto_select_primary) ? _("ON") : _("OFF"),
|
||||
(data.ipxcfg_auto_create_interfaces) ? _("ON") : _("OFF"));
|
||||
}
|
||||
exit(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
|
||||
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
|
||||
*
|
||||
|
||||
* See file COPYING for details.
|
||||
*/
|
||||
|
||||
@@ -10,389 +11,452 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netipx/ipx.h>
|
||||
#include <linux/if.h>
|
||||
#include <ncp/kernel/ipx.h>
|
||||
#include <ncp/kernel/if.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
static struct ifreq id;
|
||||
static char *progname;
|
||||
#include "ipxutil.h"
|
||||
|
||||
void
|
||||
#include "nls.h"
|
||||
|
||||
static struct ifreq id;
|
||||
static char *progname;
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s add [-p] device frame_type [net_number]\n\
|
||||
Usage: %s del device frame_type\n\
|
||||
Usage: %s delall\n\
|
||||
Usage: %s check device frame_type\n", progname, progname, progname, progname);
|
||||
exit(-1);
|
||||
fprintf(stderr,
|
||||
_("Usage: %s add [-p] device frame_type [net_number[:node]]\n"
|
||||
"Usage: %s del device frame_type\n"
|
||||
"Usage: %s delall\n"
|
||||
"Usage: %s check device frame_type\n"),
|
||||
progname, progname, progname, progname);
|
||||
}
|
||||
|
||||
struct frame_type {
|
||||
char *ft_name;
|
||||
unsigned char ft_val;
|
||||
} frame_types[] = {
|
||||
{"802.2", IPX_FRAME_8022},
|
||||
struct frame_type
|
||||
{
|
||||
const char *ft_name;
|
||||
unsigned char ft_val;
|
||||
}
|
||||
frame_types[] =
|
||||
{
|
||||
{
|
||||
"802.2", IPX_FRAME_8022
|
||||
}
|
||||
,
|
||||
#ifdef IPX_FRAME_TR_8022
|
||||
{"802.2TR", IPX_FRAME_TR_8022},
|
||||
{
|
||||
"802.2TR", IPX_FRAME_TR_8022
|
||||
}
|
||||
,
|
||||
#endif
|
||||
{"802.3", IPX_FRAME_8023},
|
||||
{"SNAP", IPX_FRAME_SNAP},
|
||||
{"EtherII", IPX_FRAME_ETHERII}
|
||||
{
|
||||
"802.3", IPX_FRAME_8023
|
||||
}
|
||||
,
|
||||
{
|
||||
"SNAP", IPX_FRAME_SNAP
|
||||
}
|
||||
,
|
||||
{
|
||||
"EtherII", IPX_FRAME_ETHERII
|
||||
}
|
||||
};
|
||||
|
||||
#define NFTYPES (sizeof(frame_types)/sizeof(struct frame_type))
|
||||
|
||||
int
|
||||
static int
|
||||
lookup_frame_type(char *frame)
|
||||
{
|
||||
size_t j;
|
||||
size_t j;
|
||||
|
||||
for (j = 0; (j < NFTYPES) &&
|
||||
(strcasecmp(frame_types[j].ft_name, frame));
|
||||
j++)
|
||||
for (j = 0; (j < NFTYPES) &&
|
||||
(strcasecmp(frame_types[j].ft_name, frame));
|
||||
j++)
|
||||
;
|
||||
|
||||
if (j != NFTYPES)
|
||||
return j;
|
||||
|
||||
fprintf(stderr, "%s: Frame type must be", progname);
|
||||
for (j = 0; j < NFTYPES; j++) {
|
||||
fprintf(stderr, "%s%s",
|
||||
(j == NFTYPES-1) ? " or " : " ",
|
||||
fprintf(stderr, _("%s: Frame type must be"), progname);
|
||||
for (j = 0; j < NFTYPES; j++)
|
||||
{
|
||||
fprintf(stderr, "%s%s",
|
||||
(j == NFTYPES - 1) ? _(" or ") : " ",
|
||||
frame_types[j].ft_name);
|
||||
}
|
||||
fprintf(stderr, ".\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
ipx_add_interface(int argc, char **argv)
|
||||
{
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
unsigned long netnum;
|
||||
char errmsg[80];
|
||||
int i, fti = 0;
|
||||
int c;
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
int i, fti = 0;
|
||||
int c;
|
||||
|
||||
sipx->sipx_special = IPX_SPECIAL_NONE;
|
||||
sipx->sipx_network = 0L;
|
||||
memset(sipx->sipx_node, 0, sizeof(sipx->sipx_node));
|
||||
sipx->sipx_type = IPX_FRAME_NONE;
|
||||
while ((c = getopt(argc, argv, "p")) > 0) {
|
||||
switch (c) {
|
||||
case 'p': sipx->sipx_special = IPX_PRIMARY; break;
|
||||
while ((c = getopt(argc, argv, "p")) > 0)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'p':
|
||||
sipx->sipx_special = IPX_PRIMARY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (((i = (argc - optind)) < 2) || (i > 3)) {
|
||||
if (((i = (argc - optind)) < 2) || (i > 3))
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = optind; i < argc; i++) {
|
||||
switch (i-optind) {
|
||||
for (i = optind; i < argc; i++)
|
||||
{
|
||||
switch (i - optind)
|
||||
{
|
||||
case 0: /* Physical Device - Required */
|
||||
strcpy(id.ifr_name, argv[i]);
|
||||
break;
|
||||
case 1: /* Frame Type - Required */
|
||||
case 1: /* Frame Type - Required */
|
||||
fti = lookup_frame_type(argv[i]);
|
||||
if (fti < 0)
|
||||
exit(-1);
|
||||
if (fti < 0) {
|
||||
return -1;
|
||||
}
|
||||
sipx->sipx_type = frame_types[fti].ft_val;
|
||||
break;
|
||||
|
||||
case 2: /* Network Number - Optional */
|
||||
netnum = strtoul(argv[i], (char **)NULL, 16);
|
||||
if (netnum == 0xffffffffL) {
|
||||
fprintf(stderr,
|
||||
"%s: Inappropriate network number %08lX\n",
|
||||
progname, netnum);
|
||||
exit(-1);
|
||||
case 2: /* Network Number - Optional */
|
||||
sscanf_ipx_addr(sipx, argv[i], SSIPX_NETWORK | SSIPX_NODE);
|
||||
if (sipx->sipx_network == htonl(0xffffffffL))
|
||||
{
|
||||
fprintf(stderr,
|
||||
_("%s: Inappropriate network number %08lX\n"),
|
||||
progname, (unsigned long)ntohl(sipx->sipx_network));
|
||||
return -1;
|
||||
}
|
||||
sipx->sipx_network = htonl(netnum);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
sprintf(errmsg, "%s: socket", progname);
|
||||
perror(errmsg);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0)
|
||||
{
|
||||
int old_errno = errno;
|
||||
fprintf(stderr, _("%s: socket: %s\n"), progname,
|
||||
strerror(errno));
|
||||
if (old_errno == -EINVAL)
|
||||
{
|
||||
fprintf(stderr, _("Probably you have no IPX support in "
|
||||
"your kernel\n"));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
i = 0;
|
||||
sipx->sipx_family = AF_IPX;
|
||||
sipx->sipx_action = IPX_CRTITF;
|
||||
do {
|
||||
do
|
||||
{
|
||||
result = ioctl(s, SIOCSIFADDR, &id);
|
||||
i++;
|
||||
} while ((i < 5) && (result < 0) && (errno == EAGAIN));
|
||||
}
|
||||
while ((i < 5) && (result < 0) && (errno == EAGAIN));
|
||||
|
||||
if (result == 0) exit(0);
|
||||
|
||||
switch (errno) {
|
||||
if (result == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (errno)
|
||||
{
|
||||
case EEXIST:
|
||||
fprintf(stderr, "%s: Primary network already selected.\n",
|
||||
fprintf(stderr, _("%s: Primary network already selected.\n"),
|
||||
progname);
|
||||
break;
|
||||
case EADDRINUSE:
|
||||
fprintf(stderr, "%s: Network number (%08X) already in use.\n",
|
||||
progname, htonl(sipx->sipx_network));
|
||||
fprintf(stderr, _("%s: Network number (%08X) already in use.\n"),
|
||||
progname, (u_int32_t)htonl(sipx->sipx_network));
|
||||
break;
|
||||
case EPROTONOSUPPORT:
|
||||
fprintf(stderr, "%s: Invalid frame type (%s).\n",
|
||||
fprintf(stderr, _("%s: Invalid frame type (%s).\n"),
|
||||
progname, frame_types[fti].ft_name);
|
||||
break;
|
||||
case ENODEV:
|
||||
fprintf(stderr, "%s: No such device (%s).\n", progname,
|
||||
fprintf(stderr, _("%s: No such device (%s).\n"), progname,
|
||||
id.ifr_name);
|
||||
break;
|
||||
case ENETDOWN:
|
||||
fprintf(stderr, "%s: Requested device (%s) is down.\n", progname,
|
||||
fprintf(stderr, _("%s: Requested device (%s) is down.\n"), progname,
|
||||
id.ifr_name);
|
||||
break;
|
||||
case EINVAL:
|
||||
fprintf(stderr, "%s: Invalid device (%s).\n", progname,
|
||||
fprintf(stderr, _("%s: Invalid device (%s).\n"), progname,
|
||||
id.ifr_name);
|
||||
break;
|
||||
case EAGAIN:
|
||||
fprintf(stderr,
|
||||
"%s: Insufficient memory to create interface.\n",
|
||||
fprintf(stderr,
|
||||
_("%s: Insufficient memory to create interface.\n"),
|
||||
progname);
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
fprintf(stderr, _("%s: ioctl: %s\n"), progname,
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
exit(-1);
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
ipx_delall_interface(void)
|
||||
static int
|
||||
ipx_delall_interface(int argc __attribute__((unused)), char **argv __attribute__((unused)))
|
||||
{
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
char errmsg[80];
|
||||
char buffer[80];
|
||||
char device[20];
|
||||
char frame_type[20];
|
||||
int fti;
|
||||
FILE *fp;
|
||||
char *ret;
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
char buffer[80];
|
||||
char device[20];
|
||||
char frame_type[20];
|
||||
int fti;
|
||||
FILE *fp;
|
||||
char *ret;
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
sprintf(errmsg, "%s: socket", progname);
|
||||
perror(errmsg);
|
||||
exit(-1);
|
||||
if (s < 0)
|
||||
{
|
||||
fprintf(stderr, _("%s: socket: %s\n"), progname,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
fp = fopen("/proc/net/ipx_interface", "r");
|
||||
if (!fp) {
|
||||
fp = fopen("/proc/net/ipx/interface", "r");
|
||||
}
|
||||
|
||||
fp = fopen("/proc/net/ipx/interface", "r");
|
||||
if (fp == NULL)
|
||||
fp = fopen("/proc/net/ipx_interface", "r");
|
||||
if (fp == NULL) {
|
||||
{
|
||||
close(s);
|
||||
fprintf(stderr,
|
||||
"%s: Unable to open \"/proc/net/ipx_interface.\"\n",
|
||||
progname);
|
||||
exit(-1);
|
||||
_("%s: Unable to open \"%s.\"\n"),
|
||||
progname,
|
||||
"/proc/net/ipx_interface");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = fgets(buffer, 80, fp);
|
||||
if (ret == NULL) {
|
||||
fprintf(stderr,
|
||||
"%s: Unable to read \"/proc/net/ipx_interface.\"\n",
|
||||
progname);
|
||||
"%s: Unable to read \"/proc/net/ipx_interface.\"\n",
|
||||
progname);
|
||||
exit(-1);
|
||||
}
|
||||
while (fscanf(fp, "%s %s %s %s %s", buffer, buffer, buffer,
|
||||
device, frame_type) == 5) {
|
||||
device, frame_type) == 5)
|
||||
{
|
||||
|
||||
sipx->sipx_network = 0L;
|
||||
if (strcasecmp(device, "Internal") == 0) {
|
||||
if (strcasecmp(device, "Internal") == 0)
|
||||
{
|
||||
sipx->sipx_special = IPX_INTERNAL;
|
||||
} else {
|
||||
} else
|
||||
{
|
||||
sipx->sipx_special = IPX_SPECIAL_NONE;
|
||||
strcpy(id.ifr_name, device);
|
||||
fti = lookup_frame_type(frame_type);
|
||||
if (fti < 0) continue;
|
||||
if (fti < 0)
|
||||
continue;
|
||||
sipx->sipx_type = frame_types[fti].ft_val;
|
||||
}
|
||||
|
||||
sipx->sipx_action = IPX_DLTITF;
|
||||
sipx->sipx_family = AF_IPX;
|
||||
result = ioctl(s, SIOCSIFADDR, &id);
|
||||
if (result == 0) continue;
|
||||
switch (errno) {
|
||||
if (result == 0)
|
||||
continue;
|
||||
switch (errno)
|
||||
{
|
||||
case EPROTONOSUPPORT:
|
||||
fprintf(stderr, "%s: Invalid frame type (%s).\n",
|
||||
fprintf(stderr, _("%s: Invalid frame type (%s).\n"),
|
||||
progname, frame_type);
|
||||
break;
|
||||
case ENODEV:
|
||||
fprintf(stderr, "%s: No such device (%s).\n",
|
||||
fprintf(stderr, _("%s: No such device (%s).\n"),
|
||||
progname, device);
|
||||
break;
|
||||
case EINVAL:
|
||||
fprintf(stderr, "%s: No such IPX interface %s %s.\n",
|
||||
fprintf(stderr, _("%s: No such IPX interface %s %s.\n"),
|
||||
progname, device, frame_type);
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
fprintf(stderr, _("%s: ioctl: %s\n"), progname,
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
exit(0);
|
||||
fclose(fp);
|
||||
close(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
ipx_del_interface(int argc, char **argv)
|
||||
{
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
char errmsg[80];
|
||||
int fti;
|
||||
|
||||
if (argc != 3) {
|
||||
usage();
|
||||
}
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
int fti;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
sipx->sipx_network = 0L;
|
||||
sipx->sipx_special = IPX_SPECIAL_NONE;
|
||||
strcpy(id.ifr_name, argv[1]);
|
||||
fti = lookup_frame_type(argv[2]);
|
||||
if (fti < 0)
|
||||
exit(-1);
|
||||
strcpy(id.ifr_name, argv[0]);
|
||||
fti = lookup_frame_type(argv[1]);
|
||||
if (fti < 0) {
|
||||
return -1;
|
||||
}
|
||||
sipx->sipx_type = frame_types[fti].ft_val;
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
sprintf(errmsg, "%s: socket", progname);
|
||||
perror(errmsg);
|
||||
exit(-1);
|
||||
if (s < 0)
|
||||
{
|
||||
fprintf(stderr, _("%s: socket: %s\n"), progname,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
sipx->sipx_action = IPX_DLTITF;
|
||||
sipx->sipx_family = AF_IPX;
|
||||
result = ioctl(s, SIOCSIFADDR, &id);
|
||||
if (result == 0) exit(0);
|
||||
if (result == 0) {
|
||||
close(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (errno) {
|
||||
switch (errno)
|
||||
{
|
||||
case EPROTONOSUPPORT:
|
||||
fprintf(stderr, "%s: Invalid frame type (%s).\n",
|
||||
fprintf(stderr, _("%s: Invalid frame type (%s).\n"),
|
||||
progname, frame_types[fti].ft_name);
|
||||
break;
|
||||
case ENODEV:
|
||||
fprintf(stderr, "%s: No such device (%s).\n", progname,
|
||||
fprintf(stderr, _("%s: No such device (%s).\n"), progname,
|
||||
id.ifr_name);
|
||||
break;
|
||||
case EINVAL:
|
||||
fprintf(stderr, "%s: No such IPX interface %s %s.\n", progname,
|
||||
fprintf(stderr, _("%s: No such IPX interface %s %s.\n"), progname,
|
||||
id.ifr_name, frame_types[fti].ft_name);
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
fprintf(stderr, _("%s: ioctl: %s\n"), progname,
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
exit(-1);
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
ipx_check_interface(int argc, char **argv)
|
||||
{
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
char errmsg[80];
|
||||
int fti;
|
||||
|
||||
if (argc != 3) {
|
||||
usage();
|
||||
}
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
int fti;
|
||||
|
||||
if (argc != 2)
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
sipx->sipx_network = 0L;
|
||||
strcpy(id.ifr_name, argv[1]);
|
||||
fti = lookup_frame_type(argv[2]);
|
||||
if (fti < 0)
|
||||
exit(-1);
|
||||
strcpy(id.ifr_name, argv[0]);
|
||||
fti = lookup_frame_type(argv[1]);
|
||||
if (fti < 0) {
|
||||
return -1;
|
||||
}
|
||||
sipx->sipx_type = frame_types[fti].ft_val;
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
sprintf(errmsg, "%s: socket", progname);
|
||||
perror(errmsg);
|
||||
exit(-1);
|
||||
if (s < 0)
|
||||
{
|
||||
fprintf(stderr, _("%s: socket: %s\n"), progname,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
sipx->sipx_family = AF_IPX;
|
||||
result = ioctl(s, SIOCGIFADDR, &id);
|
||||
if (result == 0) {
|
||||
if (result == 0)
|
||||
{
|
||||
close(s);
|
||||
printf(
|
||||
"IPX Address for (%s, %s) is %08X:%02X%02X%02X%02X%02X%02X.\n",
|
||||
argv[1], frame_types[fti].ft_name,
|
||||
htonl(sipx->sipx_network), sipx->sipx_node[0],
|
||||
sipx->sipx_node[1], sipx->sipx_node[2],
|
||||
sipx->sipx_node[3], sipx->sipx_node[4],
|
||||
sipx->sipx_node[5]);
|
||||
exit(0);
|
||||
_("IPX Address for (%s, %s) is %08X:%02X%02X%02X%02X%02X%02X.\n"),
|
||||
argv[1], frame_types[fti].ft_name,
|
||||
(u_int32_t)htonl(sipx->sipx_network), sipx->sipx_node[0],
|
||||
sipx->sipx_node[1], sipx->sipx_node[2],
|
||||
sipx->sipx_node[3], sipx->sipx_node[4],
|
||||
sipx->sipx_node[5]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (errno) {
|
||||
switch (errno)
|
||||
{
|
||||
case EPROTONOSUPPORT:
|
||||
fprintf(stderr, "%s: Invalid frame type (%s).\n",
|
||||
fprintf(stderr, _("%s: Invalid frame type (%s).\n"),
|
||||
progname, frame_types[fti].ft_name);
|
||||
break;
|
||||
case ENODEV:
|
||||
fprintf(stderr, "%s: No such device (%s).\n", progname,
|
||||
fprintf(stderr, _("%s: No such device (%s).\n"), progname,
|
||||
id.ifr_name);
|
||||
break;
|
||||
case EADDRNOTAVAIL:
|
||||
fprintf(stderr, "%s: No such IPX interface %s %s.\n", progname,
|
||||
fprintf(stderr, _("%s: No such IPX interface %s %s.\n"), progname,
|
||||
id.ifr_name, frame_types[fti].ft_name);
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
fprintf(stderr, _("%s: ioctl: %s\n"), progname,
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
exit(-1);
|
||||
close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
int i;
|
||||
|
||||
progname = argv[0];
|
||||
if (argc < 2) {
|
||||
usage();
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (strncasecmp(argv[1], "add", 3) == 0) {
|
||||
for (i = 1; i < (argc-1); i++)
|
||||
argv[i] = argv[i+1];
|
||||
ipx_add_interface(argc-1, argv);
|
||||
} else if (strncasecmp(argv[1], "delall", 6) == 0) {
|
||||
if (argc > 2) {
|
||||
usage();
|
||||
exit(-1);
|
||||
}
|
||||
ipx_delall_interface();
|
||||
} else if (strncasecmp(argv[1], "del", 3) == 0) {
|
||||
for (i = 1; i < (argc-1); i++)
|
||||
argv[i] = argv[i+1];
|
||||
ipx_del_interface(argc-1, argv);
|
||||
} else if (strncasecmp(argv[1], "check", 5) == 0) {
|
||||
for (i = 1; i < (argc-1); i++)
|
||||
argv[i] = argv[i+1];
|
||||
ipx_check_interface(argc-1, argv);
|
||||
}
|
||||
setlocale(LC_ALL, "");
|
||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
textdomain(PACKAGE);
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
if (strcasecmp(argv[1], "add") == 0)
|
||||
{
|
||||
for (i = 1; i < (argc - 1); i++)
|
||||
argv[i] = argv[i + 1];
|
||||
return ipx_add_interface(argc - 1, argv);
|
||||
} else if (strcasecmp(argv[1], "delall") == 0)
|
||||
{
|
||||
return ipx_delall_interface(argc - 2, argv + 2);
|
||||
} else if (strcasecmp(argv[1], "del") == 0)
|
||||
{
|
||||
return ipx_del_interface(argc - 2, argv + 2);
|
||||
} else if (strcasecmp(argv[1], "check") == 0)
|
||||
{
|
||||
return ipx_check_interface(argc - 2, argv + 2);
|
||||
}
|
||||
usage();
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
|
||||
*
|
||||
|
||||
* See file COPYING for details.
|
||||
*/
|
||||
|
||||
@@ -9,193 +9,176 @@
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netipx/ipx.h>
|
||||
#include <linux/if.h>
|
||||
#include <ncp/kernel/ipx.h>
|
||||
#include <ncp/kernel/if.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
static struct ifreq id;
|
||||
static char *progname;
|
||||
#include "ipxutil.h"
|
||||
|
||||
void
|
||||
#include "nls.h"
|
||||
|
||||
static struct ifreq id;
|
||||
static char *progname;
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s add net_number(hex) node(hex)\n\
|
||||
Usage: %s del\n", progname, progname);
|
||||
exit(-1);
|
||||
fprintf(stderr, _("Usage: %s add net_number(hex) node(hex)\n"
|
||||
"Usage: %s del\n"),
|
||||
progname, progname);
|
||||
}
|
||||
|
||||
int
|
||||
map_char_to_val(char dig)
|
||||
{
|
||||
char digit = tolower(dig);
|
||||
if ((digit >= '0') && (digit <= '9')) {
|
||||
return digit - '0';
|
||||
} else if ((digit >= 'a') && (digit <= 'f')) {
|
||||
return (10 + (digit - 'a'));
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
ipx_add_internal_net(int argc, char **argv)
|
||||
{
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
unsigned long netnum;
|
||||
char errmsg[80];
|
||||
int nodelen;
|
||||
char *node;
|
||||
char tmpnode[13];
|
||||
unsigned char *tout;
|
||||
char *tin;
|
||||
int i;
|
||||
|
||||
if (argc != 3) {
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
unsigned long netnum;
|
||||
int i;
|
||||
|
||||
if (argc < 1)
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
|
||||
netnum = strtoul(argv[1], (char **)NULL, 16);
|
||||
if ((netnum == 0L) || (netnum == 0xffffffffL)) {
|
||||
fprintf(stderr, "%s: Inappropriate network number %08lX\n",
|
||||
i = sscanf_ipx_addr(sipx, argv[0], SSIPX_NETWORK|SSIPX_NODE);
|
||||
if (!(i & SSIPX_NETWORK)) {
|
||||
fprintf(stderr, _("%s: Invalid internal network address %s\n"),
|
||||
progname, argv[0]);
|
||||
return -1;
|
||||
}
|
||||
if (!(i & SSIPX_NODE)) {
|
||||
if (argc < 2)
|
||||
memcpy(sipx->sipx_node, "\0\0\0\0\0\1", IPX_NODE_LEN);
|
||||
else if (sscanf_ipx_addr(sipx, argv[1], SSIPX_NODE) != SSIPX_NODE) {
|
||||
fprintf(stderr, _("%s: Invalid internal network node %s\n"),
|
||||
progname, argv[1]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
netnum = ntohl(sipx->sipx_network);
|
||||
if ((netnum == 0L) || (netnum == 0xffffffffL))
|
||||
{
|
||||
fprintf(stderr, _("%s: Inappropriate network number %08lX\n"),
|
||||
progname, netnum);
|
||||
exit(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
node = argv[2];
|
||||
nodelen = strlen(node);
|
||||
if (nodelen > 12) {
|
||||
fprintf(stderr, "%s: Node length is too long (> 12).\n", progname);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
for (i = 0; (i < nodelen) && isxdigit(node[i]); i++)
|
||||
;
|
||||
|
||||
if (i < nodelen) {
|
||||
fprintf(stderr, "%s: Invalid value in node, must be hex digits.\n",
|
||||
progname);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
strcpy(tmpnode, "000000000000");
|
||||
memcpy(&(tmpnode[12-nodelen]), node, nodelen);
|
||||
for (tin = tmpnode, tout = sipx->sipx_node; *tin != '\0'; tin += 2, tout++) {
|
||||
*tout = (unsigned char) map_char_to_val(*tin);
|
||||
*tout <<= 4;
|
||||
*tout |= (unsigned char) map_char_to_val(*(tin+1));
|
||||
}
|
||||
|
||||
if ((memcmp(sipx->sipx_node, "\0\0\0\0\0\0\0\0", IPX_NODE_LEN) == 0) ||
|
||||
(memcmp(sipx->sipx_node, "\377\377\377\377\377\377", IPX_NODE_LEN) == 0)){
|
||||
fprintf(stderr, "%s: Node is invalid.\n", progname);
|
||||
exit(-1);
|
||||
(memcmp(sipx->sipx_node, "\377\377\377\377\377\377", IPX_NODE_LEN) == 0))
|
||||
{
|
||||
fprintf(stderr, _("%s: Node is invalid.\n"), progname);
|
||||
return -1;
|
||||
}
|
||||
|
||||
sipx->sipx_network = htonl(netnum);
|
||||
sipx->sipx_type = IPX_FRAME_NONE;
|
||||
sipx->sipx_special = IPX_INTERNAL;
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
sprintf(errmsg, "%s: socket", progname);
|
||||
perror(errmsg);
|
||||
exit(-1);
|
||||
if (s < 0)
|
||||
{
|
||||
fprintf(stderr, _("%s: socket: %s\n"), progname,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
sipx->sipx_family = AF_IPX;
|
||||
sipx->sipx_action = IPX_CRTITF;
|
||||
i = 0;
|
||||
do {
|
||||
do
|
||||
{
|
||||
result = ioctl(s, SIOCSIFADDR, &id);
|
||||
i++;
|
||||
} while ((i < 5) && (result < 0) && (errno == EAGAIN));
|
||||
}
|
||||
while ((i < 5) && (result < 0) && (errno == EAGAIN));
|
||||
|
||||
if (result == 0) exit(0);
|
||||
|
||||
switch (errno) {
|
||||
if (result == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (errno)
|
||||
{
|
||||
case EEXIST:
|
||||
fprintf(stderr, "%s: Primary network already selected.\n",
|
||||
fprintf(stderr, _("%s: Primary network already selected.\n"),
|
||||
progname);
|
||||
break;
|
||||
case EADDRINUSE:
|
||||
fprintf(stderr, "%s: Network number (%08X) already in use.\n",
|
||||
progname, htonl(sipx->sipx_network));
|
||||
fprintf(stderr, _("%s: Network number (%08X) already in use.\n"),
|
||||
progname, (u_int32_t)htonl(sipx->sipx_network));
|
||||
break;
|
||||
case EAGAIN:
|
||||
fprintf(stderr,
|
||||
"%s: Insufficient memory to create internal net.\n",
|
||||
fprintf(stderr,
|
||||
_("%s: Insufficient memory to create internal net.\n"),
|
||||
progname);
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
fprintf(stderr, _("%s: ioctl: %s\n"), progname,
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
exit(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
ipx_del_internal_net(int argc, char **argv)
|
||||
static int
|
||||
ipx_del_internal_net(int argc, char **argv __attribute__((unused)))
|
||||
{
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)&id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
char errmsg[80];
|
||||
struct sockaddr_ipx *sipx = (struct sockaddr_ipx *) &id.ifr_addr;
|
||||
int s;
|
||||
int result;
|
||||
|
||||
(void)argv;
|
||||
if (argc != 1) {
|
||||
if (argc != 0)
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
|
||||
sipx->sipx_network = 0L;
|
||||
sipx->sipx_special = IPX_INTERNAL;
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
sprintf(errmsg, "%s: socket", progname);
|
||||
perror(errmsg);
|
||||
exit(-1);
|
||||
if (s < 0)
|
||||
{
|
||||
fprintf(stderr, _("%s: socket: %s\n"), progname,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
sipx->sipx_family = AF_IPX;
|
||||
sipx->sipx_action = IPX_DLTITF;
|
||||
result = ioctl(s, SIOCSIFADDR, &id);
|
||||
if (result == 0) exit(0);
|
||||
if (result == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (errno) {
|
||||
switch (errno)
|
||||
{
|
||||
case ENOENT:
|
||||
fprintf(stderr, "%s: No internal network configured.\n", progname);
|
||||
fprintf(stderr, _("%s: No internal network configured.\n"), progname);
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
fprintf(stderr, _("%s: ioctl: %s\n"), progname,
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
exit(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
textdomain(PACKAGE);
|
||||
|
||||
progname = argv[0];
|
||||
if (argc < 2) {
|
||||
if (argc < 2)
|
||||
{
|
||||
usage();
|
||||
exit(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strncasecmp(argv[1], "add", 3) == 0) {
|
||||
for (i = 1; i < (argc-1); i++)
|
||||
argv[i] = argv[i+1];
|
||||
ipx_add_internal_net(argc-1, argv);
|
||||
} else if (strncasecmp(argv[1], "del", 3) == 0) {
|
||||
for (i = 1; i < (argc-1); i++)
|
||||
argv[i] = argv[i+1];
|
||||
ipx_del_internal_net(argc-1, argv);
|
||||
if (strcasecmp(argv[1], "add") == 0)
|
||||
{
|
||||
return ipx_add_internal_net(argc - 2, argv + 2);
|
||||
} else if (strcasecmp(argv[1], "del") == 0)
|
||||
{
|
||||
return ipx_del_internal_net(argc - 2, argv + 2);
|
||||
}
|
||||
usage();
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
267
src/ipx_route.c
267
src/ipx_route.c
@@ -1,5 +1,6 @@
|
||||
|
||||
/* Copyright (c) 1995-1996 Caldera, Inc. All Rights Reserved.
|
||||
*
|
||||
|
||||
* See file COPYING for details.
|
||||
*/
|
||||
|
||||
@@ -10,211 +11,209 @@
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netipx/ipx.h>
|
||||
#include <ncp/kernel/ipx.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/route.h>
|
||||
#include <ncp/kernel/route.h>
|
||||
|
||||
static struct rtentry rd;
|
||||
static char *progname;
|
||||
#include "ipxutil.h"
|
||||
|
||||
int
|
||||
map_char_to_val(char dig)
|
||||
{
|
||||
char digit = tolower(dig);
|
||||
if ((digit >= '0') && (digit <= '9')) {
|
||||
return digit - '0';
|
||||
} else if ((digit >= 'a') && (digit <= 'f')) {
|
||||
return (10 + (digit - 'a'));
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#include "nls.h"
|
||||
|
||||
void
|
||||
static struct rtentry rd;
|
||||
static char *progname;
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: %s add network(hex) router_network(hex) router_node(hex)\n\
|
||||
Usage: %s del network(hex)\n", progname, progname);
|
||||
exit(-1);
|
||||
fprintf(stderr,
|
||||
_("Usage: %s add network(hex) router_network(hex) router_node(hex)\n"
|
||||
"Usage: %s del network(hex)\n"),
|
||||
progname, progname);
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
ipx_add_route(int argc, char **argv)
|
||||
{
|
||||
/* Router */
|
||||
struct sockaddr_ipx *sr = (struct sockaddr_ipx *)&rd.rt_gateway;
|
||||
struct sockaddr_ipx *sr = (struct sockaddr_ipx *) &rd.rt_gateway;
|
||||
/* Target */
|
||||
struct sockaddr_ipx *st = (struct sockaddr_ipx *)&rd.rt_dst;
|
||||
int s;
|
||||
int result;
|
||||
int nodelen;
|
||||
int i;
|
||||
unsigned long netnum;
|
||||
char errmsg[80];
|
||||
char *node;
|
||||
char *tin;
|
||||
char tmpnode[13];
|
||||
unsigned char *tout;
|
||||
|
||||
if (argc != 4)
|
||||
struct sockaddr_ipx *st = (struct sockaddr_ipx *) &rd.rt_dst;
|
||||
int s;
|
||||
int result;
|
||||
int val;
|
||||
int i;
|
||||
|
||||
if (argc < 2) {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Network Number */
|
||||
netnum = strtoul(argv[1], (char **)NULL, 16);
|
||||
if ((netnum == 0xffffffffL) || (netnum == 0L)) {
|
||||
fprintf(stderr, "%s: Inappropriate network number %08lX\n",
|
||||
progname, netnum);
|
||||
exit(-1);
|
||||
if (sscanf_ipx_addr(st, argv[0], SSIPX_NETWORK) != SSIPX_NETWORK) {
|
||||
fprintf(stderr, _("%s: Invalid network number %s\n"),
|
||||
progname, argv[0]);
|
||||
return -1;
|
||||
}
|
||||
if ((st->sipx_network == htonl(0xffffffffL)) ||
|
||||
(st->sipx_network == htonl(0L)))
|
||||
{
|
||||
fprintf(stderr, _("%s: Inappropriate network number %08lX\n"),
|
||||
progname, (unsigned long)ntohl(st->sipx_network));
|
||||
return -1;
|
||||
}
|
||||
rd.rt_flags = RTF_GATEWAY;
|
||||
st->sipx_network = htonl(netnum);
|
||||
|
||||
/* Router Network Number */
|
||||
netnum = strtoul(argv[2], (char **)NULL, 16);
|
||||
if ((netnum == 0xffffffffL) || (netnum == 0L)) {
|
||||
fprintf(stderr, "%s: Inappropriate network number %08lX\n",
|
||||
progname, netnum);
|
||||
val = sscanf_ipx_addr(sr, argv[1], SSIPX_NETWORK|SSIPX_NODE);
|
||||
if (!(val & SSIPX_NETWORK)) {
|
||||
fprintf(stderr, _("%s: Invalid router address %s\n"),
|
||||
progname, argv[1]);
|
||||
return -1;
|
||||
}
|
||||
if (!(val & SSIPX_NODE)) {
|
||||
if ((argc < 3) ||
|
||||
(sscanf_ipx_addr(sr, argv[2], SSIPX_NODE) != SSIPX_NODE)) {
|
||||
fprintf(stderr, _("%s: Invalid router node %s\n"),
|
||||
progname, argv[2]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if ((sr->sipx_network == htonl(0xffffffffL)) ||
|
||||
(sr->sipx_network == htonl(0L)))
|
||||
{
|
||||
fprintf(stderr, _("%s: Inappropriate network number %08lX\n"),
|
||||
progname, (unsigned long)htonl(sr->sipx_network));
|
||||
exit(-1);
|
||||
}
|
||||
sr->sipx_network = htonl(netnum);
|
||||
|
||||
/* Router Node */
|
||||
node = argv[3];
|
||||
nodelen = strlen(node);
|
||||
if (nodelen > 12) {
|
||||
fprintf(stderr, "%s: Node length is too long (> 12).\n",
|
||||
progname);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
for (i = 0; (i < nodelen) && isxdigit(node[i]); i++)
|
||||
;
|
||||
|
||||
if (i < nodelen) {
|
||||
fprintf(stderr, "%s: Invalid value in node, must be hex digits.\n",
|
||||
progname);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
strcpy(tmpnode, "000000000000");
|
||||
memcpy(&(tmpnode[12-nodelen]), node, nodelen);
|
||||
for (tin = tmpnode, tout = sr->sipx_node; *tin != '\0'; tin += 2, tout++) {
|
||||
*tout = (unsigned char) map_char_to_val(*tin);
|
||||
*tout <<= 4;
|
||||
*tout |= (unsigned char) map_char_to_val(*(tin+1));
|
||||
}
|
||||
|
||||
if ((memcmp(sr->sipx_node, "\0\0\0\0\0\0\0\0", IPX_NODE_LEN) == 0) ||
|
||||
(memcmp(sr->sipx_node, "\377\377\377\377\377\377", IPX_NODE_LEN) == 0)){
|
||||
fprintf(stderr, "%s: Node (%s) is invalid.\n", progname, tmpnode);
|
||||
(memcmp(sr->sipx_node, "\377\377\377\377\377\377", IPX_NODE_LEN) == 0))
|
||||
{
|
||||
char tmpnode[IPX_NODE_LEN*2+1];
|
||||
|
||||
for (i = 0; i < IPX_NODE_LEN; i++)
|
||||
sprintf(tmpnode+i*2, "%02X", sr->sipx_node[i]);
|
||||
fprintf(stderr, _("%s: Node (%s) is invalid.\n"), progname, tmpnode);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
sprintf(errmsg, "%s: socket", progname);
|
||||
perror(errmsg);
|
||||
if (s < 0)
|
||||
{
|
||||
fprintf(stderr, _("%s: socket: %s\n"), progname,
|
||||
strerror(errno));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
sr->sipx_family = st->sipx_family = AF_IPX;
|
||||
i = 0;
|
||||
do {
|
||||
do
|
||||
{
|
||||
result = ioctl(s, SIOCADDRT, &rd);
|
||||
i++;
|
||||
} while ((i < 5) && (result < 0) && (errno == EAGAIN));
|
||||
}
|
||||
while ((i < 5) && (result < 0) && (errno == EAGAIN));
|
||||
|
||||
if (result == 0) exit(0);
|
||||
if (result == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (errno) {
|
||||
switch (errno)
|
||||
{
|
||||
case ENETUNREACH:
|
||||
fprintf(stderr, "%s: Router network (%08X) not reachable.\n",
|
||||
progname, htonl(sr->sipx_network));
|
||||
fprintf(stderr, _("%s: Router network (%08X) not reachable.\n"),
|
||||
progname, (u_int32_t)htonl(sr->sipx_network));
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
fprintf(stderr, _("%s: ioctl: %s\n"), progname,
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
exit(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
ipx_del_route(int argc, char **argv)
|
||||
{
|
||||
/* Router */
|
||||
struct sockaddr_ipx *sr = (struct sockaddr_ipx *)&rd.rt_gateway;
|
||||
struct sockaddr_ipx *sr = (struct sockaddr_ipx *) &rd.rt_gateway;
|
||||
/* Target */
|
||||
struct sockaddr_ipx *st = (struct sockaddr_ipx *)&rd.rt_dst;
|
||||
int s;
|
||||
int result;
|
||||
unsigned long netnum;
|
||||
char errmsg[80];
|
||||
|
||||
if (argc != 2) {
|
||||
usage();
|
||||
}
|
||||
struct sockaddr_ipx *st = (struct sockaddr_ipx *) &rd.rt_dst;
|
||||
int s;
|
||||
int result;
|
||||
unsigned long netnum;
|
||||
|
||||
if (argc != 1)
|
||||
{
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
rd.rt_flags = RTF_GATEWAY;
|
||||
/* Network Number */
|
||||
netnum = strtoul(argv[1], (char **)NULL, 16);
|
||||
if ((netnum == 0xffffffffL) || (netnum == 0L)) {
|
||||
fprintf(stderr, "%s: Inappropriate network number %08lX.\n",
|
||||
progname, netnum);
|
||||
exit(-1);
|
||||
if (sscanf_ipx_addr(st, argv[0], SSIPX_NETWORK) != SSIPX_NETWORK) {
|
||||
fprintf(stderr, _("%s: Invalid network number %s\n"),
|
||||
progname, argv[0]);
|
||||
return -1;
|
||||
}
|
||||
netnum = ntohl(st->sipx_network);
|
||||
if ((netnum == 0xffffffffL) || (netnum == 0L))
|
||||
{
|
||||
fprintf(stderr, _("%s: Inappropriate network number %08lX.\n"),
|
||||
progname, netnum);
|
||||
return -1;
|
||||
}
|
||||
st->sipx_network = htonl(netnum);
|
||||
|
||||
st->sipx_family = sr->sipx_family = AF_IPX;
|
||||
s = socket(AF_IPX, SOCK_DGRAM, AF_IPX);
|
||||
if (s < 0) {
|
||||
sprintf(errmsg, "%s: socket", progname);
|
||||
perror(errmsg);
|
||||
exit(-1);
|
||||
if (s < 0)
|
||||
{
|
||||
fprintf(stderr, _("%s: socket: %s\n"), progname,
|
||||
strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
result = ioctl(s, SIOCDELRT, &rd);
|
||||
if (result == 0) exit(0);
|
||||
if (result == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch (errno) {
|
||||
switch (errno)
|
||||
{
|
||||
case ENOENT:
|
||||
fprintf(stderr, "%s: Route not found for network %08lX.\n",
|
||||
fprintf(stderr, _("%s: Route not found for network %08lX.\n"),
|
||||
progname, netnum);
|
||||
break;
|
||||
case EPERM:
|
||||
fprintf(stderr, "%s: Network %08lX is directly connected.\n",
|
||||
fprintf(stderr, _("%s: Network %08lX is directly connected.\n"),
|
||||
progname, netnum);
|
||||
break;
|
||||
default:
|
||||
sprintf(errmsg, "%s: ioctl", progname);
|
||||
perror(errmsg);
|
||||
fprintf(stderr, _("%s: ioctl: %s\n"), progname,
|
||||
strerror(errno));
|
||||
break;
|
||||
}
|
||||
exit(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
setlocale(LC_ALL, "");
|
||||
bindtextdomain(PACKAGE, LOCALEDIR);
|
||||
textdomain(PACKAGE);
|
||||
|
||||
progname = argv[0];
|
||||
if (argc < 2) {
|
||||
if (argc < 2)
|
||||
{
|
||||
usage();
|
||||
exit(-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (strncasecmp(argv[1], "add", 3) == 0) {
|
||||
for (i = 1; i < (argc-1); i++)
|
||||
argv[i] = argv[i+1];
|
||||
ipx_add_route(argc-1, argv);
|
||||
} else if (strncasecmp(argv[1], "del", 3) == 0) {
|
||||
for (i = 1; i < (argc-1); i++)
|
||||
argv[i] = argv[i+1];
|
||||
ipx_del_route(argc-1, argv);
|
||||
if (strcasecmp(argv[1], "add") == 0)
|
||||
{
|
||||
return ipx_add_route(argc - 2, argv + 2);
|
||||
} else if (strcasecmp(argv[1], "del") == 0)
|
||||
{
|
||||
return ipx_del_route(argc - 2, argv + 2);
|
||||
} else {
|
||||
usage();
|
||||
return -1;
|
||||
}
|
||||
usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
93
src/ipxutil.c
Normal file
93
src/ipxutil.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Petr Vandrovec <vandrove@vc.cvut.cz>
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* See file COPYING for details.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <netinet/in.h>
|
||||
#include <ncp/kernel/ipx.h>
|
||||
#include <sys/types.h>
|
||||
#include "ipxutil.h"
|
||||
|
||||
/* caller must fill sockaddr_ipx with default values... */
|
||||
/* it parses string in form NETWORK:NODE/PORT into sockaddr_ipx structure */
|
||||
/* you can modify parser by flags: SSIPX_NETWORK = network present
|
||||
SSIPX_NODE = node present
|
||||
SSIPX_PORT = port present
|
||||
separators (:, /) are optional if preceeding parts are not expected */
|
||||
/* return value: SSIPX_NONE if nothing usable was found, otherwise
|
||||
combination of SSIPX_* reports, what was found and successfully parsed */
|
||||
int
|
||||
sscanf_ipx_addr(struct sockaddr_ipx *sipx, const char* addr, int flags) {
|
||||
u_int32_t netnum;
|
||||
char* ptr;
|
||||
int retval = SSIPX_NONE;
|
||||
|
||||
/* skip leading spaces... should we? */
|
||||
while (*addr && isspace(*addr))
|
||||
addr++;
|
||||
if (!*addr)
|
||||
return retval; /* nothing found */
|
||||
if (flags & SSIPX_NETWORK) {
|
||||
netnum = strtoul(addr, &ptr, 16);
|
||||
if (ptr != addr) {
|
||||
sipx->sipx_network = htonl(netnum);
|
||||
retval |= SSIPX_NETWORK; /* network was specified */
|
||||
addr = ptr;
|
||||
}
|
||||
}
|
||||
if (flags & SSIPX_NODE) {
|
||||
if ((*addr == ':') || !(flags & SSIPX_NETWORK)) {
|
||||
u_int16_t hi;
|
||||
u_int32_t lo;
|
||||
unsigned int c;
|
||||
const char* scn;
|
||||
/* node... */
|
||||
hi = 0;
|
||||
lo = 0;
|
||||
if (*addr == ':')
|
||||
addr++;
|
||||
scn = addr;
|
||||
while (isxdigit(c=*scn)) {
|
||||
scn++;
|
||||
hi = (hi << 4) | ((lo >> 28) & 0x0F);
|
||||
c -= '0';
|
||||
if (c > 9)
|
||||
c = (c + '0' - 'A' + 10) & 0x0F;
|
||||
lo = (lo << 4) | c;
|
||||
}
|
||||
if (addr != scn) {
|
||||
sipx->sipx_node[0] = hi >> 8;
|
||||
sipx->sipx_node[1] = hi;
|
||||
sipx->sipx_node[2] = lo >> 24;
|
||||
sipx->sipx_node[3] = lo >> 16;
|
||||
sipx->sipx_node[4] = lo >> 8;
|
||||
sipx->sipx_node[5] = lo;
|
||||
retval |= SSIPX_NODE;
|
||||
addr = scn;
|
||||
} /* else syntax error(node empty) */
|
||||
}
|
||||
}
|
||||
if (flags & SSIPX_PORT) {
|
||||
if ((*addr == '/') || (*addr == ':') ||
|
||||
!(flags & (SSIPX_NETWORK|SSIPX_NODE))) {
|
||||
u_int16_t sock;
|
||||
|
||||
/* socket... */
|
||||
if ((*addr == '/') || (*addr == ':'))
|
||||
addr++;
|
||||
sock = strtoul(addr, &ptr, 16);
|
||||
if (ptr != addr) {
|
||||
sipx->sipx_port = sock;
|
||||
retval |= SSIPX_PORT;
|
||||
addr = ptr;
|
||||
} /* else syntax error(socket empty) */
|
||||
}
|
||||
}
|
||||
/* if (*addr) syntax error(data after end of address) */
|
||||
return retval;
|
||||
}
|
||||
19
src/ipxutil.h
Normal file
19
src/ipxutil.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Petr Vandrovec <vandrove@vc.cvut.cz>
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* See file COPYING for details.
|
||||
*/
|
||||
|
||||
#ifndef __IPXUTIL_H__
|
||||
#define __IPXUTIL_H__
|
||||
|
||||
#define SSIPX_NONE 0
|
||||
#define SSIPX_NETWORK 1
|
||||
#define SSIPX_NODE 2
|
||||
#define SSIPX_PORT 4
|
||||
|
||||
int
|
||||
sscanf_ipx_addr(struct sockaddr_ipx *sipx, const char* addr, int flags);
|
||||
|
||||
#endif /* __IPXUTIL_H__ */
|
||||
89
src/netlink.h
Normal file
89
src/netlink.h
Normal file
@@ -0,0 +1,89 @@
|
||||
/* this is Linux 2.3.3 kernel include file with:
|
||||
(1) removed __KERNEL__ part
|
||||
(2) __uXX -> u_intXX_t
|
||||
*/
|
||||
|
||||
#ifndef __LINUX_NETLINK_H
|
||||
#define __LINUX_NETLINK_H
|
||||
|
||||
#define NETLINK_ROUTE 0 /* Routing/device hook */
|
||||
#define NETLINK_SKIP 1 /* Reserved for ENskip */
|
||||
#define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */
|
||||
#define NETLINK_FIREWALL 3 /* Firewalling hook */
|
||||
#define NETLINK_ARPD 8
|
||||
#define NETLINK_ROUTE6 11 /* af_inet6 route comm channel */
|
||||
#define NETLINK_IP6_FW 13
|
||||
#define NETLINK_TAPBASE 16 /* 16 to 31 are ethertap */
|
||||
|
||||
#define MAX_LINKS 32
|
||||
|
||||
struct sockaddr_nl
|
||||
{
|
||||
sa_family_t nl_family; /* AF_NETLINK */
|
||||
unsigned short nl_pad; /* zero */
|
||||
u_int32_t nl_pid; /* process pid */
|
||||
u_int32_t nl_groups; /* multicast groups mask */
|
||||
};
|
||||
|
||||
struct nlmsghdr
|
||||
{
|
||||
u_int32_t nlmsg_len; /* Length of message including header */
|
||||
u_int16_t nlmsg_type; /* Message content */
|
||||
u_int16_t nlmsg_flags; /* Additional flags */
|
||||
u_int32_t nlmsg_seq; /* Sequence number */
|
||||
u_int32_t nlmsg_pid; /* Sending process PID */
|
||||
};
|
||||
|
||||
/* Flags values */
|
||||
|
||||
#define NLM_F_REQUEST 1 /* It is request message. */
|
||||
#define NLM_F_MULTI 2 /* Multipart message, terminated by NLMSG_DONE */
|
||||
#define NLM_F_ACK 4 /* If succeed, reply with ack */
|
||||
#define NLM_F_ECHO 8 /* Echo this request */
|
||||
|
||||
/* Modifiers to GET request */
|
||||
#define NLM_F_ROOT 0x100 /* specify tree root */
|
||||
#define NLM_F_MATCH 0x200 /* return all matching */
|
||||
#define NLM_F_ATOMIC 0x400 /* atomic GET */
|
||||
#define NLM_F_DUMP (NLM_F_ROOT|NLM_F_MATCH)
|
||||
|
||||
/* Modifiers to NEW request */
|
||||
#define NLM_F_REPLACE 0x100 /* Override existing */
|
||||
#define NLM_F_EXCL 0x200 /* Do not touch, if it exists */
|
||||
#define NLM_F_CREATE 0x400 /* Create, if it does not exist */
|
||||
#define NLM_F_APPEND 0x800 /* Add to end of list */
|
||||
|
||||
/*
|
||||
4.4BSD ADD NLM_F_CREATE|NLM_F_EXCL
|
||||
4.4BSD CHANGE NLM_F_REPLACE
|
||||
|
||||
True CHANGE NLM_F_CREATE|NLM_F_REPLACE
|
||||
Append NLM_F_CREATE
|
||||
Check NLM_F_EXCL
|
||||
*/
|
||||
|
||||
#define NLMSG_ALIGNTO 4
|
||||
#define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) )
|
||||
#define NLMSG_LENGTH(len) ((len)+NLMSG_ALIGN(sizeof(struct nlmsghdr)))
|
||||
#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))
|
||||
#define NLMSG_DATA(nlh) ((void*)(((char*)nlh) + NLMSG_LENGTH(0)))
|
||||
#define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
|
||||
(struct nlmsghdr*)(((char*)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len)))
|
||||
#define NLMSG_OK(nlh,len) ((len) > 0 && (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \
|
||||
(nlh)->nlmsg_len <= (len))
|
||||
#define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len)))
|
||||
|
||||
#define NLMSG_NOOP 0x1 /* Nothing. */
|
||||
#define NLMSG_ERROR 0x2 /* Error */
|
||||
#define NLMSG_DONE 0x3 /* End of a dump */
|
||||
#define NLMSG_OVERRUN 0x4 /* Data lost */
|
||||
|
||||
struct nlmsgerr
|
||||
{
|
||||
int error;
|
||||
struct nlmsghdr msg;
|
||||
};
|
||||
|
||||
#define NET_MAJOR 36 /* Major 36 is reserved for networking */
|
||||
|
||||
#endif /* __LINUX_NETLINK_H */
|
||||
22
src/nls.h
Normal file
22
src/nls.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef IPX_UTILS_NLS_H
|
||||
#define IPX_UTILS_NLS_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_LIBINTL_H) && defined(HAVE_GETTEXT)
|
||||
# include <libintl.h>
|
||||
#else
|
||||
# define gettext(String) (String)
|
||||
#endif
|
||||
|
||||
#ifndef _
|
||||
# define _(String) gettext(String)
|
||||
#endif
|
||||
|
||||
#ifndef N_
|
||||
# define N_(String) (String)
|
||||
#endif
|
||||
|
||||
#endif /* IPX_UTILS_NLS_H */
|
||||
Reference in New Issue
Block a user