Example #1
0
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;
}
Example #2
0
File: flexd.c Project: ve7fet/fpac
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;
}
Example #3
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");
      }
Example #4
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;
}