int wp_listen(void) { struct full_sockaddr_rose rose; int fd; char *rs_addr; rose.srose_family = AF_ROSE; rose.srose_ndigis = 0; ax25_aton_entry("WP", rose.srose_call.ax25_call); if (!wp_debug) rs_addr = rs_get_addr(NULL); else rs_addr = rs_get_addr("rose1"); if (!rs_addr) return -1; rose_aton(rs_addr, rose.srose_addr.rose_addr); fd = socket(AF_ROSE, SOCK_SEQPACKET, 0); if (fd < 0) return -1; if (bind(fd, (struct sockaddr *)&rose, sizeof(struct full_sockaddr_rose)) == -1) { perror("wp_listen: bind"); close(fd); return -1; } listen(fd, 5); return fd; }
int wp_open_remote(char *source_call, struct full_sockaddr_rose *remote, int non_block) { struct full_sockaddr_rose rose; int fd, rc; char *rs_addr = rs_get_addr(NULL); if (!rs_addr) return -1; fd = socket(AF_ROSE, SOCK_SEQPACKET, 0); if (fd < 0) return -1; memset(&rose, 0x00, sizeof(struct full_sockaddr_rose)); rose.srose_family = AF_ROSE; rose.srose_ndigis = 0; ax25_aton_entry(source_call, rose.srose_call.ax25_call); rose_aton(rs_addr, rose.srose_addr.rose_addr); if (bind(fd, (struct sockaddr *)&rose, sizeof(struct full_sockaddr_rose)) == -1) { perror("wp_open: bind"); close(fd); return -1; } if (non_block) { int flag = 1; rc = ioctl(fd, FIONBIO, &flag); if (rc) { perror("wp_open_remote:ioctl FIONBIO"); close(fd); return -1; } } if (!remote) { /* Wait a few seconds for local WP server to be ready */ if (wait_for_local_wp(6)) return -1; /* Reuse the rose structure : same X.121 address */ ax25_aton_entry("WP", rose.srose_call.ax25_call); rc = connect(fd, (struct sockaddr *)&rose, sizeof(struct full_sockaddr_rose)); } else { rc = connect(fd, (struct sockaddr *)remote, sizeof(struct full_sockaddr_rose)); } if (rc && (errno != EINPROGRESS)) { close(fd); return -1; } return fd; }
char *rs_config_get_port(rose_address *address) { RS_Port *p = rs_ports; rose_address addr; while (p != NULL) { if (p->Addr != NULL) { rose_aton(p->Addr, addr.rose_addr); if (rose_cmp(address, &addr) == 0) return p->Name; } p = p->Next; } return NULL; }
int main (int argc, char **argv) { int fd = 0; int p; int paclen = 256; int af_mode; int addrlen = 0; int len; int phase; int verbose = 0; char **av; char *digi; char *mailto = NULL; char *title = NULL; char *port = NULL; char *filename = NULL; char *call = NULL; char buf[256]; while ((p = getopt (argc, argv, "d:f:i:p:t:v")) != -1) { switch (p) { case 'd': mailto = optarg; break; case 'f': filename = optarg; break; case 'i': call = optarg; break; case 't': title = optarg; break; case 'v': verbose = 1; break; case '?': case ':': fprintf (stderr, "usage: mailbbs [-d callsign@bbs] [-f filename] [-i sender] [-t title] [-v] port bbs-callsign [[via] digis...]\n"); return 1; } } if (optind == argc || optind == argc - 1) { fprintf (stderr, "usage: mailbbs [-d callsign@bbs] [-f filename] [-i sender] [-t title] [-v] port bbs-callsign [[via] digis...]\n"); return 1; } port = argv[optind]; if (mailto == NULL) { fprintf (stderr, "message recipient missing (option -d)\n"); return 1; } if (title == NULL) { title = "message fm mailbbs"; } if (ax25_config_load_ports () == 0) { fprintf (stderr, "mailbbs: no AX.25 port data configured\n"); return 1; } if (ax25_config_get_addr (port) == NULL) { nr_config_load_ports (); if (nr_config_get_addr (port) == NULL) { rs_config_load_ports (); if (rs_config_get_addr (port) == NULL) { fprintf (stderr, "mailbbs: invalid port setting\n"); return 1; } else { af_mode = AF_ROSE; } } else { af_mode = AF_NETROM; } } else { af_mode = AF_AX25; } av = argv + optind + 1; switch (af_mode) { case AF_ROSE: paclen = rs_config_get_paclen (port); if (av[0] == NULL || av[1] == NULL) { fprintf (stderr, "mailbbs: too few arguments for Rose\n"); return (-1); } if ((fd = socket (AF_ROSE, SOCK_SEQPACKET, 0)) < 0) { perror ("socket"); return (-1); } sockaddr.rose.srose_family = AF_ROSE; sockaddr.rose.srose_ndigis = 0; if (call == NULL) call = ax25_config_get_addr (NULL); ax25_aton_entry(call, sockaddr.rose.srose_call.ax25_call); rose_aton(rs_get_addr(NULL), sockaddr.rose.srose_addr.rose_addr); addrlen = sizeof(struct full_sockaddr_rose); if (bind (fd, (struct sockaddr *) &sockaddr, addrlen) == -1) { perror ("bind"); close (fd); return (-1); } memset (&sockaddr.rose, 0x00, sizeof (struct sockaddr_rose)); if (ax25_aton_entry (av[0], sockaddr.rose.srose_call.ax25_call) == -1) { close (fd); return (-1); } if (rose_aton (av[1], sockaddr.rose.srose_addr.rose_addr) == -1) { close (fd); return (-1); } if (av[2] != NULL) { digi = av[2]; if (strcasecmp (av[2], "VIA") == 0) { if (av[3] == NULL) { fprintf (stderr, "call: callsign must follow 'via'\n"); close (fd); return (-1); } digi = av[3]; } if (ax25_aton_entry (digi, sockaddr.rose.srose_digi.ax25_call) == -1) { close (fd); return (-1); } sockaddr.rose.srose_ndigis = 1; } sockaddr.rose.srose_family = AF_ROSE; addrlen = sizeof (struct sockaddr_rose); break; case AF_NETROM: paclen = nr_config_get_paclen (port); if (av[0] == NULL) { fprintf (stderr, "call: too few arguments for NET/ROM\n"); return (-1); } if ((fd = socket (AF_NETROM, SOCK_SEQPACKET, 0)) < 0) { perror ("socket"); return (-1); } if (call == NULL) call = nr_config_get_addr (port); ax25_aton (call, &sockaddr.ax25); sockaddr.ax25.fsa_ax25.sax25_family = AF_NETROM; addrlen = sizeof (struct full_sockaddr_ax25); if (bind (fd, (struct sockaddr *) &sockaddr, addrlen) == -1) { perror ("bind"); close (fd); return (-1); } if (nr_ax25_aton (av[0], &sockaddr.ax25) == -1) { close (fd); return (-1); } sockaddr.rose.srose_family = AF_NETROM; addrlen = sizeof (struct sockaddr_ax25); break; case AF_AX25: paclen = ax25_config_get_paclen (port); if (av[0] == NULL) { fprintf (stderr, "call: too few arguments for AX.25\n"); return (-1); } if ((fd = socket (AF_AX25, SOCK_SEQPACKET, 0)) < 0) { perror ("socket"); return (-1); } if (call == NULL) call = ax25_config_get_addr (port); ax25_aton (call, &sockaddr.ax25); sockaddr.ax25.fsa_ax25.sax25_family = AF_AX25; addrlen = sizeof (struct full_sockaddr_ax25); if (bind (fd, (struct sockaddr *) &sockaddr, addrlen) == -1) { perror ("bind"); close (fd); return (-1); } if (ax25_aton_arglist ((const char **)av, &sockaddr.ax25) == -1) { close (fd); return (-1); } sockaddr.rose.srose_family = AF_AX25; addrlen = sizeof (struct full_sockaddr_ax25); break; } if (verbose) printf ("F6FBB mailbbs v%s\n", VERSION); /* Connect the BBS */ if (connect (fd, (struct sockaddr *) &sockaddr, addrlen)) { printf ("\n"); perror ("connect"); close (fd); return (-1); } if (verbose) printf ("*** Connected to %s\n", av[0]); phase = WAITSID; for (;;) { len = readbbs (fd, buf, sizeof (buf), 300, verbose); if (len <= 0) { /* Disconnection or timeout */ close (fd); return 1; } switch (phase) { case WAITSID: if (len > 3 && buf[0] == '[' && buf[len - 2] == ']') { /* SID received */ phase = WAIT1STPROMPT; } break; case WAIT1STPROMPT: if (len > 2 && buf[len - 2] == '>') { /* 1st prompt received */ /* Send SID */ sprintf(buf, "[MAIL-%s-$]\n", VERSION); writebbs(fd, buf, strlen(buf), verbose); phase = WAIT2NDPROMPT; } break; case WAIT2NDPROMPT: if (len >= 2 && buf[len - 2] == '>') { /* 2nd prompt received */ /* Send proposal */ sprintf(buf, "SP %s\n", mailto); writebbs(fd, buf, strlen(buf), verbose); phase = WAITOK; } break; case WAITOK: if (buf[0] == 'O') { /* Send title */ sprintf(buf, "%s\n", title); writebbs(fd, buf, strlen(buf), verbose); /* Send text */ if (filename) if (sendfile(fd, filename, paclen, verbose) < 0) { close(fd); return 1; } /* End the mail */ sprintf(buf, "\032\n"); writebbs(fd, buf, strlen(buf), verbose); phase = WAITLASTPROMPT; break; } else { /* Disconnect */ close (fd); return 1; } case WAITLASTPROMPT: if (len >= 2 && buf[len - 2] == '>') { /* Last prompt received. Clean disconnection */ if (verbose) printf ("*** Done\n"); close (fd); return 0; } break; } } if (verbose) printf ("*** Disconnected fm %s\n", av[0]); return 0; }
int startiface(char *dev, struct hostent *hp) { struct ifreq ifr; char addr[5]; int fd; if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("rsattach: socket"); return FALSE; } strcpy(ifr.ifr_name, dev); if (hp != NULL) { ifr.ifr_addr.sa_family = AF_INET; ifr.ifr_addr.sa_data[0] = 0; ifr.ifr_addr.sa_data[1] = 0; ifr.ifr_addr.sa_data[2] = hp->h_addr_list[0][0]; ifr.ifr_addr.sa_data[3] = hp->h_addr_list[0][1]; ifr.ifr_addr.sa_data[4] = hp->h_addr_list[0][2]; ifr.ifr_addr.sa_data[5] = hp->h_addr_list[0][3]; ifr.ifr_addr.sa_data[6] = 0; if (ioctl(fd, SIOCSIFADDR, &ifr) < 0) { perror("rsattach: SIOCSIFADDR"); return FALSE; } } if (rose_aton(address, addr) == -1) return FALSE; ifr.ifr_hwaddr.sa_family = ARPHRD_ROSE; memcpy(ifr.ifr_hwaddr.sa_data, addr, 5); if (ioctl(fd, SIOCSIFHWADDR, &ifr) != 0) { perror("rsattach: SIOCSIFHWADDR"); return FALSE; } ifr.ifr_mtu = mtu; if (ioctl(fd, SIOCSIFMTU, &ifr) < 0) { perror("rsattach: SIOCSIFMTU"); return FALSE; } if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) { perror("rsattach: SIOCGIFFLAGS"); return FALSE; } ifr.ifr_flags &= IFF_NOARP; ifr.ifr_flags |= IFF_UP; ifr.ifr_flags |= IFF_RUNNING; if (ioctl(fd, SIOCSIFFLAGS, &ifr) < 0) { perror("rsattach: SIOCSIFFLAGS"); return FALSE; } close(fd); return TRUE; }
/* * Initiate a AX.25, NET/ROM, ROSE or TCP connection to the host * specified by `address'. */ static ax25io *connect_to(char **addr, int family, int escape, int compr) { int fd; ax25io *riop; fd_set read_fdset; fd_set write_fdset; int salen; union { struct full_sockaddr_ax25 ax; #ifdef HAVE_ROSE struct sockaddr_rose rs; #endif struct sockaddr_in in; } sa; char call[10], path[20], *cp, *eol; int ret, retlen = sizeof(int); int paclen; struct hostent *hp; struct servent *sp; struct user u; #ifdef HAVE_NETROM struct proc_nr_nodes *np; #endif strcpy(call, User.call); /* * Fill in protocol spesific stuff. */ switch (family) { #ifdef HAVE_ROSE case AF_ROSE: if (aliascmd==0) { if (check_perms(PERM_ROSE, 0L) == -1) { axio_printf(NodeIo,"Permission denied"); if (User.ul_type == AF_NETROM) { node_msg(""); } node_log(LOGLVL_GW, "Permission denied: rose"); return NULL; } } if ((fd = socket(AF_ROSE, SOCK_SEQPACKET, 0)) < 0) { node_perror("connect_to: socket", errno); return NULL; } sa.rs.srose_family = AF_ROSE; sa.rs.srose_ndigis = 0; ax25_aton_entry(call, sa.rs.srose_call.ax25_call); rose_aton(rs_config_get_addr(NULL), sa.rs.srose_addr.rose_addr); salen = sizeof(struct sockaddr_rose); if (bind(fd, (struct sockaddr *)&sa, salen) == -1) { node_perror("connect_to: bind", errno); close(fd); return NULL; } memset(path, 0, 11); memcpy(path, rs_config_get_addr(NULL), 4); salen = strlen(addr[1]); if ((salen != 6) && (salen != 10)) { axio_printf(NodeIo,"Invalid ROSE address"); if (User.ul_type == AF_NETROM) { node_msg(""); } return(NULL); } memcpy(path + (10-salen), addr[1], salen); sprintf(User.dl_name, "%s @ %s", addr[0], path); sa.rs.srose_family = AF_ROSE; sa.rs.srose_ndigis = 0; if (ax25_aton_entry(addr[0], sa.rs.srose_call.ax25_call) < 0) { close(fd); return NULL; } if (rose_aton(path, sa.rs.srose_addr.rose_addr) < 0) { close(fd); return NULL; } if (addr[2] != NULL) { if (ax25_aton_entry(addr[2], sa.rs.srose_digi.ax25_call) < 0) { close(fd); return NULL; } sa.rs.srose_ndigis = 1; } salen = sizeof(struct sockaddr_rose); paclen = rs_config_get_paclen(NULL); eol = ROSE_EOL; /* Uncomment the below if you wish to have the node show a 'Trying' state */ /* node_msg("%s Trying %s... Type <RETURN> to abort", User.dl_name); */ break; #endif #ifdef HAVE_NETROM case AF_NETROM: if (aliascmd==0) { if (check_perms(PERM_NETROM, 0L) == -1) { axio_printf(NodeIo,"Permission denied"); if (User.ul_type == AF_NETROM) { node_msg(""); } node_log(LOGLVL_GW, "Permission denied: netrom"); return NULL; } } if ((fd = socket(AF_NETROM, SOCK_SEQPACKET, 0)) < 0) { node_perror("connect_to: socket", errno); return NULL; } /* Why on earth is this different from ax.25 ????? */ sprintf(path, "%s %s", nr_config_get_addr(NrPort), call); ax25_aton(path, &sa.ax); sa.ax.fsa_ax25.sax25_family = AF_NETROM; salen = sizeof(struct full_sockaddr_ax25); if (bind(fd, (struct sockaddr *)&sa, salen) == -1) { node_perror("connect_to: bind", errno); close(fd); return NULL; } if ((np = find_node(addr[0], NULL)) == NULL) { axio_printf(NodeIo,"No such node"); if (User.ul_type == AF_NETROM) { node_msg(""); } return NULL; } strcpy(User.dl_name, print_node(np->alias, np->call)); if (ax25_aton(np->call, &sa.ax) == -1) { close(fd); return NULL; } sa.ax.fsa_ax25.sax25_family = AF_NETROM; salen = sizeof(struct sockaddr_ax25); paclen = nr_config_get_paclen(NrPort); eol = NETROM_EOL; /* Uncomment the below if you wish the node to show a 'Trying' state */ if (check_perms(PERM_ANSI, 0L) != -1) { if (User.ul_type == AF_NETROM) { break; } node_msg("\e[01;36mTrying %s... hit <Enter> to abort", User.dl_name); } break; #endif #ifdef HAVE_AX25 case AF_FLEXNET: case AF_AX25: if (aliascmd==0) { if (check_perms(PERM_AX25, 0L) == -1 || (is_hidden(addr[0]) && check_perms(PERM_HIDDEN, 0L) == -1)) { axio_printf(NodeIo,"Permission denied"); if (User.ul_type == AF_NETROM) { node_msg(""); } node_log(LOGLVL_GW, "Permission denied: ax.25 port %s", addr[0]); return NULL; } } if (ax25_config_get_addr(addr[0]) == NULL) { if (User.ul_type == AF_NETROM) { axio_printf(NodeIo,"%s} ", NodeId); } axio_printf(NodeIo,"Invalid port"); if (User.ul_type == AF_NETROM) { node_msg(""); } return NULL; } if ((fd = socket(AF_AX25, SOCK_SEQPACKET, 0)) < 0) { node_perror("connect_to: socket", errno); return NULL; } /* * Invert the SSID only if user is coming in with AX.25 * and going out on the same port he is coming in via. */ if (User.ul_type == AF_AX25 && !strcasecmp(addr[0], User.ul_name)) invert_ssid(call, User.call); sprintf(path, "%s %s", call, ax25_config_get_addr(addr[0])); ax25_aton(path, &sa.ax); sa.ax.fsa_ax25.sax25_family = AF_AX25; salen = sizeof(struct full_sockaddr_ax25); if (bind(fd, (struct sockaddr *)&sa, salen) < 0) { node_perror("connect_to: bind", errno); close(fd); return NULL; } if (ax25_aton_arglist((const char **)addr+1, &sa.ax) < 0) { close(fd); return NULL; } strcpy(User.dl_name, strupr(addr[1])); strcpy(User.dl_port, strlwr(addr[0])); sa.ax.fsa_ax25.sax25_family = AF_AX25; salen = sizeof(struct full_sockaddr_ax25); paclen = ax25_config_get_paclen(addr[0]); eol = AX25_EOL; /* Uncomment the below if you wish the node to show a 'Trying' state */ /* if (family==AF_FLEXNET) node_msg("Trying %s via FlexNet... Type <RETURN> to abort", User.dl_name); */ if ((family==AF_FLEXNET) || (family == AF_AX25)) { if (!strcmp(User.dl_port,User.ul_name)) { if (check_perms(PERM_ANSI, 0L) != -1) { axio_printf(NodeIo, "\e[05;31m"); } axio_printf(NodeIo,"\aLoop detected on "); } if (check_perms(PERM_ANSI, 0L) != -1) { axio_printf(NodeIo, "\e[0;m"); } if (User.ul_type == AF_NETROM) { axio_printf(NodeIo, "%s} ", NodeId); } if (check_perms(PERM_ANSI, 0L) != -1) { axio_printf(NodeIo, "\e[01;33m"); }
int download_dest(char *gateway, char *fname) { FILE *tmp; static char *addr; char port[14]; char buffer[4096], path[AX25_MAX_DIGIS * 10]; int buflen = 4096; char *commands[10], *dlist[9]; /* Destination + 8 digipeaters */ fd_set read_fd; int paclen = 0; int window = 0; int n, cmd_send = 0, cmd_ack = 0, c, k; int s = 0; int addrlen = 0; int ret; unsigned int retlen; char *cp; struct sockaddr_rose rosebind; struct sockaddr_rose roseconnect; struct full_sockaddr_ax25 nrbind, nrconnect; union { struct full_sockaddr_ax25 ax25; struct sockaddr_rose rose; } sockaddr; char digicall[10] = "\0"; char destcall[10] = "\0"; char destaddr[11] = "\0"; static int af_mode = 0; memset(&sockaddr.rose, 0x00, sizeof(struct sockaddr_rose)); memset(&rosebind, 0x00, sizeof(struct sockaddr_rose)); memset(&roseconnect, 0x00, sizeof(struct sockaddr_rose)); memset(&nrbind, 0x00, sizeof(struct full_sockaddr_ax25)); memset(&nrconnect, 0x00, sizeof(struct sockaddr_ax25)); gw = find_route(gateway, NULL); if (gw == NULL) { fprintf(stderr,"flexd connect: FlexGate %s not found in file: %s\n", gateway, FLEXD_CONF_FILE); return -1; } else { *path = '\0'; for (k = 0; k < AX25_MAX_DIGIS; k++) { if (gw->digis[k][0] == '\0') dlist[k + 1] = NULL; else dlist[k + 1] = gw->digis[k]; } dlist[0] = gw->dest_call; strcpy(port, gw->dev); } if (af_mode == 0) { if ((addr = ax25_config_get_addr(port)) == NULL) { nr_config_load_ports(); if ((addr = nr_config_get_addr(port)) == NULL) { rs_config_load_ports(); if ((addr = rs_config_get_addr(port)) == NULL) { fprintf(stderr, "flexd: invalid port setting\n"); return -1; } else { af_mode = AF_ROSE; } } else { af_mode = AF_NETROM; } } else { af_mode = AF_AX25; } } switch (af_mode) { case AF_ROSE: paclen = rs_config_get_paclen(port); if (dlist[0] == NULL || dlist[1] == NULL) { fprintf(stderr, "flexd: too few arguments for Rose\n"); return (-1); } /* * Parse the passed values for correctness. */ roseconnect.srose_family = rosebind.srose_family = AF_ROSE; roseconnect.srose_ndigis = rosebind.srose_ndigis = 0; /* if (dlist[2] == NULL) { */ strcpy(destaddr, dlist[1]); strcpy(destcall, dlist[0]); /* *digicall ='\0';*/ /* } else { strcpy(destaddr, dlist[2]); strcpy(digicall, dlist[0]); strcpy(destcall, dlist[1]); } */ if (ax25_aton_entry(destcall, roseconnect.srose_call.ax25_call) == -1) { sprintf(buffer, "ERROR: invalid destination callsign - %s\n", destcall); fprintf(stderr, "%s\n", buffer); return (-1); } if (rose_aton(destaddr, roseconnect.srose_addr.rose_addr) == -1) { sprintf(buffer, "ERROR: invalid destination Rose address - %s\n", destaddr); fprintf(stderr, "%s\n", buffer); return (-1); } rosebind.srose_family = AF_ROSE; roseconnect.srose_family = AF_ROSE; sockaddr.rose.srose_family = AF_ROSE; addrlen = sizeof(struct sockaddr_rose); /* * Open the socket into the kernel. */ if ((s = socket(AF_ROSE, SOCK_SEQPACKET, 0)) < 0) { sprintf(buffer, "ERROR: cannot open Rose socket, %s\n", strerror(errno)); fprintf(stderr, "%s\n", buffer); close(s); return (-1); } /* * Set our AX.25 callsign and Rose address accordingly. */ if (rose_aton(addr, rosebind.srose_addr.rose_addr) == -1) { sprintf(buffer, "ERROR: invalid Rose port address - %s\n", addr); fprintf(stderr, "%s\n", buffer); close(s); return (-1); } if (ax25_aton_entry(mycall, rosebind.srose_call.ax25_call) == -1) { sprintf(buffer, "ERROR: invalid callsign - %s\n", mycall); fprintf(stderr, "%s\n", buffer); close(s); return (-1); } if (bind(s, (struct sockaddr *)&rosebind, addrlen) != 0) { sprintf(buffer, "ERROR: cannot bind Rose socket, %s\n", strerror(errno)); fprintf(stderr, "%s\n", buffer); close(s); return (-1); } /* * Lets try and connect to the far end. */ if (connect(s, (struct sockaddr *)&roseconnect, addrlen) != 0) { switch (errno) { case ECONNREFUSED: strcpy(buffer, "*** Flexd: Connection refused - will try again later\n"); break; case ENETUNREACH: strcpy(buffer, "*** Flexd: Route is closed - will try again later\n"); break; case EINTR: strcpy(buffer, "*** Flexd: Connection timed out - will try again later\n"); break; default: sprintf(buffer, "Flexd: ERROR cannot connect to Rose address %s\n", strerror(errno)); break; } fprintf(stderr, "%s\n", buffer); close(s); return (1); } break; case AF_NETROM: if (paclen == 0) paclen = nr_config_get_paclen(port); if (dlist[0] == NULL) { fprintf(stderr, "flexd: too few arguments for NET/ROM\n"); return (-1); } /* * Parse the passed values for correctness. */ nrconnect.fsa_ax25.sax25_family = AF_NETROM; nrbind.fsa_ax25.sax25_family = AF_NETROM; nrbind.fsa_ax25.sax25_ndigis = 1; nrconnect.fsa_ax25.sax25_ndigis = 0; addrlen = sizeof(struct full_sockaddr_ax25); if (ax25_aton_entry(addr, nrbind.fsa_ax25.sax25_call.ax25_call) == -1) { sprintf(buffer, "ERROR: invalid NET/ROM port callsign - %s\n", addr); fprintf(stderr, "%s\n", buffer); return (-1); } if (ax25_aton_entry(mycall, nrbind.fsa_digipeater[0].ax25_call) == -1) { sprintf(buffer, "ERROR: invalid callsign - %s\n", mycall); fprintf(stderr, "%s\n", buffer); return (-1); } /* if (dlist[1] == NULL) { */ strcpy(destcall, dlist[0]); /* } else { strcpy(destcall, dlist[1]); strcpy(digicall, dlist[0]); } */ /*FSA*/ fprintf(stderr, "\nCase AF_NETROM destcall: '%s' digicall: '%s' mycall: '%s' port callsign: '%s'\n", destcall, digicall, mycall, addr); /*FSA*/ printf("Case AF_NETROM destcall: '%s' digicall: '%s' mycall: '%s' port callsign: '%s' addrlen %d\n", destcall, digicall, mycall, addr, addrlen); if (ax25_aton_entry(destcall, nrconnect.fsa_ax25.sax25_call.ax25_call) == -1) { sprintf(buffer, "ERROR: invalid destination callsign - %s\n", destcall); fprintf(stderr, "%s\n", buffer); return (-1); } /* * Open the socket into the kernel. */ if ((s = socket(AF_NETROM, SOCK_SEQPACKET, 0)) < 0) { sprintf(buffer, "ERROR: cannot open NET/ROM socket, %s\n", strerror(errno)); fprintf(stderr, "%s\n", buffer); close(s); return (-1); } /* * Set our AX.25 callsign and NET/ROM callsign accordingly. */ if (bind(s, (struct sockaddr *)&nrbind, addrlen) != 0) { sprintf(buffer, "ERROR: cannot bind NET/ROM socket, %s\n", strerror(errno)); fprintf(stderr, "%s\n", buffer); close(s); return (-1); } /* * Lets try and connect to the far end. */ if (connect(s, (struct sockaddr *)&nrconnect, addrlen) != 0) { sprintf(buffer,"\nTrying %s ", destcall); switch (errno) { case ECONNREFUSED: strcat(buffer, "*** Flexd: Connection refused - will try again later\n"); break; case ENETUNREACH: strcat(buffer, "*** Flexd: Route is closed - will try again later\n"); break; case EINTR: strcat(buffer, "*** Flexd: Connection timed out - will try again later\n"); break; default: sprintf(buffer, "Flexd: ERROR cannot connect to NET/ROM node, %s\n", strerror(errno)); break; } fprintf(stderr, "\nBUFFER:%s\n", buffer); close(s); return (1); } break; case AF_AX25: if (window == 0) window = ax25_config_get_window(port); if (paclen == 0) paclen = ax25_config_get_paclen(port); dlist[0] = gw->dest_call; if (dlist[0] == NULL) { fprintf(stderr, "flexd: too few arguments for AX.25\n"); return (-1); } if ((s = socket(AF_AX25, SOCK_SEQPACKET, 0)) < 0) { perror("flexd: socket"); return (-1); } ax25_aton(ax25_config_get_addr(port), &sockaddr.ax25); if (sockaddr.ax25.fsa_ax25.sax25_ndigis == 0) { ax25_aton_entry(ax25_config_get_addr(port), sockaddr.ax25.fsa_digipeater[0]. ax25_call); sockaddr.ax25.fsa_ax25.sax25_ndigis = 1; } sockaddr.ax25.fsa_ax25.sax25_family = AF_AX25; addrlen = sizeof(struct full_sockaddr_ax25); if (setsockopt (s, SOL_AX25, AX25_WINDOW, &window, sizeof(window)) == -1) { perror("flexd: AX25_WINDOW"); close(s); return (-1); } if (setsockopt (s, SOL_AX25, AX25_PACLEN, &paclen, sizeof(paclen)) == -1) { perror("flexd: AX25_PACLEN"); close(s); return (-1); } if (backoff != -1) { if (setsockopt (s, SOL_AX25, AX25_BACKOFF, &backoff, sizeof(backoff)) == -1) { perror("flexd: AX25_BACKOFF"); close(s); return (-1); } } if (ax25mode != -1) { if (setsockopt (s, SOL_AX25, AX25_EXTSEQ, &ax25mode, sizeof(ax25mode)) == -1) { perror("flexd: AX25_EXTSEQ"); close(s); return (-1); } } if (ax25_aton_arglist ((const char **) dlist, &sockaddr.ax25) == -1) { close(s); return (-1); } /* * Open the socket into the kernel. */ if ((s = socket(AF_AX25, SOCK_SEQPACKET, 0)) < 0) { sprintf(buffer, "flexd connect: cannot open AX.25 socket, %s\n", strerror(errno)); write(STDOUT_FILENO, buffer, strlen(buffer)); return (-1); } /* * Set our AX.25 callsign and AX.25 port callsign accordingly. */ if (*mycall == '\0') sprintf(buffer, "\n%s %s\n", addr, addr); else sprintf(buffer, "\n%s %s\n", mycall, addr); ax25_aton(buffer, &sockaddr.ax25); if (bind(s, (struct sockaddr *) &sockaddr, addrlen) != 0) { sprintf(buffer, "flexd connect: cannot bind AX.25 socket, %s\n", strerror(errno)); write(STDOUT_FILENO, buffer, strlen(buffer)); close(s); return (-1); } /*FSA*/ sleep(1); /*FSA*/ /* * Lets try and connect to the far end. * */ if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) { sprintf(buffer, "flexd connect: fcntl on socket: %s\n", strerror(errno)); write(STDOUT_FILENO, buffer, strlen(buffer)); close(s); return (-1); } if (ax25_aton_arglist((const char **) dlist, &sockaddr.ax25) == -1) { sprintf(buffer, "flexd connect: invalid destination callsign or digipeater\n"); write(STDOUT_FILENO, buffer, strlen(buffer)); close(s); return (-1); } /*FSA*/ sleep(1); /*FSA*/ /**/ if (connect(s, (struct sockaddr *) &sockaddr, addrlen) == -1 && errno != EINPROGRESS) { switch (errno) { case ECONNREFUSED: strcpy(buffer, "*** Flexd: Connection refused - will try again later\n"); break; case ENETUNREACH: strcpy(buffer, "*** Flexd: Route is closed - will try again later\n"); break; case EINTR: strcpy(buffer, "*** Flexd: Connection timed out - will try again later\n"); break; default: sprintf(buffer, "*** Flexd: Cannot connect %s\n", strerror(errno)); break; } write(STDOUT_FILENO, buffer, strlen(buffer)); close(s); return (1); } /**/ break; } fflush(stdout); /* * We got there. */ while (1) { FD_ZERO(&read_fd); FD_SET(s, &read_fd); if (select(s + 1, &read_fd, NULL, 0, 0) == -1) { break; } if (FD_ISSET(s, &read_fd)) { /* See if we got connected or if this was an error */ getsockopt(s, SOL_SOCKET, SO_ERROR, &ret, &retlen); switch (af_mode) { case AF_ROSE: break; case AF_NETROM: break; case AF_AX25: { /*FSA don'know how but works!*/ if ((ret != 0) && (ret != 256)) { cp = strdup(strerror(ret)); strlwr(cp); sprintf(buffer, "flexd connect: Failure with %s error %d %s\n", gateway, ret, cp); write(STDOUT_FILENO, buffer, strlen(buffer)); free(cp); close(s); return 1; } } break; default: break; } break; } } commands[0] = "d\r"; commands[1] = "q\r"; commands[2] = "b\r"; commands[3] = NULL; /* * Loop until one end of the connection goes away. */ if ((tmp = fopen(fname, "w")) == NULL) { fprintf(stderr, "flexd connect: Cannot open temporary file: %s\n", fname); close(s); return (-1); } /*FSA*/ sleep(1); /*FSA*/ for (;;) { int prompt = 0; FD_ZERO(&read_fd); FD_SET(s, &read_fd); if (select(s + 1, &read_fd, NULL, NULL, NULL) == -1) { break; } if (FD_ISSET(s, &read_fd)) { if ((n = read(s, buffer, 512)) == -1) break; for (c = 0; c < n; c++) { if (buffer[c] == '\r') buffer[c] = '\n'; if ((c < n-1) && ((buffer[c] == '=') && (buffer[c + 1] == '>') || (buffer[c] == '-' && (buffer[c + 1] == '>')) || ((buffer[c] == ':') && (buffer[c - 1] == ' ') && (buffer[c + 1] == ' ')))) { cmd_ack++; } } if (cmd_send > 0) { fwrite(buffer, sizeof(char), n, tmp); } } if (cmd_ack != 0) { if (cmd_send < 3) { write(s, commands[cmd_send], 2); cmd_send++; } } } close(s); fclose(tmp); return 0; }
int main(int argc, char **argv) { unsigned char buffer[512], *addr, *p; char rose_address[11]; fd_set read_fd; int n, s, dnicindex = -1, addrindex = -1; int yes = 1, verbose = 1; socklen_t addrlen; struct sockaddr_rose rosebind, roseconnect; struct full_sockaddr_ax25 ax25sock, ax25peer; openlog("rsuplnk", LOG_PID, LOG_DAEMON); /* * Arguments should be "rsuplnk [-q] roseport" */ if (argc > 2 && strcmp(argv[1], "-q") == 0) { verbose = 0; --argc; ++argv; } if (argc != 2) { syslog(LOG_ERR, "invalid number of parameters\n"); closelog(); return 1; } if (rs_config_load_ports() == 0) { syslog(LOG_ERR, "problem with rsports file\n"); closelog(); return 1; } addrlen = sizeof(struct full_sockaddr_ax25); if (getsockname(STDIN_FILENO, (struct sockaddr *)&ax25sock, &addrlen) == -1) { syslog(LOG_ERR, "cannot getsockname, %s\n", strerror(errno)); closelog(); return 1; } addrlen = sizeof(struct full_sockaddr_ax25); if (getpeername(STDIN_FILENO, (struct sockaddr *)&ax25peer, &addrlen) == -1) { syslog(LOG_ERR, "cannot getpeername, %s\n", strerror(errno)); closelog(); return 1; } #ifdef HAVE_AX25_PIDINCL if (setsockopt(STDIN_FILENO, SOL_AX25, AX25_PIDINCL, &yes, sizeof(yes)) == -1) { syslog(LOG_ERR, "cannot setsockopt(AX25_PIDINCL) - %s\n", strerror(errno)); closelog(); return 1; } #endif /* HAVE_AX25_PIDINCL */ roseconnect.srose_family = rosebind.srose_family = AF_ROSE; roseconnect.srose_ndigis = rosebind.srose_ndigis = 0; addrlen = sizeof(struct sockaddr_rose); if ((addr = rs_config_get_addr(argv[1])) == NULL) { syslog(LOG_ERR, "invalid Rose port name - %s\n", argv[1]); closelog(); return 1; } if (rose_aton(addr, rosebind.srose_addr.rose_addr) == -1) { syslog(LOG_ERR, "invalid ROSE port address - %s\n", argv[1]); closelog(); return 1; } /* * Copy our DNIC in as default. */ memset(rose_address, 0x00, 11); memcpy(rose_address, addr, 4); for (n = 0; n < ax25peer.fsa_ax25.sax25_ndigis; n++) { addr = ax25_ntoa(&ax25peer.fsa_digipeater[n]); if (strspn(addr, "0123456789-") == strlen(addr)) { if ((p = strchr(addr, '-')) != NULL) *p = '\0'; switch (strlen(addr)) { case 4: memcpy(rose_address + 0, addr, 4); dnicindex = n; break; case 6: memcpy(rose_address + 4, addr, 6); addrindex = n; break; default: break; } } } /* * The user didn't give an address. */ if (addrindex == -1) { strcpy(buffer, "*** No ROSE address given\r"); write(STDOUT_FILENO, buffer, strlen(buffer)); sleep(20); closelog(); return 1; } if (rose_aton(rose_address, roseconnect.srose_addr.rose_addr) == -1) { syslog(LOG_ERR, "invalid Rose address - %s\n", argv[4]); closelog(); return 1; } rosebind.srose_call = ax25peer.fsa_ax25.sax25_call; roseconnect.srose_call = ax25sock.fsa_ax25.sax25_call; /* * A far end digipeater was specified. */ if (addrindex > 0) { roseconnect.srose_ndigis = 1; roseconnect.srose_digi = ax25peer.fsa_digipeater[addrindex - 1]; } /* * Check for a local digipeater. */ if (dnicindex != -1) { if (ax25peer.fsa_ax25.sax25_ndigis - dnicindex > 2) { rosebind.srose_ndigis = 1; rosebind.srose_digi = ax25peer.fsa_digipeater[dnicindex + 2]; } } else { if (ax25peer.fsa_ax25.sax25_ndigis - addrindex > 2) { rosebind.srose_ndigis = 1; rosebind.srose_digi = ax25peer.fsa_digipeater[addrindex + 2]; } } /* * Open the socket into the kernel. */ if ((s = socket(AF_ROSE, SOCK_SEQPACKET, 0)) < 0) { syslog(LOG_ERR, "cannot open ROSE socket, %s\n", strerror(errno)); closelog(); return 1; } /* * Set our AX.25 callsign and Rose address accordingly. */ if (bind(s, (struct sockaddr *)&rosebind, addrlen) != 0) { syslog(LOG_ERR, "cannot bind ROSE socket, %s\n", strerror(errno)); closelog(); close(s); return 1; } if (setsockopt(s, SOL_ROSE, ROSE_QBITINCL, &yes, sizeof(yes)) == -1) { syslog(LOG_ERR, "cannot setsockopt(ROSE_QBITINCL) - %s\n", strerror(errno)); closelog(); close(s); return 1; } if (verbose) { strcpy(buffer, "*** Connection in progress\r"); write(STDOUT_FILENO, buffer, strlen(buffer)); } /* * If no response in 5 minutes, go away. */ alarm(300); signal(SIGALRM, alarm_handler); /* * Lets try and connect to the far end. */ if (connect(s, (struct sockaddr *)&roseconnect, addrlen) != 0) { switch (errno) { case ECONNREFUSED: strcpy(buffer, "*** Disconnected - 0100 - Number Busy\r"); break; case ENETUNREACH: strcpy(buffer, "*** Disconnected - 0D00 - Not Obtainable\r"); break; case EINTR: strcpy(buffer, "*** Disconnected - 3900 - Ship Absent\r"); break; default: sprintf(buffer, "*** Disconnected - %d - %s\r", errno, strerror(errno)); break; } close(s); if (verbose) { write(STDOUT_FILENO, buffer, strlen(buffer)); sleep(20); } return 0; } /* * We got there. */ alarm(0); if (verbose) { 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, 512)) == -1) { strcpy(buffer, "\r*** Disconnected - 0000 - DTE Originated\r"); write(STDOUT_FILENO, buffer, strlen(buffer)); break; } if (buffer[0] == 0) { /* Q Bit not set */ buffer[0] = 0xF0; write(STDOUT_FILENO, buffer, n); } else { /* Lose the leading 0x7F */ write(STDOUT_FILENO, buffer + 2, n - 2); } } if (FD_ISSET(STDIN_FILENO, &read_fd)) { if ((n = read(STDIN_FILENO, buffer + 2, sizeof(buffer)-2)) == -1) { close(s); break; } if (buffer[2] == 0xF0) { buffer[2] = 0; write(s, buffer + 2, n); } else { buffer[0] = 1; /* Set Q bit on */ buffer[1] = 0x7F; /* PID Escape */ write(s, buffer, n + 2); } } } closelog(); return 0; }