/** * 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 read_conf(void) { FILE *fp, *fgt; char buf[512], line[1024], *cp; int i = 0, k; char digipath[AX25_MAX_DIGIS * 10]; if ((fp = fopen(FLEXD_CONF_FILE, "r")) == NULL) { fprintf(stderr, "flexd config: Cannot open config file: %s\n", FLEXD_CONF_FILE); return -1; } if ((fgt = fopen(FLEX_GT_FILE, "w")) == NULL) { fprintf(stderr, "flexd config: Cannot open flexnet gateways file: %s\n", FLEX_GT_FILE); fclose(fp); return -1; } fputs("addr callsign dev digipeaters\n", fgt); while (fgets(buf, sizeof(buf), fp)) { if (*buf == '#' || *buf == ' ') continue; /* comment line/empty line */ cp = strchr(buf, '#'); if (cp) *cp = '\0'; cp = strtok(buf, " \t\n\r"); if (cp == NULL) continue; /* empty line */ if (strcasecmp(cp, "pollinterval") == 0) { /* set poll interval */ cp = strtok(NULL, " \t\n\r"); if (cp == NULL) { fprintf(stderr, "flexd config: PollInterval needs an argument\n"); fclose(fp); fclose(fgt); return -1; } poll_time = safe_atoi(cp); if (poll_time < MINIMUM_POLL_TIME) poll_time = MINIMUM_POLL_TIME; } if (strcasecmp(cp, "mycall") == 0) { /* set connect call for download */ cp = strtok(NULL, " \t\n\r"); if (cp == NULL) { fprintf(stderr, "flexd config: MyCall needs an argument\n"); fclose(fp); fclose(fgt); return -1; } safe_strncpy(mycall, cp, 9); } if (strcasecmp(cp, "flexgate") == 0) { /* set flexnet gateway */ cp = strtok(NULL, " \t\n\r"); if (cp == NULL) { fprintf(stderr, "flexd config: FlexGate needs an argument\n"); fclose(fp); fclose(fgt); return -1; } safe_strncpy(flexgate, cp, 9); /* strcat(cp,"\0");*/ gw = find_route(flexgate, NULL); if (gw == NULL) { fprintf(stderr, "flexd config: FlexGate %s not found in file: %s\n", flexgate, AX_ROUTES_FILE); fclose(fp); fclose(fgt); return -1; } else { *digipath = '\0'; for (k = 0; k < AX25_MAX_DIGIS; k++) { if (gw->digis[k] == NULL) break; strcat(digipath, " "); strcat(digipath, gw->digis[k]); } if ((ax25_config_get_dev(gw->dev)) == NULL ) sprintf(line, "%05d %-8s %5s %s\n",i++, gw->dest_call, gw->dev, digipath); else /* ax25 device */ sprintf(line, "%05d %-8s %4s %s\n",i++, gw->dest_call, ax25_config_get_dev(gw->dev), digipath); fputs(line, fgt); } } } fclose(fgt); fclose(fp); return 0; }
int main(int argc, char **argv) { unsigned char buffer[BUFSIZE]; int dumpstyle = ASCII; int size; int s; char *port = NULL, *dev = NULL; struct sockaddr sa; socklen_t asize = sizeof(sa); struct ifreq ifr; int proto = ETH_P_AX25; int exit_code = EXIT_SUCCESS; timestamp = 0; while ((s = getopt(argc, argv, "8achip:rtv")) != -1) { switch (s) { case '8': sevenbit = 0; break; case 'a': proto = ETH_P_ALL; break; case 'c': color = 1; break; case 'h': dumpstyle = HEX; break; case 'i': ibmhack = 1; break; case 'p': port = optarg; break; case 'r': dumpstyle = READABLE; break; case 't': timestamp = 1; break; case 'v': printf("listen: %s\n", VERSION); return 0; case ':': fprintf(stderr, "listen: option -p needs a port name\n"); return 1; case '?': fprintf(stderr, "Usage: listen [-8] [-a] [-c] [-h] [-i] [-p port] [-r] [-t] [-v]\n"); return 1; } } if (ax25_config_load_ports() == 0) fprintf(stderr, "listen: no AX.25 port data configured\n"); if (port != NULL) { if ((dev = ax25_config_get_dev(port)) == NULL) { fprintf(stderr, "listen: invalid port name - %s\n", port); return 1; } } if ((sock = socket(PF_PACKET, SOCK_PACKET, htons(proto))) == -1) { perror("socket"); return 1; } if (color) { color = initcolor(); /* Initialize color support */ if (!color) printf("Could not initialize color support.\n"); } setservent(1); while (!sigint) { asize = sizeof(sa); signal(SIGINT, handle_sigint); signal(SIGTERM, handle_sigint); if ((size = recvfrom(sock, buffer, sizeof(buffer), 0, &sa, &asize)) == -1) { /* * Signals are cared for by the handler, and we * don't want to abort on SIGWINCH */ if (errno == EINTR) { refresh(); continue; } else if (!(errno == EBADF && sigint)) { perror("recv"); exit_code = errno; } break; } signal(SIGINT, SIG_DFL); signal(SIGTERM, SIG_DFL); if (sock == -1 || sigint) break; if (dev != NULL && strcmp(dev, sa.sa_data) != 0) continue; if (proto == ETH_P_ALL) { strcpy(ifr.ifr_name, sa.sa_data); signal(SIGINT, handle_sigint); signal(SIGTERM, handle_sigint); if (ioctl(sock, SIOCGIFHWADDR, &ifr) == -1) { if (!(errno == EBADF && sigint)) { perror("SIOCGIFHWADDR"); exit_code = errno; break; } } signal(SIGINT, SIG_DFL); signal(SIGTERM, SIG_DFL); if (sock == -1 || sigint) break; if (ifr.ifr_hwaddr.sa_family == AF_AX25) { display_port(sa.sa_data); #ifdef NEW_AX25_STACK ax25_dump(buffer, size, dumpstyle); #else ki_dump(buffer, size, dumpstyle); #endif /* lprintf(T_DATA, "\n"); */ } } else { display_port(sa.sa_data); #ifdef NEW_AX25_STACK ax25_dump(buffer, size, dumpstyle); #else ki_dump(buffer, size, dumpstyle); #endif /* lprintf(T_DATA, "\n"); */ } if (color) refresh(); } if (color) endwin(); return exit_code; }