From 17287576555a5c46fa23549e2e5f073660dccb70 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 21 Apr 1999 09:51:03 +0200 Subject: Import ax25-tools 0.0.1 from tarball --- rose/rsdwnlnk.c | 272 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 272 insertions(+) create mode 100644 rose/rsdwnlnk.c (limited to 'rose/rsdwnlnk.c') diff --git a/rose/rsdwnlnk.c b/rose/rsdwnlnk.c new file mode 100644 index 0000000..5729d99 --- /dev/null +++ b/rose/rsdwnlnk.c @@ -0,0 +1,272 @@ +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#define AX25_HBIT 0x80 + +void alarm_handler(int sig) +{ +} + +int main(int argc, char **argv) +{ + unsigned char buffer[512], *addr; + fd_set read_fd; + int n = 0, s, addrlen, yes = 1; + struct full_sockaddr_ax25 axbind, axconnect; + struct sockaddr_rose rosesock, rosepeer; + + openlog("rsdwnlnk", LOG_PID, LOG_DAEMON); + + /* + * Arguments should be "rsdwnlnk ax25port ax25call" + */ + if (argc != 3) { + syslog(LOG_ERR, "invalid number of parameters\n"); + closelog(); + return 1; + } + + if (ax25_config_load_ports() == 0) { + syslog(LOG_ERR, "problem with axports file\n"); + closelog(); + return 1; + } + + addrlen = sizeof(struct sockaddr_rose); + + if (getsockname(STDIN_FILENO, (struct sockaddr *)&rosesock, &addrlen) == -1) { + syslog(LOG_ERR, "cannot getsockname - %s\n", strerror(errno)); + closelog(); + return 1; + } + + addrlen = sizeof(struct sockaddr_rose); + + if (getpeername(STDIN_FILENO, (struct sockaddr *)&rosepeer, &addrlen) == -1) { + syslog(LOG_ERR, "cannot getpeername - %s\n", strerror(errno)); + closelog(); + return 1; + } + + if (setsockopt(STDIN_FILENO, SOL_ROSE, ROSE_QBITINCL, &yes, sizeof(yes)) == -1) { + syslog(LOG_ERR, "cannot setsockopt(ROSE_QBITINCL) - %s\n", strerror(errno)); + closelog(); + return 1; + } + + /* + * Parse the passed values for correctness. + */ + axbind.fsa_ax25.sax25_family = AF_AX25; + axbind.fsa_ax25.sax25_ndigis = 1; + axbind.fsa_ax25.sax25_call = rosepeer.srose_call; + + if ((addr = ax25_config_get_addr(argv[1])) == NULL) { + syslog(LOG_ERR, "invalid AX.25 port name - %s\n", argv[1]); + closelog(); + return 1; + } + + if (ax25_aton_entry(addr, axbind.fsa_digipeater[0].ax25_call) == -1) { + syslog(LOG_ERR, "invalid AX.25 port callsign - %s\n", argv[1]); + closelog(); + return 1; + } + + axconnect.fsa_ax25.sax25_family = AF_AX25; + axconnect.fsa_ax25.sax25_call = rosesock.srose_call; + + /* + * The path at the far end has a digi in it. + */ + if (rosepeer.srose_ndigis == 1) { + axconnect.fsa_digipeater[n] = rosepeer.srose_digi; + axconnect.fsa_digipeater[n].ax25_call[6] |= AX25_HBIT; + n++; + } + + /* + * Incoming call has a different DNIC + */ + if (memcmp(rosepeer.srose_addr.rose_addr, rosesock.srose_addr.rose_addr, 2) != 0) { + addr = rose_ntoa(&rosepeer.srose_addr); + addr[4] = '\0'; + if (ax25_aton_entry(addr, axconnect.fsa_digipeater[n].ax25_call) == -1) { + syslog(LOG_ERR, "invalid callsign - %s\n", addr); + closelog(); + return 1; + } + axconnect.fsa_digipeater[n].ax25_call[6] |= AX25_HBIT; + n++; + } + + /* + * Put the remote address sans DNIC into the digi chain. + */ + addr = rose_ntoa(&rosepeer.srose_addr); + if (ax25_aton_entry(addr + 4, axconnect.fsa_digipeater[n].ax25_call) == -1) { + syslog(LOG_ERR, "invalid callsign - %s\n", addr + 4); + closelog(); + return 1; + } + axconnect.fsa_digipeater[n].ax25_call[6] |= AX25_HBIT; + n++; + + /* + * And my local ROSE callsign. + */ + if (ax25_aton_entry(argv[2], axconnect.fsa_digipeater[n].ax25_call) == -1) { + syslog(LOG_ERR, "invalid callsign - %s\n", argv[2]); + closelog(); + return 1; + } + axconnect.fsa_digipeater[n].ax25_call[6] |= AX25_HBIT; + n++; + + /* + * A digi has been specified for this end. + */ + if (rosesock.srose_ndigis == 1) { + axconnect.fsa_digipeater[n] = rosesock.srose_digi; + n++; + } + + axconnect.fsa_ax25.sax25_ndigis = n; + + addrlen = sizeof(struct full_sockaddr_ax25); + + /* + * Open the socket into the kernel. + */ + if ((s = socket(AF_AX25, SOCK_SEQPACKET, 0)) < 0) { + syslog(LOG_ERR, "cannot open AX.25 socket, %s\n", strerror(errno)); + closelog(); + return 1; + } +#ifdef HAVE_AX25_IAMDIGI + if (setsockopt(s, SOL_AX25, AX25_IAMDIGI, &yes, sizeof(yes)) == -1) { + syslog(LOG_ERR, "cannot setsockopt(AX25_IAMDIGI), %s\n", strerror(errno)); + close(s); + closelog(); + return 1; + } +#endif /* HAVE_AX25_IAMDIGI */ +#ifdef HAVE_AX25_PIDINCL + if (setsockopt(s, SOL_AX25, AX25_PIDINCL, &yes, sizeof(yes)) == -1) { + syslog(LOG_ERR, "cannot setsockopt(AX25_PIDINCL), %s\n", strerror(errno)); + close(s); + closelog(); + return 1; + } +#endif /* HAVE_AX25_PIDINCL */ + /* + * Set our AX.25 callsign and AX.25 port callsign accordingly. + */ + if (bind(s, (struct sockaddr *)&axbind, addrlen) != 0) { + syslog(LOG_ERR, "cannot bind AX.25 socket, %s\n", strerror(errno)); + close(s); + closelog(); + return 1; + } + + /* + * If no response in 60 seconds, go away. + */ + alarm(60); + + signal(SIGALRM, alarm_handler); + + /* + * Lets try and connect to the far end. + */ + if (connect(s, (struct sockaddr *)&axconnect, addrlen) != 0) { + switch (errno) { + case ECONNREFUSED: + strcpy(buffer, "*** Connection refused\r"); + break; + case ENETUNREACH: + strcpy(buffer, "*** No known route\r"); + break; + case EINTR: + strcpy(buffer, "*** Connection timed out\r"); + break; + default: + sprintf(buffer, "ERROR: cannot connect to AX.25 callsign, %s\r", strerror(errno)); + break; + } + + close(s); + + write(STDOUT_FILENO, buffer, strlen(buffer)); + + sleep(20); + + return 0; + } + + /* + * We got there. + */ + alarm(0); + + strcpy(buffer, "*** Connected\r"); + write(STDOUT_FILENO, buffer, strlen(buffer)); + + /* + * Loop until one end of the connection goes away. + */ + for (;;) { + FD_ZERO(&read_fd); + FD_SET(STDIN_FILENO, &read_fd); + FD_SET(s, &read_fd); + + select(s + 1, &read_fd, NULL, NULL, NULL); + + if (FD_ISSET(s, &read_fd)) { + if ((n = read(s, buffer + 2, 512)) == -1) + break; + if (buffer[2] == 0xF0) { + buffer[2] = 0; + write(STDOUT_FILENO, buffer + 2, n); + } else { + buffer[0] = 1; /* Set Q Bit on */ + buffer[1] = 0x7F; /* Q Bit escape */ + write(STDOUT_FILENO, buffer, n + 2); + } + } + + if (FD_ISSET(STDIN_FILENO, &read_fd)) { + if ((n = read(STDIN_FILENO, buffer, 512)) == -1) { + close(s); + break; + } + if (buffer[0] == 0) { /* Q Bit not set */ + buffer[0] = 0xF0; + write(s, buffer, n); + } else { + /* Lose the leading 0x7F */ + write(s, buffer + 2, n - 2); + } + } + } + + closelog(); + + return 0; +} -- cgit v1.2.3