* Linux's X.25 and Isode
@ 2004-10-25 8:25 Francisco A. Lozano Lopez
2004-10-25 22:20 ` Andrew Hendry
0 siblings, 1 reply; 6+ messages in thread
From: Francisco A. Lozano Lopez @ 2004-10-25 8:25 UTC (permalink / raw)
To: linux-x25
Is there any way to use ISODE 8.0 with Linux's X.25?
I have a Cisco router which tunnels X.25 throught XOT. I've seen that there
is a small XOT implementation for older kernels so I'd like to try it to
connect to a 5ess switch which, serves files throught FTAM over X.25.
If not, is there any other FTAM client which can connect throught Linux's
X.25?
Thankyou.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Linux's X.25 and Isode
2004-10-25 8:25 Linux's X.25 and Isode Francisco A. Lozano Lopez
@ 2004-10-25 22:20 ` Andrew Hendry
2004-10-26 7:12 ` Francisco A. Lozano Lopez
0 siblings, 1 reply; 6+ messages in thread
From: Andrew Hendry @ 2004-10-25 22:20 UTC (permalink / raw)
To: Francisco A. Lozano Lopez; +Cc: linux-x25
[-- Attachment #1: Type: text/plain, Size: 1005 bytes --]
A linux patch for isode 8.0 exists here:
http://www.ibiblio.org/pub/Linux/system/network/isode/
I haven't used it.
As for the XOT implementation I have used this and it works well with
cisco XOT. Are you planning on using 2.4 or 2.6?
Attached is an updated xotd.c file with a minor locking fix.
gcc -o xotd xotd.c -lpthread is all it needs.
Andrew.
On Mon, 2004-10-25 at 18:25, Francisco A. Lozano Lopez wrote:
> Is there any way to use ISODE 8.0 with Linux's X.25?
>
> I have a Cisco router which tunnels X.25 throught XOT. I've seen that there
> is a small XOT implementation for older kernels so I'd like to try it to
> connect to a 5ess switch which, serves files throught FTAM over X.25.
>
> If not, is there any other FTAM client which can connect throught Linux's
> X.25?
>
> Thankyou.
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-x25" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
[-- Attachment #2: xotd.c --]
[-- Type: text/x-csrc, Size: 26391 bytes --]
/*
* xotd.c This file contains an implementation of RFC1613 XOT
* (X.25 over TCP/IP), using x25tap Linux module.
*
* Version: xotd.c 0.04 (1999-01-08)
*
* Author: Stephane Fillod, <sfillod@charybde.gyptis.frmug.org>
*
* 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.
*
* Modifications:
*
* 10/2002 by JH:
*
* Fix this up so we can talk to multiple remote xot devices
*
* Tell X.25 if TCP call clears
*
* Don't try to use same TCP call for multiple X.25 calls,
* leads to horrid clearing windows.
*
* Make outbound calls in thread, to avoid blocking everyone
*
*/
#include <pthread.h>
#include <stdio.h>
#include <sys/param.h>
#include <sys/types.h>
#include <linux/types.h> /* don't move this one ! */
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/uio.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <syslog.h>
#include <netdb.h>
#include <fcntl.h>
#include <termio.h>
#include <errno.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdarg.h>
#include <ctype.h>
#include <linux/netlink.h>
#define XOT_PORT 1998
#define XOT_VERSION 0
#define MAX_PKT_LEN 1030 /* 1024 bytes of data + PLP header */
#define MIN_PKT_LEN 3
#define CALL_REQUEST 0x0B
#define CALL_ACCEPT 0x0F
#define CLEAR_REQUEST 0x13
#define CLEAR_CONFIRMATION 0x17
#define RESTART_REQUEST 0xFB
#define RESTART_CONFIRMATION 0xFF
#define RR(pr) (0x01 + (pr << 5))
#define RNR(pr) (0x05 + (pr << 5))
#define REJ(pr) (0x09 + (pr << 5))
/* #define KEEPLCI0 (NOT IMPLEMENTED) */
#define DEBUG 1
#define FROM_TAP 1
#define TO_TAP 2
/*
* The famous xot header
*
*/
struct xot_header {
u_int16_t version;
u_int16_t length;
};
/*
* Information kept for each xot connection:
*
*/
struct xot {
int sock; /* socket connected to remote */
int cleared; /* True if we've sent CLR REQ */
struct xot_device *device; /* backpointer to device */
int lci;
pthread_t thread; /* inbound thread id */
pthread_mutex_t lock;
int busy;
int closing;
struct xot_header head; /* Should be contig */
unsigned char call [256];
};
/*
* Information for each remote xot device we know
*
*/
struct xot_device {
int max_addr; /* Number of addresses for this one */
struct sockaddr *addr;
int tap; /* The x25tap device it talks to. */
int max_xot; /* The biggest LCI it can use */
struct xot **xot; /* Table of virtual circuits */
pthread_t thread; /* Outbound thread id */
pthread_mutex_t lock;
};
int max_device;
pthread_cond_t wait_for_idle;
struct xot_device *device;
int isVerbose = 0;
int lport = XOT_PORT;
int rport = XOT_PORT;
void usage();
void daemon_start(void);
void printd (const char *format, ...);
void print_x25 (const char *head, const unsigned char *buf, int len);
void dump_packet(const unsigned char* pkt, int len,int direction);
static int writen(int fd, unsigned char *ptr, int nbytes);
static int readn(int fd, unsigned char *ptr, int nbytes);
struct xot *find_xot_for_call (int fd, struct sockaddr_in *addr);
int create_outbound (struct xot_device *dev);
void create_inbound (struct xot *xot);
void *outbound(void*);
void *inbound(void*);
void read_config (char *name);
void config_device (char *device_name, char *remote, char *circuits);
static char *addr (struct sockaddr *sa) {
switch (sa->sa_family) {
case AF_INET:
return inet_ntoa (((struct sockaddr_in *)sa)->sin_addr);
default:
return "unknown address family";
}
}
/* xot must be locked before use */
static void busy_xot (struct xot *xot) {
++xot->busy;
printd ("busy (%d)", xot->busy);
}
/* xot MUST NOT be locked before use; asymetry rules */
void idle_xot (struct xot *xot) {
pthread_mutex_lock (&xot->lock);
printd ("idle (busy = %d, closing = %d)", xot->busy, xot->closing);
if (!--xot->busy && xot->closing) {
pthread_cond_broadcast (&wait_for_idle);
}
pthread_mutex_unlock (&xot->lock);
}
static inline int get_lci(const unsigned char *packet)
{
return (packet[0] & 0x0F) * 256 + packet[1];
}
static int unit_of_devname(const char *devname)
{
int len;
if (!devname || !*devname)
return -1;
len = strlen(devname);
while (len>0 && isdigit(devname[len-1]))
len--;
return atoi(devname+len);
}
int main(int argc, char *argv[])
{
int sock;
struct sockaddr_in addr;
int on = 1;
char c;
char *bindto;
int errflg=0;
int unit=0;
int bindtointerface=0;
char *config = NULL;
struct xot_device *dev;
while ((c = getopt(argc, argv, "l:r:b:vf:h")) != -1)
switch (c) {
case 'v':
if(isVerbose)
errflg++;
else
isVerbose++;
break;
case 'r':
rport = atoi(optarg);
break;
case 'l':
lport = atoi(optarg);
break;
case 'b':
bindto = optarg;
bindtointerface++;
break;
case 'h':
errflg++;
break;
case 'f':
config = optarg;
break;
default:
errflg++;
}
#ifdef DEBUG
isVerbose++;
setvbuf (stderr, NULL, _IOLBF, BUFSIZ);
#endif
if (config) {
if (argc > optind)
++errflg;
else
read_config (config);
}
else {
if (argc - optind < 2 || argc - optind > 3)
++errflg;
else
config_device (argv[optind], argv[optind+1],
argc - optind > 2 ? argv[optind+2] : NULL);
}
if (errflg || max_device == 0) {
usage ();
return 1;
}
#ifndef DEBUG
/* Let's become a daemon */
daemon_start();
openlog("xotd", LOG_PID /*|LOG_NOWAIT*/, LOG_DAEMON);
#endif
pthread_cond_init (&wait_for_idle, NULL);
/* Make socket for incoming XOT calls */
if ((sock = socket (AF_INET, SOCK_STREAM, 0)) == -1) {
printd ("Error creating socket: %s",strerror(errno));
return 2;
}
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR/*|SO_DEBUG*/, &on, sizeof on);
memset(&addr, 0, sizeof addr);
addr.sin_family = AF_INET;
addr.sin_port = htons (lport);
if (bindtointerface) {
if(inet_aton(bindto,&addr.sin_addr) == 0) {
printd("Error with bind address");
return 2;
}
} else {
addr.sin_addr.s_addr = htonl (INADDR_ANY);
}
if (bind (sock, (struct sockaddr *) &addr, sizeof addr) == -1) {
printd ("Error binding socket: %s", strerror(errno));
close (sock);
return 2;
}
if (listen (sock, 8) == -1) {
printd ("Error listening socket: %s", strerror (errno));
close (sock);
return 2;
}
/* Start all the outbound threads, copy x.25 -> tcp */
unit = 0;
for (dev = device; dev < device + max_device; ++dev) {
if (create_outbound (dev)) ++unit;
}
if (!unit) return 2;
#ifdef DEBUG
printd ("Waiting for connections.");
#endif
for (;;) {
int len = sizeof addr;
int fd;
struct xot *xot;
if ((fd = accept (sock, (struct sockaddr *) &addr, &len)) == -1) {
printd ("accept error: %s", strerror(errno));
exit (1);
}
if (!(xot = find_xot_for_call (fd, &addr))) {
close (fd);
continue;
}
create_inbound (xot);
}
return 0;
}
void usage()
{
fprintf(stderr,
"\n"
"Usage:\txotd [-v] device_name remote_name [ circuits ]\n"
"or:\txotd [-v] -f config-file\n"
"\n"
"Config file format:\n"
"\n"
"device-name remote name [ circuits]\n"
"\n");
}
/*
* Create a new outbound thread, copy x.25 -> tcp
*
*/
int create_outbound (struct xot_device *dev) {
int unit;
struct sockaddr_nl addr;
int e;
unit = dev->tap + NETLINK_TAPBASE;
if ((dev->tap = socket (AF_NETLINK, SOCK_RAW, unit)) == -1) {
printd ("Error creating netlink socket: %s" ,
strerror(errno));
return 0;
}
memset(&addr, 0, sizeof addr);
addr.nl_family = AF_NETLINK;
addr.nl_groups = ~0;
if (bind (dev->tap, (struct sockaddr *) &addr,sizeof addr) == -1) {
printd ("Error binding netlink socket: %s",
strerror(errno));
close (dev->tap);
return 0;
}
pthread_mutex_init (&dev->lock, NULL);
if ((e = pthread_create (&dev->thread, NULL, outbound, dev))) {
printd ("pthread_create (outbound): %s", strerror (e));
close (dev->tap);
return 0;
}
return 1;
}
/*
* Create a inbound thread for a xot connection
*
* ... fix, should cope with failure.
*
*/
void create_inbound (struct xot *xot) {
int e;
pthread_attr_t attr;
pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
if ((e = pthread_create (&xot->thread, &attr, inbound, xot))) {
printd ("pthread_create (inbound): %s", strerror (e));
/* clean up ... */
return;
}
pthread_attr_destroy(&attr);
}
/*
* Find a xot to handle an incoming call
*
*/
struct xot *find_xot_for_call (int fd, struct sockaddr_in *addr) {
struct xot_device *dev;
struct xot *xot;
int lci;
/* First find the device */
for (dev = device; dev < device + max_device; ++dev) {
struct sockaddr *a;
for (a = dev->addr; a < dev->addr + dev->max_addr; ++a) {
if (((struct sockaddr_in *)a)->sin_addr.s_addr ==
addr->sin_addr.s_addr)
goto found_device;
}
}
printd ("call from unknown address %s", inet_ntoa (addr->sin_addr));
return NULL;
found_device:
/* Now look for a free lci. Count down like a DCE */
/* Fixme - doesn't allow LCI0 */
pthread_mutex_lock (&dev->lock);
for (lci = dev->max_xot - 1; lci; --lci) {
if (!dev->xot [lci]) goto found_lci;
}
pthread_mutex_unlock (&dev->lock);
printd ("Too many vc's from %s", inet_ntoa (addr->sin_addr));
return NULL;
found_lci:
xot = calloc (sizeof *xot, 1);
xot->device = device;
xot->sock = fd;
xot->lci = lci;
pthread_mutex_init (&xot->lock, NULL);
dev->xot [lci] = xot;
pthread_mutex_unlock (&dev->lock);
return xot;
}
/*
* Find the xot connection for an outbound packet
*
*/
struct xot *find_xot_for_packet (struct xot_device *dev,
unsigned char *packet,
int len)
{
struct xot *xot;
unsigned char *tap_packet = packet - 1;
int lci = get_lci (packet);
printd("find_xot_for_packet");
if (lci == 0) { /* ignore this one, see 6.4 in RFC */
if (packet[2] == RESTART_REQUEST) {
packet [2] = RESTART_CONFIRMATION;
write (dev->tap, packet - 1, 1 + 3);
dump_packet(packet,4,TO_TAP);
}
#ifdef DEBUG
printd("Drop packet, lci=0");
#endif
return NULL;
}
if (lci >= dev->max_xot) {
printd ("Bad lci %d - max %d", lci, dev->max_xot);
goto force_clear;
}
pthread_mutex_lock (&dev->lock);
if (!(xot = dev->xot [lci])) {
/* Not connected */
switch (packet [2]) {
case CLEAR_CONFIRMATION:
/* discard the message */
pthread_mutex_unlock (&dev->lock);
return NULL;
default:
pthread_mutex_unlock (&dev->lock);
printd ("no connection and packet not CALL");
goto force_clear;
case CALL_REQUEST:
break;
/* All is good, make the call */
}
xot = dev->xot [lci] = calloc (sizeof *xot, 1);
xot->device = dev;
xot->sock = -1;
xot->lci = lci;
pthread_mutex_init (&xot->lock, NULL);
pthread_mutex_unlock (&dev->lock);
/* Save call packet 'till connected to remote */
xot->head.length = htons (len);
xot->head.version = htons (XOT_VERSION);
memcpy (xot->call, packet, len);
/* Create thread for TCP->X.25, it'll make the call */
create_inbound (xot);
return NULL; /* send call after connected */
}
/* DANGER - locked device, then xot - always in that order! */
pthread_mutex_lock (&xot->lock);
pthread_mutex_unlock (&dev->lock);
if (xot->sock == -1) {
/* Not yet connected, only legal thing is CLEAR REQUEST */
xot->cleared = packet [2];
pthread_mutex_unlock (&xot->lock);
return NULL;
}
if (xot->closing) {
/* It's being closed */
pthread_mutex_unlock (&xot->lock);
return NULL;
}
busy_xot (xot);
pthread_mutex_unlock (&xot->lock);
if (packet [2] == CALL_REQUEST) {
printd ("call request on active channel");
idle_xot (xot);
goto force_clear;
}
xot->cleared = packet [2];
/* Copy GFI, LCI from call packet */
packet [0] = (packet [0] & 0xa0) + (xot->call [0] & 0x3f);
packet [1] = xot->call [1];
return xot;
force_clear:
printd ("fake clear");
packet[2] = CLEAR_REQUEST;
packet[3] = 0x05;
packet[4] = 0;
write (dev->tap, tap_packet, 1 + 5);
dump_packet(tap_packet,6,TO_TAP);
return NULL;
}
/*
* The outbound thread, read from Linux X.25 and send out
* to remote xot devices over TCP
*
* One thread per local xot device
*
*/
void *outbound(void *arg)
{
struct xot_device *dev = arg;
int nread;
/* Many ways of addressing same data. UGERLY */
unsigned char full_packet [sizeof (struct xot_header) + MAX_PKT_LEN];
struct xot_header *header = (struct xot_header *) full_packet;
unsigned char *packet = full_packet + sizeof *header;
unsigned char *tap_packet = packet - 1;
for (;;) {
struct xot *xot;
nread = read (dev->tap, tap_packet, MAX_PKT_LEN + 1);
dump_packet(tap_packet,nread,FROM_TAP);
if (nread < 0) {
printd("read error: %s", strerror(errno));
break;
}
if (nread == 0) /* strange, ignore it!? */
continue;
--nread; /* Ignore NETLINK byte */
switch (*tap_packet) {
case 0x00: /* data request */
if (nread < MIN_PKT_LEN) /* invalid packet size ? */
break;
#ifdef DEBUG
print_x25 ("Tap->TCP", packet, nread);
#endif
if (!(xot = find_xot_for_packet (dev, packet, nread)))
break;
printd ("forward to TCP");
header->version = htons (XOT_VERSION);
header->length = htons (nread);
nread += sizeof header;
/* Don't care if write fails, read should fail too
and that'll tell X.25 for us */
writen (xot->sock, (char *) header, nread);
if (packet [2] == CLEAR_CONFIRMATION) {
/* After this packet this vc is available for use */
printd ("outbound done with xot %p", xot);
/* This should kill the inbound side */
shutdown (xot->sock, SHUT_RDWR);
/* We should not send on this xot */
pthread_mutex_lock (&dev->lock);
if (dev->xot [xot->lci] == xot) {
dev->xot [xot->lci] = NULL;
}
else {
printd ("already zapped (in)");
}
pthread_mutex_unlock (&dev->lock);
}
idle_xot (xot);
break;
case 0x01: /* Connection request, send back ACK */
#ifdef DEBUG
printd("Tap->TCP: [conn.req], %d data bytes", nread);
#endif
*tap_packet = 0x01;
if (write(dev->tap, tap_packet, 1) != 1) {
printd("write error: %s",strerror(errno));
return NULL;
}
dump_packet(tap_packet,1,TO_TAP);
break;
case 0x02: /* Disconnect request */
#ifdef DEBUG
printd("Tap->TCP: [clr.req], %d data bytes", nread);
#endif
*tap_packet = 0x02;
if (write(dev->tap, tap_packet, 1) != 1) {
printd("write error: %s",strerror(errno));
return NULL;
}
dump_packet(tap_packet,1,TO_TAP);
break;
case 0x03:
#ifdef DEBUG
printd("Tap->TCP: [param], %d data bytes", nread);
#endif
printd("changing parameters not supported");
break;
default:
printd("read from tap: unknown command %#x",*tap_packet);
break;
}
}
if (isVerbose)
printd("exiting Tap outbound!");
close (dev->tap);
return NULL;
}
/*
* Send data from TCP to X.25
*
* One thread per active X.25 connection.
*
*/
void *inbound(void *arg)
{
struct xot *xot = arg;
struct xot_device *dev = xot->device;
int nread, len;
struct xot_header header;
unsigned char tap_packet [MAX_PKT_LEN + 1];
unsigned char *packet = tap_packet + 1;
if (isVerbose)
printd("lci=%d New TCP connection (tap inbound).", xot->lci);
if (xot->sock == -1) {
int sock;
struct sockaddr *a;
/* It's up to us to make the call */
for (a = dev->addr; a < dev->addr + dev->max_addr; ++a) {
sock = socket (a->sa_family, SOCK_STREAM, 0);
if (sock == -1) {
printd ("socket: %s", strerror (errno));
goto clear;
}
if (connect (sock, a, sizeof *a) == 0) goto ok;
printd ("%s: %s", addr (a), strerror (errno));
close (sock);
}
/* all call attempts failed; tell X.25 */
goto clear;
ok:
pthread_mutex_lock (&xot->lock);
printd ("connected to %s", addr (a));
if (xot->cleared == CLEAR_REQUEST) {
/* but X.25 has decided to give up. */
pthread_mutex_unlock (&xot->lock);
goto clear;
}
xot->sock = sock;
pthread_mutex_unlock (&xot->lock);
/* OK, send out the call packet */
len = ntohs (xot->head.length) + sizeof xot->head;
printd ("write %d bytes call request", len);
printd ("gfi=%02x lcn=%02x pti=%02x",
xot->call[0], xot->call[1], xot->call[2]);
len = writen (xot->sock, (unsigned char *) &xot->head, len);
if (len < 0)
printd("readn error: %s", strerror(errno));
}
*tap_packet = 0x00; /* Data.ind */
do {
nread = readn (xot->sock, (unsigned char*) &header, sizeof header);
if (nread != sizeof header) {
if (nread < 0 && ( errno != EPIPE || errno != ENOTCONN))
printd("readn error: %s", strerror(errno));
break; /* abort */
}
len = ntohs (header.length);
if (ntohs (header.version) != XOT_VERSION) {
printd("XOT version not supported: %d", ntohs(header.version));
break; /* and close the connexion */
}
if (len == 0) {
#ifdef DEBUG
printd("Zero length packet received!");
#endif
continue; /* discard it */
}
/*
* TODO: replace MAX_PKT_LEN by the X.25 device MTU (packet size)
*/
if (len > MAX_PKT_LEN || len < MIN_PKT_LEN) {
printd("Invalid packet size: %d", len);
break; /* and close the connexion */
}
nread = readn (xot->sock, packet, len); /* read the remainder */
if (nread != len)
if (nread < 0) {
printd("readn error: %s",strerror(errno));
break;
}
#ifdef DEBUG
print_x25 ("TCP->Tap", packet, len);
#endif
switch (packet[2]) {
case CLEAR_CONFIRMATION:
pthread_mutex_lock (&dev->lock);
if (dev->xot [xot->lci] == xot) {
dev->xot[xot->lci] = NULL;
}
pthread_mutex_unlock (&dev->lock);
xot->cleared = CLEAR_CONFIRMATION;
break;
case CALL_REQUEST:
/* Should check he doesn't send 2 calls */
if ((xot->head.length = len) > sizeof xot->call) {
xot->head.length = sizeof xot->call;
}
memcpy (xot->call, packet, xot->head.length);
}
/* Check gfi, lci of packet */
if ((packet [0] & 0x3f) != (xot->call[0] & 0x3f) ||
packet [1] != xot->call [1])
{
printd ("Bad GFI/LCN %02x, %02x", packet [0], packet [1]);
break;
}
/* Fix LCI to be what we want */
packet [0] = (packet [0] & 0xf0) + xot->lci / 256;
packet [1] = xot->lci;
if (write (dev->tap, tap_packet, nread + 1) != nread + 1) {
printd("Tap write error: %s",strerror(errno));
break;
}
dump_packet(tap_packet, nread +1,TO_TAP);
/* If we get a clear confirm from remote then we can hang up */
}
while (xot->cleared != CLEAR_CONFIRMATION);
clear:
if (isVerbose)
printd("TCP connection closed (tap inbound), lci=%d.", xot->lci);
switch (xot->cleared) {
case CLEAR_CONFIRMATION:
/* Nothing to send to X.25 */
break;
case CLEAR_REQUEST:
printd ("send clear confirmation to x.25");
packet [2] = CLEAR_CONFIRMATION;
len = 3;
goto send;
default:
printd ("send clear request to x.25");
packet [2] = CLEAR_REQUEST;
packet [3] = 0;
packet [4] = 0;
len = 5;
send:
packet [0] = 0x10 + xot->lci / 256;
packet [1] = xot->lci;
write (xot->device->tap, tap_packet, len + 1);
dump_packet(tap_packet, len + 1,TO_TAP);
}
/* Wait for outbound side to finish work */
pthread_mutex_lock (&xot->lock);
++xot->closing;
while (xot->busy) {
printd ("wait for idle");
pthread_cond_wait (&wait_for_idle, &xot->lock);
}
pthread_mutex_unlock (&xot->lock);
pthread_mutex_lock (&dev->lock);
if (dev->xot [xot->lci] == xot) {
dev->xot [xot->lci] = NULL;
}
else {
printd ("already zapped (out)");
}
pthread_mutex_unlock (&dev->lock);
printd ("idle");
close (xot->sock);
pthread_mutex_destroy (&xot->lock);
free (xot);
printd ("done");
return NULL;
}
/*
* Write "n" bytes to a descriptor.
* Use in place of write() when fd is a stream socket.
*/
static int writen(int fd, unsigned char *ptr, int nbytes)
{
int nleft, nwritten;
nleft = nbytes;
while (nleft > 0) {
nwritten = write(fd, ptr, nleft);
if (nwritten <= 0)
return nwritten; /* error */
nleft -= nwritten;
ptr += nwritten;
}
return nbytes - nleft;
}
/*
* Read "n" bytes from a descriptor.
* Use in place of read() when fd is a stream socket.
*/
static int readn(int fd, unsigned char *ptr, int nbytes)
{
int nread, nleft;
if (!ptr)
return -1;
nleft = nbytes;
while (nleft > 0) {
nread = read(fd, ptr, nleft);
if (nread <= 0)
return nread; /* error */
nleft -= nread;
ptr += nread;
}
return nbytes - nleft;
}
/*
* print debug messages
*
*/
void printd(const char *format, ...)
{
va_list ap;
va_start(ap, format);
#ifndef DEBUG
vsyslog(LOG_INFO,format,ap);
#else
{
char buf [BUFSIZ];
char *p = buf;
int left = sizeof buf - 1;
int len;
len = snprintf (p, left, "xotd[%d]:", (int) getpid ());
p += len;
left -= len;
if ((len = vsnprintf (p, left, format, ap)) < 0) len = left;
p += len;
*p++ = '\n';
write (fileno (stderr), buf, p - buf);
}
#endif
va_end(ap);
}
#ifdef DEBUG
/*
* print a pretty description of X.25 packet
*
*/
void print_x25 (const char *head, const unsigned char *packet, int len) {
int gfi = *packet;
int extended = (gfi & 0x30) == 0x20;
int lci = get_lci (packet);
int pti = packet [2];
if (!(pti & 1)) { /* Data packet */
int ps = pti >> 1, pr, m;
if (extended) {
pr = packet[3];
m = pr & 1;
pr >>= 1;
}
else {
ps &= 0x7;
m = pti & 0x10;
pr = pti >> 5;
}
printd ("%s lci=%d DATA (ps=%d, pr=%d%s%s%s)",
head,
lci, ps, pr,
m ? ", M" : "",
(gfi & 0x80) ? ", Q" : "",
(gfi & 0x40) ? ". D" : "");
}
else switch (pti) {
case RR(0):
if (extended) {
printd ("%s lci=%d RR (pr=%d)", head,
lci, packet[3] >> 1);
break;
}
case RR(1): case RR(2): case RR(3):
case RR(4): case RR(5): case RR(6): case RR(7):
printd ("%s lci=%d RR (pr=%d)", head, lci, pti >> 5);
break;
case RNR(0):
if (extended) {
printd ("%s lci=%d RNR(pr=%d)", head,
lci, packet[3] >> 1);
break;
}
case RNR(1): case RNR(2): case RNR(3):
case RNR(4): case RNR(5): case RNR(6): case RNR(7):
printd ("%s lci=%d RNR (pr=%d)", head, lci, pti >> 5);
break;
case REJ(0):
if (extended) {
printd ("%s lci=%d REJ (pr=%d)", head,
lci, packet[3] >> 1);
break;
}
case REJ(1): case REJ(2): case REJ(3):
case REJ(4): case REJ(5): case REJ(6): case REJ(7):
printd ("%s lci=%d REJ (pr=%d)", head, lci, pti >> 5);
break;
case CALL_REQUEST:
printd ("%s lci=%d CALL REQUEST", head, lci);
break;
case CALL_ACCEPT:
printd ("%s lci=%d CALL ACCEPT", head, lci);
break;
case CLEAR_REQUEST:
printd ("%s lci=%d CLEAR REQUEST", head, lci);
break;
case CLEAR_CONFIRMATION:
printd ("%s lci=%d CLEAR CONFIRMATION", head, lci);
break;
case RESTART_REQUEST:
printd ("%s lci=%d RESTART REQUEST", head, lci);
break;
case RESTART_CONFIRMATION:
printd ("%s lci=%d RESTART CONFIRMATION", head, lci);
break;
default:
printd ("%s lci=%d pti=0x%02x", head, lci, pti);
}
}
#endif
/*
* Detach a daemon process from login session context.
*/
void daemon_start(void)
{
if (fork())
exit(0);
chdir("/");
umask(0);
close(0);
close(1);
close(2);
open("/", O_RDONLY);
dup2(0, 1);
dup2(0, 2);
setsid();
}
/*
* Read our configuration file
*
*/
void read_config (char *name) {
FILE *f;
char line [80];
if (strcmp (name, "-") == 0) {
f = stdin;
}
else if (!(f = fopen (name, "r"))) {
perror (name);
exit (1);
}
while (fgets (line, sizeof line, f)) {
char *device_name = strtok (line, " \t\n");
char *remote_name = strtok (NULL, " \t\n");
char *circuits = strtok (NULL, " \t\n");
if (!device_name || *device_name == '#') continue;
if (!remote_name) {
fprintf (stderr, "Bad line %s in %s\n",
device_name, name);
continue;
}
config_device (device_name, remote_name, circuits);
}
if (f != stdin) fclose (f);
}
void config_device (char *device_name, char *remote_name, char *circuits) {
struct hostent *host;
int n;
int unit = unit_of_devname (device_name);
int vc;
struct xot_device *dev;
if (unit < 0 || unit > MAX_LINKS - NETLINK_TAPBASE - 1) {
fprintf (stderr, "Invalid netlink tap unit %s\n",
device_name);
return;
}
if (!(host = gethostbyname (remote_name))) {
fprintf (stderr, "Can't find %s for %s\n",
remote_name, device_name);
return;
}
if (!circuits) {
vc = 256;
}
else if (sscanf (circuits, "%d", &vc) != 1 ||
vc <= 0 || vc > 4095) {
fprintf (stderr, "Bad vc's %s for %s\n",
circuits, device_name);
return;
}
++max_device;
device = realloc (device, max_device * sizeof *device);
dev = &device [max_device - 1];
dev->tap = unit;
dev->max_xot = vc;
dev->xot = calloc (dev->max_xot, sizeof *dev->xot);
for (n = 0; host->h_addr_list[n]; ++n);
dev->addr = calloc (n, sizeof *device->addr);
dev->max_addr = n;
for (n = 0; n < device->max_addr; ++n) {
struct sockaddr_in *addr =
(struct sockaddr_in *) (&device->addr[n]);
addr->sin_family = AF_INET;
addr->sin_port = htons (rport);
memcpy (&addr->sin_addr,
host->h_addr_list[n],
host->h_length);
}
}
void dump_packet(const unsigned char* pkt, int len,int direction)
{
int i;
if (direction == TO_TAP) {
printf("TAP Wrote ");
} else {
printf("TAP Read ");
}
for(i=0;i<len;i++) {
printf("%02X ",pkt[i]);
}
printf("\n");
}
^ permalink raw reply [flat|nested] 6+ messages in thread
* RE: Linux's X.25 and Isode
2004-10-25 22:20 ` Andrew Hendry
@ 2004-10-26 7:12 ` Francisco A. Lozano Lopez
2004-10-26 12:44 ` John Hughes
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Francisco A. Lozano Lopez @ 2004-10-26 7:12 UTC (permalink / raw)
To: 'Andrew Hendry'; +Cc: linux-x25
This patch enables ISODE to work under Linux, but I thought it was only for
ISO/OSI through TCP/IP.
Has anyone managed to make it work with Linux's X.25? In the config.h file,
if you define X_25 it doesn't compile :(
I just need a ftam client for Linux's X.25; if there is any other different
from isode's I'd be glad to hear about it.
I was planning on using Linux 2.2 because I couldn't patch a more current
kernel with the needed patch. If there is any chance of making it work under
a newer version i'd like to do so, but anyway for what I need to do with XOT
Linux 2.2 is more than enough. I just need an opensource platform for CDR
recollection from a 5ess phone switch, which has a Cisco router serving X.25
through XOT.
Currently we have a proprietary implementation from a commercial software
company which is based on ISODE but has the X.25 stack and the XOT client
inside the FTAM binary... So it must be possible :)
By the way, thankyou very much, you're almost the only person i've found on
internet which knows what XOT is :/
-----Mensaje original-----
De: linux-x25-owner@vger.kernel.org [mailto:linux-x25-owner@vger.kernel.org]
En nombre de Andrew Hendry
Enviado el: martes, 26 de octubre de 2004 0:21
Para: Francisco A. Lozano Lopez
CC: linux-x25@vger.kernel.org
Asunto: Re: Linux's X.25 and Isode
A linux patch for isode 8.0 exists here:
http://www.ibiblio.org/pub/Linux/system/network/isode/
I haven't used it.
As for the XOT implementation I have used this and it works well with cisco
XOT. Are you planning on using 2.4 or 2.6?
Attached is an updated xotd.c file with a minor locking fix.
gcc -o xotd xotd.c -lpthread is all it needs.
Andrew.
On Mon, 2004-10-25 at 18:25, Francisco A. Lozano Lopez wrote:
> Is there any way to use ISODE 8.0 with Linux's X.25?
>
> I have a Cisco router which tunnels X.25 throught XOT. I've seen that
> there is a small XOT implementation for older kernels so I'd like to
> try it to connect to a 5ess switch which, serves files throught FTAM over
X.25.
>
> If not, is there any other FTAM client which can connect throught
> Linux's X.25?
>
> Thankyou.
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-x25"
> in the body of a message to majordomo@vger.kernel.org More majordomo
> info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Linux's X.25 and Isode
2004-10-26 7:12 ` Francisco A. Lozano Lopez
@ 2004-10-26 12:44 ` John Hughes
2004-10-26 13:27 ` Frederico Faria
2004-10-26 14:02 ` Steve Schefter
2 siblings, 0 replies; 6+ messages in thread
From: John Hughes @ 2004-10-26 12:44 UTC (permalink / raw)
To: Francisco A. Lozano Lopez; +Cc: 'Andrew Hendry', linux-x25
Francisco A. Lozano Lopez wrote:
>This patch enables ISODE to work under Linux, but I thought it was only for
>ISO/OSI through TCP/IP.
>Has anyone managed to make it work with Linux's X.25? In the config.h file,
>if you define X_25 it doesn't compile :(
>
>
All you have to do is write the X.25 interface routines in the compat
directory.
Make a linuxx25.c based on ubcx25.c, patch x25addr.c to know about the
Linux X.25 socket level.
You might have problems with Linux X.25's stupid non-handling of the M bit.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Linux's X.25 and Isode
2004-10-26 7:12 ` Francisco A. Lozano Lopez
2004-10-26 12:44 ` John Hughes
@ 2004-10-26 13:27 ` Frederico Faria
2004-10-26 14:02 ` Steve Schefter
2 siblings, 0 replies; 6+ messages in thread
From: Frederico Faria @ 2004-10-26 13:27 UTC (permalink / raw)
To: Francisco A. Lozano Lopez; +Cc: 'Andrew Hendry', linux-x25
Hi Francisco,
I also am searching a open source Ftam implementation for Linux
about X25.
Today I am evaluating a commercial software that implements Ftam
on Linux over X25. It works fine!!!
Now, I am starting the tests with FTAM/XOT using CISCO router to
tranfer file with an EWSD ( Siemens ) switch.
Regards,
Frederico Faria
Francisco A. Lozano Lopez escreveu:
> This patch enables ISODE to work under Linux, but I thought it was only for
> ISO/OSI through TCP/IP.
> Has anyone managed to make it work with Linux's X.25? In the config.h file,
> if you define X_25 it doesn't compile :(
>
> I just need a ftam client for Linux's X.25; if there is any other different
> from isode's I'd be glad to hear about it.
>
> I was planning on using Linux 2.2 because I couldn't patch a more current
> kernel with the needed patch. If there is any chance of making it work under
> a newer version i'd like to do so, but anyway for what I need to do with XOT
> Linux 2.2 is more than enough. I just need an opensource platform for CDR
> recollection from a 5ess phone switch, which has a Cisco router serving X.25
> through XOT.
>
> Currently we have a proprietary implementation from a commercial software
> company which is based on ISODE but has the X.25 stack and the XOT client
> inside the FTAM binary... So it must be possible :)
>
>
> By the way, thankyou very much, you're almost the only person i've found on
> internet which knows what XOT is :/
>
> -----Mensaje original-----
> De: linux-x25-owner@vger.kernel.org [mailto:linux-x25-owner@vger.kernel.org]
> En nombre de Andrew Hendry
> Enviado el: martes, 26 de octubre de 2004 0:21
> Para: Francisco A. Lozano Lopez
> CC: linux-x25@vger.kernel.org
> Asunto: Re: Linux's X.25 and Isode
>
>
> A linux patch for isode 8.0 exists here:
> http://www.ibiblio.org/pub/Linux/system/network/isode/
> I haven't used it.
>
> As for the XOT implementation I have used this and it works well with cisco
> XOT. Are you planning on using 2.4 or 2.6?
>
> Attached is an updated xotd.c file with a minor locking fix.
> gcc -o xotd xotd.c -lpthread is all it needs.
>
> Andrew.
>
> On Mon, 2004-10-25 at 18:25, Francisco A. Lozano Lopez wrote:
>
>>Is there any way to use ISODE 8.0 with Linux's X.25?
>>
>>I have a Cisco router which tunnels X.25 throught XOT. I've seen that
>>there is a small XOT implementation for older kernels so I'd like to
>>try it to connect to a 5ess switch which, serves files throught FTAM over
>
> X.25.
>
>>If not, is there any other FTAM client which can connect throught
>>Linux's X.25?
>>
>>Thankyou.
>>
>>-
>>To unsubscribe from this list: send the line "unsubscribe linux-x25"
>>in the body of a message to majordomo@vger.kernel.org More majordomo
>>info at http://vger.kernel.org/majordomo-info.html
>
>
> -
> To unsubscribe from this list: send the line "unsubscribe linux-x25" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
>
--
Frederico Charles S. Faria
ATI / ATITEL Ltda
www.ati.com.br
(31) - 2105-3100
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Linux's X.25 and Isode
2004-10-26 7:12 ` Francisco A. Lozano Lopez
2004-10-26 12:44 ` John Hughes
2004-10-26 13:27 ` Frederico Faria
@ 2004-10-26 14:02 ` Steve Schefter
2 siblings, 0 replies; 6+ messages in thread
From: Steve Schefter @ 2004-10-26 14:02 UTC (permalink / raw)
To: Francisco A. Lozano Lopez; +Cc: 'Andrew Hendry', linux-x25
Francisco A. Lozano Lopez wrote:
> This patch enables ISODE to work under Linux, but I thought it was only for
> ISO/OSI through TCP/IP.
That's correct. The interfaces for X.25 are still limited to Concurrent X.25,
HPUX X.25, UBC X.25 and Ultrix X.25.
> Has anyone managed to make it work with Linux's X.25? In the config.h file,
> if you define X_25 it doesn't compile :(
>
> I just need a ftam client for Linux's X.25; if there is any other different
> from isode's I'd be glad to hear about it.
>
> I was planning on using Linux 2.2 because I couldn't patch a more current
> kernel with the needed patch.
We've got a patch which adds support for ISODE over our commercial X.25
stack. If you want to use the open X.25 stack rather than ours, it'll
at least get you an ISODE with X25 defined that compiles on a 2.4 kernel.
There's a link for downloading the patch as well as compile tips and other
information at:
http://www.wanware.com/index.php?page=products/wan/isode&menu=products/wan
Regards,
Steve
------------------------------------------------------------------------
Steve Schefter phone: +1 705 725 9999 x26
The Software Group Limited fax: +1 705 725 9666
642 Welham Road, email: steve@wanware.com
Barrie, Ontario CANADA L4N 9A1 Web: www.wanware.com
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2004-10-26 14:02 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-10-25 8:25 Linux's X.25 and Isode Francisco A. Lozano Lopez
2004-10-25 22:20 ` Andrew Hendry
2004-10-26 7:12 ` Francisco A. Lozano Lopez
2004-10-26 12:44 ` John Hughes
2004-10-26 13:27 ` Frederico Faria
2004-10-26 14:02 ` Steve Schefter
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.