コード例 #1
0
ファイル: port_link.c プロジェクト: alhazred/onarm
/*
 * Removes port entries that no longer have devices
 * backing them
 * Schedules an update the sacadm (portmon) database
 */
static void
rm_dangling_port(char *devname)
{
	char *portstr;
	int  portnum;

	devfsadm_print(PORT_MID, "%s:rm_stale_port: %s\n",
	    modname, devname);

	if ((portstr = strrchr(devname, (int)'/')) == NULL) {
		devfsadm_errprint("%s: invalid name: %s\n",
		    modname, devname);
		return;
	}
	portstr++;

	/*
	 * mark for removal from sacadm database
	 */
	if ((portnum = parse_portno(portstr)) != -1)
		pma[portnum].flags |= PORT_REMOVED;

	devfsadm_rm_all(devname);
}
コード例 #2
0
ファイル: logging.c プロジェクト: 0ndorio/gnupg
static gpgrt_ssize_t
fun_writer (void *cookie_arg, const void *buffer, size_t size)
{
  struct fun_cookie_s *cookie = cookie_arg;

  /* FIXME: Use only estream with a callback for socket writing.  This
     avoids the ugly mix of fd and estream code.  */

  /* Note that we always try to reconnect to the socket but print
     error messages only the first time an error occurred.  If
     RUNNING_DETACHED is set we don't fall back to stderr and even do
     not print any error messages.  This is needed because detached
     processes often close stderr and by writing to file descriptor 2
     we might send the log message to a file not intended for logging
     (e.g. a pipe or network connection). */
  if (cookie->want_socket && cookie->fd == -1)
    {
#ifdef WITH_IPV6
      struct sockaddr_in6 srvr_addr_in6;
#endif
      struct sockaddr_in srvr_addr_in;
#ifndef HAVE_W32_SYSTEM
      struct sockaddr_un srvr_addr_un;
#endif
      size_t addrlen;
      struct sockaddr *srvr_addr = NULL;
      unsigned short port = 0;
      int af = AF_LOCAL;
      int pf = PF_LOCAL;
      const char *name = cookie->name;

      /* Not yet open or meanwhile closed due to an error. */
      cookie->is_socket = 0;

      /* Check whether this is a TCP socket or a local socket.  */
      if (!strncmp (name, "tcp://", 6) && name[6])
        {
          name += 6;
          af = AF_INET;
          pf = PF_INET;
        }
#ifndef HAVE_W32_SYSTEM
      else if (!strncmp (name, "socket://", 9) && name[9])
        name += 9;
#endif

      if (af == AF_LOCAL)
        {
#ifdef HAVE_W32_SYSTEM
          addrlen = 0;
#else
          memset (&srvr_addr, 0, sizeof srvr_addr);
          srvr_addr_un.sun_family = af;
          strncpy (srvr_addr_un.sun_path,
                   name, sizeof (srvr_addr_un.sun_path)-1);
          srvr_addr_un.sun_path[sizeof (srvr_addr_un.sun_path)-1] = 0;
          srvr_addr = (struct sockaddr *)&srvr_addr_un;
          addrlen = SUN_LEN (&srvr_addr_un);
#endif
        }
      else
        {
          char *addrstr, *p;
#ifdef HAVE_INET_PTON
          void *addrbuf = NULL;
#endif /*HAVE_INET_PTON*/

          addrstr = xtrymalloc (strlen (name) + 1);
          if (!addrstr)
            addrlen = 0; /* This indicates an error.  */
          else if (*name == '[')
            {
              /* Check for IPv6 literal address.  */
              strcpy (addrstr, name+1);
              p = strchr (addrstr, ']');
              if (!p || p[1] != ':' || !parse_portno (p+2, &port))
                {
                  gpg_err_set_errno (EINVAL);
                  addrlen = 0;
                }
              else
                {
                  *p = 0;
#ifdef WITH_IPV6
                  af = AF_INET6;
                  pf = PF_INET6;
                  memset (&srvr_addr_in6, 0, sizeof srvr_addr_in6);
                  srvr_addr_in6.sin6_family = af;
                  srvr_addr_in6.sin6_port = htons (port);
#ifdef HAVE_INET_PTON
                  addrbuf = &srvr_addr_in6.sin6_addr;
#endif /*HAVE_INET_PTON*/
                  srvr_addr = (struct sockaddr *)&srvr_addr_in6;
                  addrlen = sizeof srvr_addr_in6;
#else
                  gpg_err_set_errno (EAFNOSUPPORT);
                  addrlen = 0;
#endif
                }
            }
          else
            {
              /* Check for IPv4 literal address.  */
              strcpy (addrstr, name);
              p = strchr (addrstr, ':');
              if (!p || !parse_portno (p+1, &port))
                {
                  gpg_err_set_errno (EINVAL);
                  addrlen = 0;
                }
              else
                {
                  *p = 0;
                  memset (&srvr_addr_in, 0, sizeof srvr_addr_in);
                  srvr_addr_in.sin_family = af;
                  srvr_addr_in.sin_port = htons (port);
#ifdef HAVE_INET_PTON
                  addrbuf = &srvr_addr_in.sin_addr;
#endif /*HAVE_INET_PTON*/
                  srvr_addr = (struct sockaddr *)&srvr_addr_in;
                  addrlen = sizeof srvr_addr_in;
                }
            }

          if (addrlen)
            {
#ifdef HAVE_INET_PTON
              if (inet_pton (af, addrstr, addrbuf) != 1)
                addrlen = 0;
#else /*!HAVE_INET_PTON*/
              /* We need to use the old function.  If we are here v6
                 support isn't enabled anyway and thus we can do fine
                 without.  Note that Windows has a compatible inet_pton
                 function named inetPton, but only since Vista.  */
              srvr_addr_in.sin_addr.s_addr = inet_addr (addrstr);
              if (srvr_addr_in.sin_addr.s_addr == INADDR_NONE)
                addrlen = 0;
#endif /*!HAVE_INET_PTON*/
            }

          xfree (addrstr);
        }

      cookie->fd = addrlen? socket (pf, SOCK_STREAM, 0) : -1;
      if (cookie->fd == -1)
        {
          if (!cookie->quiet && !running_detached
              && isatty (es_fileno (es_stderr)))
            es_fprintf (es_stderr, "failed to create socket for logging: %s\n",
                        strerror(errno));
        }
      else
        {
          if (connect (cookie->fd, srvr_addr, addrlen) == -1)
            {
              if (!cookie->quiet && !running_detached
                  && isatty (es_fileno (es_stderr)))
                es_fprintf (es_stderr, "can't connect to '%s': %s\n",
                            cookie->name, strerror(errno));
              sock_close (cookie->fd);
              cookie->fd = -1;
            }
        }

      if (cookie->fd == -1)
        {
          if (!running_detached)
            {
              /* Due to all the problems with apps not running
                 detached but being called with stderr closed or used
                 for a different purposes, it does not make sense to
                 switch to stderr.  We therefore disable it. */
              if (!cookie->quiet)
                {
                  /* fputs ("switching logging to stderr\n", stderr);*/
                  cookie->quiet = 1;
                }
              cookie->fd = -1; /*fileno (stderr);*/
            }
        }
      else /* Connection has been established. */
        {
          cookie->quiet = 0;
          cookie->is_socket = 1;
        }
    }

  log_socket = cookie->fd;
  if (cookie->fd != -1)
    {
#ifdef HAVE_W32CE_SYSTEM
      if (cookie->use_writefile)
        {
          DWORD nwritten;

          WriteFile ((HANDLE)cookie->fd, buffer, size, &nwritten, NULL);
          return (gpgrt_ssize_t)size; /* Okay.  */
        }
#endif
      if (!writen (cookie->fd, buffer, size, cookie->is_socket))
        return (gpgrt_ssize_t)size; /* Okay. */
    }

  if (!running_detached && cookie->fd != -1
      && isatty (es_fileno (es_stderr)))
    {
      if (*cookie->name)
        es_fprintf (es_stderr, "error writing to '%s': %s\n",
                    cookie->name, strerror(errno));
      else
        es_fprintf (es_stderr, "error writing to file descriptor %d: %s\n",
                    cookie->fd, strerror(errno));
    }
  if (cookie->is_socket && cookie->fd != -1)
    {
      sock_close (cookie->fd);
      cookie->fd = -1;
      log_socket = -1;
    }

  return (gpgrt_ssize_t)size;
}
コード例 #3
0
/* Make a connection to the Unix domain socket NAME and return a new
   Assuan context in CTX.  SERVER_PID is currently not used but may
   become handy in the future.  Defined flag bits are:

     ASSUAN_SOCKET_CONNECT_FDPASSING
        sendmsg and recvmsg are used.

   NAME must either start with a slash and optional with a drive
   prefix ("c:") or use one of these URL schemata:

      file://<fname>

        This is the same as the default just with an explicit schemata.

      assuan://<ipaddr>:<port>
      assuan://[<ip6addr>]:<port>

        Connect using TCP to PORT of the server with the numerical
        IPADDR.  Note that '[' and ']' are literal characters.

  */
