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; }
/* * 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"); }
/** * Function: main * * The calling convention for this function is: * * wl2kax25 -c targetcall -a ax25port -t timeoutsecs -e emailaddress * * The parameters are: * mycall : my call sign, which MUST be set in wl2k.conf * targetcall: callsign for the RMS * ax25port: name of the ax25 port to use (e.g., sm0) * timeoutsecs: timeout in seconds * emailaddress: email address where the retrieved message will be sent via sendmail * * The targetcall parameter does not support a path yet. */ int main(int argc, char *argv[]) { int s; FILE *fp; unsigned int addrlen = 0; union { struct full_sockaddr_ax25 ax25; struct sockaddr_rose rose; } sockaddr; char *dev; pid_t procID; int sv[2]; int ready; struct pollfd fds[2]; ssize_t len; unsigned char *pbuf; ssize_t byteswritten; static cfg_t cfg; loadconfig(argc, argv, &cfg); g_mime_init(0); setlinebuf(stdout); if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv)) { perror("socketpair"); exit(EXIT_FAILURE); } // Begin AX25 socket code if (ax25_config_load_ports() == 0) fprintf(stderr, "wl2kax25: no AX.25 port data configured\n"); if (cfg.ax25port != NULL) { if ((dev = ax25_config_get_dev(cfg.ax25port)) == NULL) { fprintf(stderr, "wl2kax25: invalid port name - %s\n", cfg.ax25port); return(EXIT_FAILURE); } } if ((s = socket(AF_AX25, SOCK_SEQPACKET, 0)) == -1) { perror("socket"); printf("%d\n", __LINE__); exit(EXIT_FAILURE); } ax25_aton(ax25_config_get_addr(cfg.ax25port), &sockaddr.ax25); ax25_aton(cfg.mycall, &sockaddr.ax25); if (sockaddr.ax25.fsa_ax25.sax25_ndigis == 0) { ax25_aton_entry(ax25_config_get_addr(cfg.ax25port), 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 (bind(s, (struct sockaddr *) &sockaddr, addrlen) == -1) { perror("bind"); close(s); exit(EXIT_FAILURE); } if (ax25_aton(cfg.targetcall, &sockaddr.ax25) < 0) { close(s); perror("ax25_aton()"); exit(EXIT_FAILURE); } sockaddr.rose.srose_family = AF_AX25; addrlen = sizeof(struct full_sockaddr_ax25); settimeout(cfg.timeoutsecs); if (connect(s, (struct sockaddr *) &sockaddr, addrlen) != 0) { close(s); perror("connect()"); exit(EXIT_FAILURE); } unsettimeout(); printf("Connected to AX.25 stack\n"); fflush(stdout); // End AX25 socket code // Fork a process if ((procID = fork())) { // Parent processing if (-1 == procID) { fprintf(stderr, "fork\n"); exit(EXIT_FAILURE); } close(sv[1]); fds[0].fd = s; fds[0].events = POLLIN; fds[1].fd = sv[0]; fds[1].events = POLLIN; // poll here and feed to the ax25 socket. // Data must be chunked to the appropriate size for (;;) { ready = poll(fds, sizeof(fds)/sizeof(struct pollfd), -1); if (-1 == ready) { if (EINTR == errno) break; close(s); perror("poll"); exit(EXIT_FAILURE); } // Inbound if (fds[0].revents & POLLIN) { len = read(fds[0].fd, axread, sizeof(axread)); if ( len > 0 ) { pbuf = axread; while(len > 0) { byteswritten = write(fds[1].fd, pbuf, MIN(paclen, (size_t)len)); if (byteswritten == 0 || (byteswritten < 0 && errno != EAGAIN)) { fprintf(stderr,"%s error on inbound write: %s)\n", getprogname(), strerror(errno)); break; } pbuf += byteswritten; len -= byteswritten; } } else if (len == 0) { close(s); printf("EOF on ax25 socket, exiting...\n"); exit(EXIT_FAILURE); } } // Outbound if (fds[1].revents & POLLIN) { len = read(fds[1].fd, axwrite, sizeof(axwrite)); if (len > 0 ) { pbuf = axwrite; while(len > 0) { byteswritten = write(fds[0].fd, pbuf, MIN(paclen, (size_t)len)); if (byteswritten == 0 || (byteswritten < 0 && errno != EAGAIN)) { fprintf(stderr,"%s error on outbound write: %s)\n", getprogname(), strerror(errno)); break; } pbuf += byteswritten; len -= byteswritten; } } else if (len == 0) { printf("EOF on child fd, terminating communications loop.\n"); break; } } } printf("Closing ax25 connection\n"); #if 1 { time_t start_time, current_time; bool bax25conn; start_time = time(NULL); /* get current time in seconds */ if ((bax25conn=isax25connected(s)) == TRUE) { printf("Waiting for AX25 peer ... "); while(isax25connected(s)){ current_time = time(NULL); if (difftime(current_time, start_time) > 5) { break; } } if (isax25connected(s)) { printf("timeout\n"); }else { printf("disconnected\n"); } } } #endif g_mime_shutdown(); close(sv[0]); close(s); exit(EXIT_SUCCESS); return 1; } else { // Child processing printf("Child process\n"); close(sv[0]); if ((fp = fdopen(sv[1], "r+b")) == NULL) { close(sv[1]); perror("fdopen()"); _exit(EXIT_FAILURE); } /* set buf size to paclen */ setvbuf(fp, NULL, _IOFBF, paclen); /* * The messages are exchanged in this call * * TODO: The sid sent by the client should contain an NXX, * where NXX represents N followed by two digits of SSID. * This allows the RMS to find the correct registered * user in case the SSID has been changed in the network. */ if(cfg.bVerbose) { printf("Child process calling wl2kexchange()\n"); } settimeout(cfg.timeoutsecs); wl2kexchange(cfg.mycall, cfg.targetcall, fp, fp, cfg.emailaddr); fclose(fp); printf("Child process exiting\n"); _exit(EXIT_SUCCESS); } }
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 ax25_init(int* sock, char* src_port, char* dst_call) { int protocol = 0; /* Use default protocol */ int sockfd; char* src_call; struct full_sockaddr_ax25 src_addr; struct full_sockaddr_ax25 dst_addr; unsigned src_addr_len; unsigned dst_addr_len; char buf[256]; int buf_len = 256; int msg_len; struct timeval timeout; if (ax25_config_load_ports() == 0) { return -1001; } ax25_list_ports(); if ((src_call = ax25_config_get_addr(src_port)) == NULL) { return -1002; } fprintf(stderr, "src_call=%s\n", src_call); fprintf(stderr, "dst_call=%s\n", dst_call); if ((src_addr_len = ax25_aton(src_call, &src_addr)) == -1) { return -1003; } if ((dst_addr_len = ax25_aton(dst_call, &dst_addr)) == -1) { return -1004; } if ((sockfd = socket(AF_AX25, SOCK_DGRAM, protocol)) == -1) { fprintf(stderr, "socket err=%d\n", errno); return errno; } if (bind(sockfd, (struct sockaddr *) &src_addr, src_addr_len) == -1) { fprintf(stderr, "bind err=%d\n", errno); return errno; } /* * Try send something. */ if (sendto(sockfd, "asd", 3, 0, (struct sockaddr *) &dst_addr, dst_addr_len) == -1) { fprintf(stderr, "sendto err=%d\n", errno); return errno; } /* * Configure timeout for receive. */ timeout.tv_sec = 10; timeout.tv_usec = 0; if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) != 0) { fprintf(stderr, "setsockopt err=%d\n", errno); return errno; } /* * Do receive. */ fprintf(stderr, "recvfrom...\n"); if ((msg_len = recvfrom(sockfd, &buf, buf_len, 0, (struct sockaddr *) &dst_addr, &dst_addr_len)) == -1) { fprintf(stderr, "recvfrom err=%d\n", errno); return errno; } fprintf(stderr, "recvfrom... done, msglen=%d\n", msg_len); *sock = sockfd; return 0; }