Пример #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;
}
Пример #2
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");
      }
Пример #3
0
/**
 * 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);
  }
}
Пример #4
0
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;
}
Пример #5
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;
}