gpg_error_t
assuan_socket_connect (assuan_context_t ctx, const char *name,
		       pid_t server_pid, unsigned int flags)
{
  gpg_error_t err = 0;
  assuan_fd_t fd;
#ifdef WITH_IPV6
  struct sockaddr_in6 srvr_addr_in6;
#endif
  struct sockaddr_un srvr_addr_un;
  struct sockaddr_in srvr_addr_in;
  struct sockaddr *srvr_addr = NULL;
  uint16_t port = 0;
  size_t len = 0;
  const char *s;
  int af = AF_LOCAL;
  int pf = PF_LOCAL;

  TRACE2 (ctx, ASSUAN_LOG_CTX, "assuan_socket_connect", ctx,
	  "name=%s, flags=0x%x", name ? name : "(null)", flags);

  if (!ctx || !name)
    return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);

  if (!strncmp (name, "file://", 7) && name[7])
    name += 7;
  else if (!strncmp (name, "assuan://", 9) && name[9])
    {
      name += 9;
      af = AF_INET;
      pf = PF_INET;
    }
  else /* Default.  */
    {
      /* We require that the name starts with a slash if no URL
         schemata is used.  To make things easier we allow an optional
         drive prefix.  */
      s = name;
      if (*s && s[1] == ':')
        s += 2;
      if (*s != DIRSEP_C && *s != '/')
        return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);
    }

  if (af == AF_LOCAL)
    {
      if (strlen (name)+1 >= sizeof srvr_addr_un.sun_path)
        return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE);

      memset (&srvr_addr_un, 0, sizeof srvr_addr_un);
      srvr_addr_un.sun_family = AF_LOCAL;
      strncpy (srvr_addr_un.sun_path, name, sizeof (srvr_addr_un.sun_path) - 1);
      srvr_addr_un.sun_path[sizeof (srvr_addr_un.sun_path) - 1] = 0;
      len = SUN_LEN (&srvr_addr_un);

      srvr_addr = (struct sockaddr *)&srvr_addr_un;
    }
  else
    {
      char *addrstr, *p;
#ifdef HAVE_INET_PTON
      void *addrbuf = NULL;
#endif

      addrstr = _assuan_malloc (ctx, strlen (name) + 1);
      if (!addrstr)
        return _assuan_error (ctx, gpg_err_code_from_syserror ());

      if (*name == '[')
        {
          strcpy (addrstr, name+1);
          p = strchr (addrstr, ']');
          if (!p || p[1] != ':' || !parse_portno (p+2, &port))
            err = _assuan_error (ctx, GPG_ERR_BAD_URI);
          else
            {
              *p = 0;
#ifdef WITH_IPV6
              af = AF_INET6;
              pf = PF_INET6;
              memset (&srvr_addr_in6, 0, sizeof srvr_addr_in6);
              srvr_addr_in6.sin6_family = af;
              srvr_addr_in6.sin6_port = htons (port);
#ifdef HAVE_INET_PTON
              addrbuf = &srvr_addr_in6.sin6_addr;
#endif
              srvr_addr = (struct sockaddr *)&srvr_addr_in6;
              len = sizeof srvr_addr_in6;
#else
              err =  _assuan_error (ctx, GPG_ERR_EAFNOSUPPORT);
#endif
            }
        }
      else
        {
          strcpy (addrstr, name);
          p = strchr (addrstr, ':');
          if (!p || !parse_portno (p+1, &port))
            err = _assuan_error (ctx, GPG_ERR_BAD_URI);
          else
            {
              *p = 0;
              memset (&srvr_addr_in, 0, sizeof srvr_addr_in);
              srvr_addr_in.sin_family = af;
              srvr_addr_in.sin_port = htons (port);
#ifdef HAVE_INET_PTON
              addrbuf = &srvr_addr_in.sin_addr;
#endif
              srvr_addr = (struct sockaddr *)&srvr_addr_in;
              len = sizeof srvr_addr_in;
            }
        }

      if (!err)
        {
#ifdef HAVE_INET_PTON
          switch (inet_pton (af, addrstr, addrbuf))
            {
            case 1:  break;
            case 0:  err = _assuan_error (ctx, GPG_ERR_BAD_URI); break;
            default: err = _assuan_error (ctx, gpg_err_code_from_syserror ());
            }
#else /*!HAVE_INET_PTON*/
          /* We need to use the old function.  If we are here v6
             support isn't enabled anyway and thus we can do fine
             without.  Note that Windows as a compatible inet_pton
             function named inetPton, but only since Vista.  */
          srvr_addr_in.sin_addr.s_addr = inet_addr (addrstr);
          if (srvr_addr_in.sin_addr.s_addr == INADDR_NONE)
            err = _assuan_error (ctx, GPG_ERR_BAD_URI);
#endif /*!HAVE_INET_PTON*/
        }

      _assuan_free (ctx, addrstr);
      if (err)
        return err;
    }

  fd = _assuan_sock_new (ctx, pf, SOCK_STREAM, 0);
  if (fd == ASSUAN_INVALID_FD)
    {
      err = _assuan_error (ctx, gpg_err_code_from_syserror ());
      TRACE1 (ctx, ASSUAN_LOG_SYSIO, "assuan_socket_connect", ctx,
              "can't create socket: %s", strerror (errno));
      return err;
    }

  if (_assuan_sock_connect (ctx, fd, srvr_addr, len) == -1)
    {
      TRACE2 (ctx, ASSUAN_LOG_SYSIO, "assuan_socket_connect", ctx,
	      "can't connect to `%s': %s\n", name, strerror (errno));
      _assuan_close (ctx, fd);
      return _assuan_error (ctx, GPG_ERR_ASS_CONNECT_FAILED);
    }

  err = _assuan_connect_finalize (ctx, fd, flags);

  if (err)
    _assuan_reset (ctx);

  return err;
}
コード例 #4
0
ファイル: port_link.c プロジェクト: alhazred/onarm
/*
 * Determine which port monitor entries already exist by invoking pmadm(1m)
 * to list all configured 'ttymon' port monitor entries.
 * Do not explicitly report errors from executing pmadm(1m) or sacadm(1m)
 * commands to remain compatible with the ports(1m) implementation.
 */
static int
load_ttymondb(void)
{
	char	cmdline[CMDLEN];
	char	cmdbuf[PMTAB_MAXLINE+1];
	int	sac_exitval;
	FILE	*fs_popen;
	char	*portname;	/* pointer to a tty name */
	int	portnum;
	char	*ptr;
	char	*error_msg = "%s: failed to load port monitor database\n";

	(void) strcpy(cmdline, "/usr/sbin/pmadm -L -t ttymon");
	fs_popen = popen(cmdline, "r");
	if (fs_popen == NULL) {
		devfsadm_print(VERBOSE_MID, error_msg, modname);
		return (DEVFSADM_FAILURE);
	}

	while (fgets(cmdbuf, PMTAB_MAXLINE, fs_popen) != NULL) {
		if ((portname = pmtab_parse_portname(cmdbuf)) == NULL) {
			devfsadm_print(VERBOSE_MID,
			    "load_ttymondb: failed to parse portname\n");
			devfsadm_print(VERBOSE_MID,
			    "load_ttymondb: buffer \"%s\"\n", cmdbuf);
			goto load_failed;
		}

		devfsadm_print(PORT_MID, "%s:load_ttymondb: port %s ",
		    modname, portname);

		/*
		 * skip onboard ports
		 * There is no reliable way to determine if we
		 * should start a port monitor on these lines.
		 */
		if ((portnum = parse_portno(portname)) == -1) {
			devfsadm_print(PORT_MID, "ignored\n");
			continue;
		}

		/*
		 * the first field of the pmadm output is
		 * the port monitor name for this entry
		 */
		if ((ptr = strchr(cmdbuf, PMTAB_SEPR)) == NULL) {
			devfsadm_print(VERBOSE_MID,
			    "load_ttymondb: no portmon tag\n");
			goto load_failed;
		}

		*ptr = MN_NULLCHAR;
		if ((pma[portnum].pm_tag = strdup(cmdbuf)) == NULL) {
			devfsadm_errprint("load_ttymondb: failed strdup\n");
			goto load_failed;
		}
		pma[portnum].flags |= PM_HAS_ENTRY;
		pma[PM_SLOT(portnum)].flags |= HAS_PORT_MON;
		devfsadm_print(PORT_MID, "present\n");
	}
	(void) pclose(fs_popen);
	return (DEVFSADM_SUCCESS);

load_failed:

	/*
	 * failed to load the port monitor database
	 */
	devfsadm_print(VERBOSE_MID, error_msg, modname);
	sac_exitval = SAC_EXITVAL(pclose(fs_popen));
	if (sac_exitval != 0) {
		devfsadm_print(VERBOSE_MID,
		    "pmadm: (%s) %s\n", SAC_EID(sac_exitval),
		    SAC_EMSG(sac_exitval));
	}
	return (DEVFSADM_FAILURE);
}
コード例 #5
0
ファイル: port_link.c プロジェクト: alhazred/onarm
/*
 * Called for all serial devices that are NOT onboard
 * Creates links of the form "/dev/term/[0..n]"
 * Schedules an update the sacadm (portmon).
 */
static int
serial_port_create(di_minor_t minor, di_node_t node)
{
	char l_path[MAXPATHLEN], p_path[MAXPATHLEN];
	char *devfspath, *buf, *minor_name;
	int port_num;

	devfspath = di_devfs_path(node);
	if (devfspath == NULL) {
		devfsadm_errprint("%s: di_devfs_path() failed\n", modname);
		return (DEVFSADM_CONTINUE);
	}

	if ((minor_name = di_minor_name(minor)) == NULL) {
		devfsadm_errprint("%s: NULL minor name\n\t%s\n", modname,
		    devfspath);
		di_devfs_path_free(devfspath);
		return (DEVFSADM_CONTINUE);
	}

	/*
	 * verify dialout ports do not come in on this nodetype
	 */
	if (is_dialout(minor_name)) {
		devfsadm_errprint("%s: dialout device\n\t%s:%s\n",
		    modname, devfspath, minor_name);
		di_devfs_path_free(devfspath);
		return (DEVFSADM_CONTINUE);
	}

	/*
	 *  add the minor name to the physical path so we can
	 *  enum the port# and create the the link.
	 */
	(void) strcpy(p_path, devfspath);
	(void) strcat(p_path, ":");
	(void) strcat(p_path, minor_name);
	di_devfs_path_free(devfspath);

	if (devfsadm_enumerate_int(p_path, 0, &buf, port_rules, 1)) {
		devfsadm_errprint("%s:serial_port_create:"
		    " enumerate_int() failed\n\t%s\n",
		    modname, p_path);
		return (DEVFSADM_CONTINUE);
	}

	(void) strcpy(l_path, "term/");
	(void) strcat(l_path, buf);
	(void) devfsadm_mklink(l_path, node, minor, 0);

	/*
	 * update the portmon database if this port falls within
	 * the valid range of ports.
	 */
	if ((port_num = parse_portno(buf)) != -1) {
		pma[port_num].flags |= HAS_PORT_DEVICE;
	}

	free(buf);
	return (DEVFSADM_CONTINUE);
}