Esempio n. 1
0
int
control_init(struct control_sock *cs)
{
	struct sockaddr_un	 sun;
	int			 fd;
	mode_t			 old_umask, mode;

	if (cs->cs_name == NULL)
		return (0);

	if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
		log_warn("control_init: socket");
		return (-1);
	}

	sun.sun_family = AF_UNIX;
	if (strlcpy(sun.sun_path, cs->cs_name,
	    sizeof(sun.sun_path)) >= sizeof(sun.sun_path)) {
		log_warn("control_init: %s name too long", cs->cs_name);
		close(fd);
		return (-1);
	}

	if (unlink(cs->cs_name) == -1)
		if (errno != ENOENT) {
			log_warn("control_init: unlink %s", cs->cs_name);
			close(fd);
			return (-1);
		}

	if (cs->cs_restricted) {
		old_umask = umask(S_IXUSR|S_IXGRP|S_IXOTH);
		mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
	} else {
		old_umask = umask(S_IXUSR|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH);
		mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP;
	}

	if (bind(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) {
		log_warn("control_init: bind: %s", cs->cs_name);
		close(fd);
		(void)umask(old_umask);
		return (-1);
	}
	(void)umask(old_umask);

	if (chmod(cs->cs_name, mode) == -1) {
		log_warn("control_init: chmod");
		close(fd);
		(void)unlink(cs->cs_name);
		return (-1);
	}
	TAILQ_INIT(&ctl_conns);

	fd_nonblock(fd);
	cs->cs_fd = fd;

	return (0);
}
Esempio n. 2
0
int
udp_attach(PNATState pData, struct socket *so)
{
    struct sockaddr_in *addr;
    struct sockaddr sa_addr;
    socklen_t socklen = sizeof(struct sockaddr);
    int status;
    int opt = 1;

    /* We attaching some olready attched socket ??? */
    Assert(so->so_type == 0);
    if ((so->s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
        goto error;
    /*
     * Here, we bind() the socket.  Although not really needed
     * (sendto() on an unbound socket will bind it), it's done
     * here so that emulation of ytalk etc. don't have to do it
     */
    memset(&sa_addr, 0, sizeof(struct sockaddr));
    addr = (struct sockaddr_in *)&sa_addr;
#ifdef RT_OS_DARWIN
    addr->sin_len = sizeof(struct sockaddr_in);
#endif
    addr->sin_family = AF_INET;
    addr->sin_addr.s_addr = pData->bindIP.s_addr;
    fd_nonblock(so->s);
    if (bind(so->s, &sa_addr, sizeof(struct sockaddr_in)) < 0)
    {
        int lasterrno = errno;
        closesocket(so->s);
        so->s = -1;
#ifdef RT_OS_WINDOWS
        WSASetLastError(lasterrno);
#else
        errno = lasterrno;
#endif
        goto error;
    }
    /* success, insert in queue */
    so->so_expire = curtime + SO_EXPIRE;
    /* enable broadcast for later use */
    setsockopt(so->s, SOL_SOCKET, SO_BROADCAST, (const char *)&opt, sizeof(opt));
    status = getsockname(so->s, &sa_addr, &socklen);
    Assert(status == 0 && sa_addr.sa_family == AF_INET);
    so->so_hlport = ((struct sockaddr_in *)&sa_addr)->sin_port;
    so->so_hladdr.s_addr = ((struct sockaddr_in *)&sa_addr)->sin_addr.s_addr;

    SOCKET_LOCK_CREATE(so);
    QSOCKET_LOCK(udb);
    insque(pData, so, &udb);
    NSOCK_INC();
    QSOCKET_UNLOCK(udb);
    so->so_type = IPPROTO_UDP;
    return so->s;
error:
    Log2(("NAT: can't create datagramm socket\n"));
    return -1;
}
Esempio n. 3
0
void set_socket_non_blocking(int socket)
{
    const auto non_blocking_result = fd_nonblock(socket);
    if(non_blocking_result == -1)
    {
        std::cout << "Error setting socket to non blocking. error #" << errno << std::endl;
        exit(1);
    }
}
Esempio n. 4
0
int main(int argc, char *argv[]) {
        int r, accept_fd;
        uid_t uid, bus_uid;
        gid_t gid;

        log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
        log_parse_environment();
        log_open();

        bus_uid = getuid();

        if (geteuid() == 0) {
                const char *user = "******";

                r = get_user_creds(&user, &uid, &gid, NULL, NULL);
                if (r < 0) {
                        log_error_errno(r, "Cannot resolve user name %s: %m", user);
                        goto finish;
                }

                r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER);
                if (r < 0) {
                        log_error_errno(r, "Cannot drop privileges: %m");
                        goto finish;
                }
        }

        r = parse_argv(argc, argv);
        if (r <= 0)
                goto finish;

        r = sd_listen_fds(0);
        if (r != 1) {
                log_error("Illegal number of file descriptors passed");
                goto finish;
        }

        accept_fd = SD_LISTEN_FDS_START;

        r = fd_nonblock(accept_fd, false);
        if (r < 0) {
                log_error_errno(r, "Cannot mark accept-fd non-blocking: %m");
                goto finish;
        }

        r = loop_clients(accept_fd, bus_uid);

finish:
        sd_notify(false,
                  "STOPPING=1\n"
                  "STATUS=Shutting down.");

        strv_free(arg_configuration);
        free(arg_address);

        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}
Esempio n. 5
0
int raw_export_start(RawExport *e, const char *path, int fd, ImportCompressType compress) {
        _cleanup_close_ int sfd = -1, tfd = -1;
        int r;

        assert(e);
        assert(path);
        assert(fd >= 0);
        assert(compress < _IMPORT_COMPRESS_TYPE_MAX);
        assert(compress != IMPORT_COMPRESS_UNKNOWN);

        if (e->output_fd >= 0)
                return -EBUSY;

        r = fd_nonblock(fd, true);
        if (r < 0)
                return r;

        r = free_and_strdup(&e->path, path);
        if (r < 0)
                return r;

        sfd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY);
        if (sfd < 0)
                return -errno;

        if (fstat(sfd, &e->st) < 0)
                return -errno;
        r = stat_verify_regular(&e->st);
        if (r < 0)
                return r;

        /* Try to take a reflink snapshot of the file, if we can t make the export atomic */
        tfd = reflink_snapshot(sfd, path);
        if (tfd >= 0)
                e->input_fd = TAKE_FD(tfd);
        else
                e->input_fd = TAKE_FD(sfd);

        r = import_compress_init(&e->compress, compress);
        if (r < 0)
                return r;

        r = sd_event_add_io(e->event, &e->output_event_source, fd, EPOLLOUT, raw_export_on_output, e);
        if (r == -EPERM) {
                r = sd_event_add_defer(e->event, &e->output_event_source, raw_export_on_defer, e);
                if (r < 0)
                        return r;

                r = sd_event_source_set_enabled(e->output_event_source, SD_EVENT_ON);
        }
        if (r < 0)
                return r;

        e->output_fd = fd;
        return r;
}
Esempio n. 6
0
int main(int argc, char **argv) {
	FILE *dst;
	int gps_fd=-1;
	char *port;
	int baudrate;
	char *dst_fn;
	struct pollfd pfd = {.fd=-1, .events=POLLIN|POLLERR|POLLHUP};
	struct timespec ts;
	
	assert(argc > 3);
	port = argv[1];
	baudrate = atoi(argv[2]);
	dst_fn = argv[3];
	
	dst = fopen(dst_fn, "a");
	assert(dst);
	
	while(1) {
		int res;
		if(gps_fd < 0) {
			gps_fd = rs232_init(port, baudrate, 0, 0);
			if(gps_fd>=0) {
				fd_nonblock(gps_fd);
				pfd.fd = gps_fd;
				puts("GPS connected");
			}
		}
		res = poll(&pfd, 1, 1000);
		clock_gettime(CLOCK_REALTIME, &ts);
		if(res < 0)
			continue;
		if(pfd.revents & (POLLERR|POLLHUP)) {
			close(gps_fd);
			gps_fd = -1;
			pfd.fd = -1;
			puts("GPS lost");
		}
		else if(pfd.revents & POLLIN) {
			res=read(gps_fd, buf, sizeof(buf));
			if(res > 0) {
				fprintf(dst, "%d.%ld\n",(int)ts.tv_sec, ts.tv_nsec);
				fwrite(buf, res, 1, dst);
				fflush(dst);
			}
			if(res >= 0)
				continue;
			close(gps_fd);
			gps_fd = -1;
			pfd.fd = -1;
			puts("GPS lost");
		}
	}
	
	return 0;
}
Esempio n. 7
0
/* ARGSUSED */
void
control_accept(int listenfd, short event, void *arg)
{
	struct control_sock	*cs = (struct control_sock *)arg;
	int			 connfd;
	socklen_t		 len;
	struct sockaddr_un	 sun;
	struct ctl_conn		*c;

	event_add(&cs->cs_ev, NULL);
	if ((event & EV_TIMEOUT))
		return;

	len = sizeof(sun);
	if ((connfd = accept(listenfd,
	    (struct sockaddr *)&sun, &len)) == -1) {
		/*
		 * Pause accept if we are out of file descriptors, or
		 * libevent will haunt us here too.
		 */
		if (errno == ENFILE || errno == EMFILE) {
			struct timeval evtpause = { 1, 0 };

			event_del(&cs->cs_ev);
			evtimer_add(&cs->cs_evt, &evtpause);
		} else if (errno != EWOULDBLOCK && errno != EINTR)
			log_warn("control_accept: accept");
		return;
	}

	fd_nonblock(connfd);

	if ((c = calloc(1, sizeof(struct ctl_conn))) == NULL) {
		log_warn("control_accept");
		close(connfd);
		return;
	}
	if ((c->ctx = npppd_ctl_create(cs->cs_ctx)) == NULL) {
		free(c);
		log_warn("control_accept");
		close(connfd);
		return;
	}

	imsg_init(&c->iev.ibuf, connfd);
	c->iev.handler = control_dispatch_imsg;
	c->iev.events = EV_READ;
	c->iev.data = cs;
	event_set(&c->iev.ev, c->iev.ibuf.fd, c->iev.events,
	    c->iev.handler, cs);
	event_add(&c->iev.ev, NULL);

	TAILQ_INSERT_TAIL(&ctl_conns, c, entry);
}
Esempio n. 8
0
int server_open_native_socket(Server*s) {

        static const union sockaddr_union sa = {
                .un.sun_family = AF_UNIX,
                .un.sun_path = "/run/systemd/journal/socket",
        };
        static const int one = 1;
        int r;

        assert(s);

        if (s->native_fd < 0) {
                s->native_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
                if (s->native_fd < 0)
                        return log_error_errno(errno, "socket() failed: %m");

                (void) unlink(sa.un.sun_path);

                r = bind(s->native_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un));
                if (r < 0)
                        return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path);

                (void) chmod(sa.un.sun_path, 0666);
        } else
                fd_nonblock(s->native_fd, 1);

        r = setsockopt(s->native_fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one));
        if (r < 0)
                return log_error_errno(errno, "SO_PASSCRED failed: %m");

#ifdef HAVE_SELINUX
        if (mac_selinux_use()) {
                r = setsockopt(s->native_fd, SOL_SOCKET, SO_PASSSEC, &one, sizeof(one));
                if (r < 0)
                        log_warning_errno(errno, "SO_PASSSEC failed: %m");
        }
#endif

        r = setsockopt(s->native_fd, SOL_SOCKET, SO_TIMESTAMP, &one, sizeof(one));
        if (r < 0)
                return log_error_errno(errno, "SO_TIMESTAMP failed: %m");

        r = sd_event_add_io(s->event, &s->native_event_source, s->native_fd, EPOLLIN, server_process_datagram, s);
        if (r < 0)
                return log_error_errno(r, "Failed to add native server fd to event loop: %m");

        r = sd_event_source_set_priority(s->native_event_source, SD_EVENT_PRIORITY_NORMAL+5);
        if (r < 0)
                return log_error_errno(r, "Failed to adjust native event source priority: %m");

        return 0;
}
Esempio n. 9
0
static void pty_forward_disconnect(PTYForward *f) {

    if (f) {
        f->stdin_event_source = sd_event_source_unref(f->stdin_event_source);
        f->stdout_event_source = sd_event_source_unref(f->stdout_event_source);

        f->master_event_source = sd_event_source_unref(f->master_event_source);
        f->sigwinch_event_source = sd_event_source_unref(f->sigwinch_event_source);
        f->event = sd_event_unref(f->event);

        if (f->saved_stdout)
            tcsetattr(STDOUT_FILENO, TCSANOW, &f->saved_stdout_attr);
        if (f->saved_stdin)
            tcsetattr(STDIN_FILENO, TCSANOW, &f->saved_stdin_attr);

        f->saved_stdout = f->saved_stdin = false;
    }

    /* STDIN/STDOUT should not be nonblocking normally, so let's unconditionally reset it */
    fd_nonblock(STDIN_FILENO, false);
    fd_nonblock(STDOUT_FILENO, false);
}
Esempio n. 10
0
PTYForward *pty_forward_free(PTYForward *f) {

        if (f) {
                sd_event_source_unref(f->stdin_event_source);
                sd_event_source_unref(f->stdout_event_source);
                sd_event_source_unref(f->master_event_source);
                sd_event_unref(f->event);

                if (f->saved_stdout)
                        tcsetattr(STDOUT_FILENO, TCSANOW, &f->saved_stdout_attr);
                if (f->saved_stdin)
                        tcsetattr(STDIN_FILENO, TCSANOW, &f->saved_stdin_attr);

                free(f);
        }

        /* STDIN/STDOUT should not be nonblocking normally, so let's
         * unconditionally reset it */
        fd_nonblock(STDIN_FILENO, false);
        fd_nonblock(STDOUT_FILENO, false);

        return NULL;
}
Esempio n. 11
0
int
udp_attach(PNATState pData, struct socket *so)
{
    struct sockaddr sa_addr;
    socklen_t socklen = sizeof(struct sockaddr);
    int status;
    int opt = 1;

    AssertReturn(so->so_type == 0, -1);
    so->so_type = IPPROTO_UDP;

    so->s = socket(AF_INET, SOCK_DGRAM, 0);
    if (so->s == -1)
        goto error;
    fd_nonblock(so->s);

    so->so_sottl = 0;
    so->so_sotos = 0;
    so->so_sodf = -1;

    status = sobind(pData, so);
    if (status != 0)
        return status;

    /* success, insert in queue */
    so->so_expire = curtime + SO_EXPIRE;

    /* enable broadcast for later use */
    setsockopt(so->s, SOL_SOCKET, SO_BROADCAST, (const char *)&opt, sizeof(opt));

    status = getsockname(so->s, &sa_addr, &socklen);
    if (status == 0)
    {
        Assert(sa_addr.sa_family == AF_INET);
        so->so_hlport = ((struct sockaddr_in *)&sa_addr)->sin_port;
        so->so_hladdr.s_addr = ((struct sockaddr_in *)&sa_addr)->sin_addr.s_addr;
    }

    SOCKET_LOCK_CREATE(so);
    QSOCKET_LOCK(udb);
    insque(pData, so, &udb);
    NSOCK_INC();
    QSOCKET_UNLOCK(udb);
    return so->s;
error:
    Log2(("NAT: can't create datagram socket\n"));
    return -1;
}
Esempio n. 12
0
void new_client(const int listen_fd, short event, void *ev)
{
    Client *client;
    struct sockaddr_storage client_sa;
    socklen_t client_sa_len = sizeof client_sa;
    int client_fd;

    (void) ev;
    if ((event & EV_READ) == 0) {
        logfile(LOG_DEBUG, _("Wrong event %d received on fd #%d"),
                (int) event, listen_fd);
        return;
    }
    memset(&client_sa, 0, sizeof client_sa);
    if ((client_fd = accept(listen_fd, (struct sockaddr *) &client_sa,
                            &client_sa_len)) < 0) {
        logfile(LOG_DEBUG, _("accept(): [%s]"), strerror(errno));
        return;
    }
    if (client_sa_len <= (socklen_t) 0U) {
        (void) close(client_fd);
        return;
    }
    fd_nonblock(client_fd);
    if ((client = malloc(sizeof *client)) == NULL) {
        (void) close(client_fd);
        logfile(LOG_ERR, _("Out of memory to accept a new client"));
        return;
    }
    client->client_fd = client_fd;
    client->read_buf = NULL;
    client->sizeof_read_buf = (size_t) 0U;
    client->offset_read_buf = (size_t) 0U;
    client->client_command = CC_UNDEF;
    client->key_len = (size_t) 0U;
    client->data_len = (size_t) 0U;
    client->total_len = (size_t) 0U;
    client->write_fd = -1;
    client->read_fd = -1;
    client->read_mapped_zone = NULL;
    client->read_mapped_zone_length = (size_t) 0U;
    client->returncode_bufev = NULL;
    event_set(&client->ev_client_read, client_fd, EV_READ,
              client_read, client);
    event_add(&client->ev_client_read, &timeout);
    logfile(LOG_DEBUG, _("New client on fd #%d"), client_fd);
}
Esempio n. 13
0
static int add_listen_socket(Context *context, int fd) {
        sd_event_source *source;
        int r;

        assert(context);
        assert(fd >= 0);

        r = set_ensure_allocated(&context->listen, NULL);
        if (r < 0) {
                log_oom();
                return r;
        }

        r = sd_is_socket(fd, 0, SOCK_STREAM, 1);
        if (r < 0)
                return log_error_errno(r, "Failed to determine socket type: %m");
        if (r == 0) {
                log_error("Passed in socket is not a stream socket.");
                return -EINVAL;
        }

        r = fd_nonblock(fd, true);
        if (r < 0)
                return log_error_errno(r, "Failed to mark file descriptor non-blocking: %m");

        r = sd_event_add_io(context->event, &source, fd, EPOLLIN, accept_cb, context);
        if (r < 0)
                return log_error_errno(r, "Failed to add event source: %m");

        r = set_put(context->listen, source);
        if (r < 0) {
                log_error_errno(r, "Failed to add source to set: %m");
                sd_event_source_unref(source);
                return r;
        }

        /* Set the watcher to oneshot in case other processes are also
         * watching to accept(). */
        r = sd_event_source_set_enabled(source, SD_EVENT_ONESHOT);
        if (r < 0)
                return log_error_errno(r, "Failed to enable oneshot mode: %m");

        return 0;
}
Esempio n. 14
0
int raw_import_start(RawImport *i, int fd, const char *local, bool force_local, bool read_only) {
        int r;

        assert(i);
        assert(fd >= 0);
        assert(local);

        if (!machine_name_is_valid(local))
                return -EINVAL;

        if (i->input_fd >= 0)
                return -EBUSY;

        r = fd_nonblock(fd, true);
        if (r < 0)
                return r;

        r = free_and_strdup(&i->local, local);
        if (r < 0)
                return r;
        i->force_local = force_local;
        i->read_only = read_only;

        if (fstat(fd, &i->st) < 0)
                return -errno;

        r = sd_event_add_io(i->event, &i->input_event_source, fd, EPOLLIN, raw_import_on_input, i);
        if (r == -EPERM) {
                /* This fd does not support epoll, for example because it is a regular file. Busy read in that case */
                r = sd_event_add_defer(i->event, &i->input_event_source, raw_import_on_defer, i);
                if (r < 0)
                        return r;

                r = sd_event_source_set_enabled(i->input_event_source, SD_EVENT_ON);
        }
        if (r < 0)
                return r;

        i->input_fd = fd;
        return r;
}
Esempio n. 15
0
static
void
setup(void)
{
  int  i = 0;

  if(pipe(my_sigpipe) == -1){
      fatal_syserr("failure setting up selfpipe");
  }

  for(i = 0; i < 2; ++i){
      fd_cloexec(my_sigpipe[i]);
      fd_nonblock(my_sigpipe[i]);
  }

  if(pipe(my_logpipe) == -1){
      fatal_syserr("failure creating logpipe");
  }

  sigset_fill(&my_sigset);
  sigset_block(&my_sigset);

  sig_catch(SIGTERM, &sigtrap);
  sig_catch(SIGINT, &sigtrap);
  sig_catch(SIGCHLD, &sigtrap);

  /* catching these signals to pass to program: */
  sig_catch(SIGALRM, &sigtrap);
  sig_catch(SIGCONT, &sigtrap);
  sig_catch(SIGHUP, &sigtrap);
  sig_catch(SIGQUIT, &sigtrap);
  sig_catch(SIGTSTP, &sigtrap);
  sig_catch(SIGUSR1, &sigtrap);
  sig_catch(SIGUSR2, &sigtrap);

  sig_ignore(SIGPIPE);
  return;
}    
Esempio n. 16
0
int pty_forward_new(
    sd_event *event,
    int master,
    PTYForwardFlags flags,
    PTYForward **ret) {

    _cleanup_(pty_forward_freep) PTYForward *f = NULL;
    struct winsize ws;
    int r;

    f = new0(PTYForward, 1);
    if (!f)
        return -ENOMEM;

    f->flags = flags;

    if (event)
        f->event = sd_event_ref(event);
    else {
        r = sd_event_default(&f->event);
        if (r < 0)
            return r;
    }

    if (!(flags & PTY_FORWARD_READ_ONLY)) {
        r = fd_nonblock(STDIN_FILENO, true);
        if (r < 0)
            return r;

        r = fd_nonblock(STDOUT_FILENO, true);
        if (r < 0)
            return r;
    }

    r = fd_nonblock(master, true);
    if (r < 0)
        return r;

    f->master = master;

    if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) >= 0)
        (void) ioctl(master, TIOCSWINSZ, &ws);

    if (!(flags & PTY_FORWARD_READ_ONLY)) {
        if (tcgetattr(STDIN_FILENO, &f->saved_stdin_attr) >= 0) {
            struct termios raw_stdin_attr;

            f->saved_stdin = true;

            raw_stdin_attr = f->saved_stdin_attr;
            cfmakeraw(&raw_stdin_attr);
            raw_stdin_attr.c_oflag = f->saved_stdin_attr.c_oflag;
            tcsetattr(STDIN_FILENO, TCSANOW, &raw_stdin_attr);
        }

        if (tcgetattr(STDOUT_FILENO, &f->saved_stdout_attr) >= 0) {
            struct termios raw_stdout_attr;

            f->saved_stdout = true;

            raw_stdout_attr = f->saved_stdout_attr;
            cfmakeraw(&raw_stdout_attr);
            raw_stdout_attr.c_iflag = f->saved_stdout_attr.c_iflag;
            raw_stdout_attr.c_lflag = f->saved_stdout_attr.c_lflag;
            tcsetattr(STDOUT_FILENO, TCSANOW, &raw_stdout_attr);
        }

        r = sd_event_add_io(f->event, &f->stdin_event_source, STDIN_FILENO, EPOLLIN|EPOLLET, on_stdin_event, f);
        if (r < 0 && r != -EPERM)
            return r;
    }

    r = sd_event_add_io(f->event, &f->stdout_event_source, STDOUT_FILENO, EPOLLOUT|EPOLLET, on_stdout_event, f);
    if (r == -EPERM)
        /* stdout without epoll support. Likely redirected to regular file. */
        f->stdout_writable = true;
    else if (r < 0)
        return r;

    r = sd_event_add_io(f->event, &f->master_event_source, master, EPOLLIN|EPOLLOUT|EPOLLET, on_master_event, f);
    if (r < 0)
        return r;

    r = sd_event_add_signal(f->event, &f->sigwinch_event_source, SIGWINCH, on_sigwinch_event, f);
    if (r < 0)
        return r;

    *ret = f;
    f = NULL;

    return 0;
}
Esempio n. 17
0
int 
bmp_server_init(int port, int interactive)
{
    int rc = 0, timer;
    struct epoll_event ev;
    struct sockaddr_in saddr;

    signal(SIGPIPE, SIG_IGN);
    signal(SIGINT,  bmp_server_exit);
    signal(SIGTERM, bmp_server_exit);
 

    memset(&server, 0, sizeof(bmp_server));
 
    server.pid = getpid();
    server.port = port;

    memset(&saddr, 0, sizeof(saddr)); 
    saddr.sin_family = AF_INET;
    saddr.sin_addr.s_addr = INADDR_ANY;
    saddr.sin_port = htons(server.port);

    server.listen = socket(AF_INET, SOCK_STREAM, 0);
    
    if (server.listen < 0) {
        bmp_log("socket() failed: %s", strerror(errno));
        exit(1);
    }

    rc = so_reuseaddr(server.listen);

    if (rc < 0) {
        return rc;
    }

    rc = bind(server.listen, (struct sockaddr *) &saddr, sizeof(saddr));

    if (rc < 0) {
        bmp_log("bind() failed: %s", strerror(errno));
        return rc;
    }
 
    rc = listen(server.listen, BMP_SESSION_MAX);

    if (rc < 0) {
        bmp_log("listen() failed: %s", strerror(errno));
        return rc;
    }
    
    rc = fd_nonblock(server.listen);

    if (rc < 0) {
        return rc;
    }
 
    /*
     * Create the epoll instance and register the listen socket with the server 
     * epoll queue 
     */
    server.eq = epoll_create(BMP_SESSION_MAX);

    if (server.eq < 0) {
        bmp_log("epoll_create1() failed: %s", strerror(errno));
        return -1;
    }

    MONITOR_FD(server.eq, server.listen, rc);

    if (rc < 0) {
        bmp_log("epoll_ctl(server->fd) failed: %s", strerror(errno));
        return rc;
    }

    /*
     * Create a timer fd and register the read-end of the timer pipe with the 
     * server's epoll queue
     */
    timer = bmp_timer_init();

    if (timer < 0) {
        bmp_log("Timer init failed");
        return -1;
    }

    server.timer = timer;

    MONITOR_FD(server.eq, timer, rc);

    if (rc < 0) {
        bmp_log("server timer listen error: %s", timer, strerror(errno));
        return rc;
    }

    /*
     * Allocate the clients event queue
     */
    server.ev = calloc(BMP_SESSION_MAX, sizeof(ev));

    if (server.ev == NULL) {
        bmp_log("calloc(server->ev) failed");
        return -1;
    }

    /* 
     * Initialize the session AVL tree
     */
    server.sessions = avl_init(bmp_session_compare, NULL, AVL_TREE_INTRUSIVE);

    /* 
     * Start the command processing task
     */
    rc = bmp_command_init(interactive);
    
    if (rc < 0) {
        return -1;
    }

    /*
     * Initialize the main BMP "processing" task
     */
    rc = bmp_process_init();

    if (rc < 0) {
        return -1;
    }

    /*
     * Initialize the realtime "online" BMP context
     */
    rc = bmp_context_init(0);

    if (rc < 0) {
        return -1;
    }
 
    return rc;
}
Esempio n. 18
0
struct ttys *tty_attach(int unit, char *device)
{
	char buff[256], *bptr;
	struct ttys *ttyp, *ttyp_tmp, *ttyp_last = 0;
	struct stat stat;
	
	DEBUG_CALL("tty_attach");
	DEBUG_ARG("unit = %d", unit);
	DEBUG_ARG("device = %lx", (long)device);
	
	if ((ttyp = (struct ttys *)malloc(sizeof(struct ttys))) == NULL)
	    return 0;
	memset(ttyp, 0, sizeof(struct ttys));
	ttyp->next = 0;
	ttyp->fd = 0; /* Default changed from -1 -RedWolf */
	
	/* Only open the device if there is one */
	if (device) {
		if ((ttyp->fd = open(device, O_RDWR)) < 0) {
			free(ttyp);
			return 0; /* XXXXX */
		}
        lprint ("Opening device %s...\r\n\r\n", device);
	}
	
	/* Link it to the *tail* of the list XXXXX */
	if (!ttys) {
		ttys = ttyp;
	} else {
		for (ttyp_tmp = ttys; ttyp_tmp; ttyp_tmp = ttyp_tmp->next)
		   ttyp_last = ttyp_tmp;
		/* XXX More checks? */
		ttyp_last->next = ttyp;
	}
	
#ifdef FULL_BOLT
	fd_nonblock(ttyp->fd);
#endif
	
	if (ttyp->fd >= 0 && isatty(ttyp->fd) && fstat(ttyp->fd, &stat) == 0) {
		/* Save the current permissions */
		ttyp->mode = stat.st_mode;
#ifdef HAVE_FCHMOD
		fchmod(ttyp->fd, S_IRUSR|S_IWUSR);
#else
		chmod(ttyname(ttyp->fd), S_IRUSR|S_IWUSR);
#endif
	}
	
	ttyp->unit = unit;
#ifndef FULL_BOLT
	ttyp->towrite = towrite_max;
#endif
#ifndef FULL_BOLT
	ttyp->baud = DEFAULT_BAUD;
	ttyp->bytesps = ttyp->baud/10;
#endif
	ttyp->lastime = curtime;
	ttyp->sc_xc_state = 0;
	ttyp->sc_rc_state = 0;
	
	/* Default is SLIP */
	ttyp->proto = PROTO_SLIP;
	ttyp->up = 1; /* SLIP is always up */
	ttyp->if_input = sl_input;
	ttyp->if_encap = sl_encap;
	ttys_unit[unit] = ttyp;
	
	/* Rawify the terminal, if applicable */
	if (ttyp->fd >= 0)
	   term_raw(ttyp);
	
	/* Config the new tty */
	if ((bptr = (char *)getenv("HOME")))
	   sprintf(buff, "%s/.slirprc-%d", bptr, unit);
	else
	   sprintf(buff, ".slirprc-%d", unit);
	config(buff, ttyp->unit);
	
	return ttyp;
}
Esempio n. 19
0
void server_process_native_file(
                Server *s,
                int fd,
                const struct ucred *ucred,
                const struct timeval *tv,
                const char *label, size_t label_len) {

        struct stat st;
        bool sealed;
        int r;

        /* Data is in the passed fd, since it didn't fit in a
         * datagram. */

        assert(s);
        assert(fd >= 0);

        /* If it's a memfd, check if it is sealed. If so, we can just
         * use map it and use it, and do not need to copy the data
         * out. */
        sealed = memfd_get_sealed(fd) > 0;

        if (!sealed && (!ucred || ucred->uid != 0)) {
                _cleanup_free_ char *sl = NULL, *k = NULL;
                const char *e;

                /* If this is not a sealed memfd, and the peer is unknown or
                 * unprivileged, then verify the path. */

                if (asprintf(&sl, "/proc/self/fd/%i", fd) < 0) {
                        log_oom();
                        return;
                }

                r = readlink_malloc(sl, &k);
                if (r < 0) {
                        log_error_errno(r, "readlink(%s) failed: %m", sl);
                        return;
                }

                e = path_startswith(k, "/dev/shm/");
                if (!e)
                        e = path_startswith(k, "/tmp/");
                if (!e)
                        e = path_startswith(k, "/var/tmp/");
                if (!e) {
                        log_error("Received file outside of allowed directories. Refusing.");
                        return;
                }

                if (!filename_is_valid(e)) {
                        log_error("Received file in subdirectory of allowed directories. Refusing.");
                        return;
                }
        }

        if (fstat(fd, &st) < 0) {
                log_error_errno(errno, "Failed to stat passed file, ignoring: %m");
                return;
        }

        if (!S_ISREG(st.st_mode)) {
                log_error("File passed is not regular. Ignoring.");
                return;
        }

        if (st.st_size <= 0)
                return;

        if (st.st_size > ENTRY_SIZE_MAX) {
                log_error("File passed too large. Ignoring.");
                return;
        }

        if (sealed) {
                void *p;
                size_t ps;

                /* The file is sealed, we can just map it and use it. */

                ps = PAGE_ALIGN(st.st_size);
                p = mmap(NULL, ps, PROT_READ, MAP_PRIVATE, fd, 0);
                if (p == MAP_FAILED) {
                        log_error_errno(errno, "Failed to map memfd, ignoring: %m");
                        return;
                }

                server_process_native_message(s, p, st.st_size, ucred, tv, label, label_len);
                assert_se(munmap(p, ps) >= 0);
        } else {
                _cleanup_free_ void *p = NULL;
                struct statvfs vfs;
                ssize_t n;

                if (fstatvfs(fd, &vfs) < 0) {
                        log_error_errno(errno, "Failed to stat file system of passed file, ignoring: %m");
                        return;
                }

                /* Refuse operating on file systems that have
                 * mandatory locking enabled, see:
                 *
                 * https://github.com/systemd/systemd/issues/1822
                 */
                if (vfs.f_flag & ST_MANDLOCK) {
                        log_error("Received file descriptor from file system with mandatory locking enable, refusing.");
                        return;
                }

                /* Make the fd non-blocking. On regular files this has
                 * the effect of bypassing mandatory locking. Of
                 * course, this should normally not be necessary given
                 * the check above, but let's better be safe than
                 * sorry, after all NFS is pretty confusing regarding
                 * file system flags, and we better don't trust it,
                 * and so is SMB. */
                r = fd_nonblock(fd, true);
                if (r < 0) {
                        log_error_errno(r, "Failed to make fd non-blocking, ignoring: %m");
                        return;
                }

                /* The file is not sealed, we can't map the file here, since
                 * clients might then truncate it and trigger a SIGBUS for
                 * us. So let's stupidly read it */

                p = malloc(st.st_size);
                if (!p) {
                        log_oom();
                        return;
                }

                n = pread(fd, p, st.st_size, 0);
                if (n < 0)
                        log_error_errno(errno, "Failed to read file, ignoring: %m");
                else if (n > 0)
                        server_process_native_message(s, p, n, ucred, tv, label, label_len);
        }
}
Esempio n. 20
0
int server_open_stdout_socket(Server *s) {
        static const union sockaddr_union sa = {
                .un.sun_family = AF_UNIX,
                .un.sun_path = "/run/systemd/journal/stdout",
        };
        int r;

        assert(s);

        if (s->stdout_fd < 0) {
                s->stdout_fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
                if (s->stdout_fd < 0)
                        return log_error_errno(errno, "socket() failed: %m");

                (void) unlink(sa.un.sun_path);

                r = bind(s->stdout_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un));
                if (r < 0)
                        return log_error_errno(errno, "bind(%s) failed: %m", sa.un.sun_path);

                (void) chmod(sa.un.sun_path, 0666);

                if (listen(s->stdout_fd, SOMAXCONN) < 0)
                        return log_error_errno(errno, "listen(%s) failed: %m", sa.un.sun_path);
        } else
                fd_nonblock(s->stdout_fd, 1);

        r = sd_event_add_io(s->event, &s->stdout_event_source, s->stdout_fd, EPOLLIN, stdout_stream_new, s);
        if (r < 0)
                return log_error_errno(r, "Failed to add stdout server fd to event source: %m");

        r = sd_event_source_set_priority(s->stdout_event_source, SD_EVENT_PRIORITY_NORMAL+5);
        if (r < 0)
                return log_error_errno(r, "Failed to adjust priority of stdout server event source: %m");

        return 0;
}

void stdout_stream_send_notify(StdoutStream *s) {
        struct iovec iovec = {
                .iov_base = (char*) "FDSTORE=1",
                .iov_len = strlen("FDSTORE=1"),
        };
        struct msghdr msghdr = {
                .msg_iov = &iovec,
                .msg_iovlen = 1,
        };
        struct cmsghdr *cmsg;
        ssize_t l;

        assert(s);
        assert(!s->fdstore);
        assert(s->in_notify_queue);
        assert(s->server);
        assert(s->server->notify_fd >= 0);

        /* Store the connection fd in PID 1, so that we get it passed
         * in again on next start */

        msghdr.msg_controllen = CMSG_SPACE(sizeof(int));
        msghdr.msg_control = alloca0(msghdr.msg_controllen);

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

        memcpy(CMSG_DATA(cmsg), &s->fd, sizeof(int));

        l = sendmsg(s->server->notify_fd, &msghdr, MSG_DONTWAIT|MSG_NOSIGNAL);
        if (l < 0) {
                if (errno == EAGAIN)
                        return;

                log_error_errno(errno, "Failed to send stream file descriptor to service manager: %m");
        } else {
                log_debug("Successfully sent stream file descriptor to service manager.");
                s->fdstore = 1;
        }

        LIST_REMOVE(stdout_stream_notify_queue, s->server->stdout_streams_notify_queue, s);
        s->in_notify_queue = false;

}
Esempio n. 21
0
struct socket *
udp_listen(PNATState pData, u_int32_t bind_addr, u_int port, u_int32_t laddr, u_int lport, int flags)
{
    struct sockaddr_in addr;
    struct socket *so;
    socklen_t addrlen = sizeof(struct sockaddr_in);
    int opt = 1;
    LogFlowFunc(("ENTER: bind_addr:%RTnaipv4, port:%d, laddr:%RTnaipv4, lport:%d, flags:%x\n",
                 bind_addr, RT_N2H_U16(port), laddr, RT_N2H_U16(lport), flags));

    if ((so = socreate()) == NULL)
    {
        LogFlowFunc(("LEAVE: NULL\n"));
        return NULL;
    }

    so->s = socket(AF_INET, SOCK_DGRAM, 0);
    if (so->s == -1)
    {
        LogRel(("NAT: can't create datagram socket\n"));
        RTMemFree(so);
        LogFlowFunc(("LEAVE: NULL\n"));
        return NULL;
    }
    so->so_expire = curtime + SO_EXPIRE;
    so->so_type = IPPROTO_UDP;
    fd_nonblock(so->s);
    so->so_sottl = 0;
    so->so_sotos = 0;
    so->so_sodf = -1;
    SOCKET_LOCK_CREATE(so);
    QSOCKET_LOCK(udb);
    insque(pData, so, &udb);
    NSOCK_INC();
    QSOCKET_UNLOCK(udb);

    memset(&addr, 0, sizeof(addr));
#ifdef RT_OS_DARWIN
    addr.sin_len = sizeof(addr);
#endif
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = bind_addr;
    addr.sin_port = port;

    if (bind(so->s,(struct sockaddr *)&addr, addrlen) < 0)
    {
        LogRel(("NAT: udp bind to %RTnaipv4:%d failed, error %d\n",
                addr.sin_addr, RT_N2H_U16(port), errno));
        udp_detach(pData, so);
        LogFlowFunc(("LEAVE: NULL\n"));
        return NULL;
    }
    setsockopt(so->s, SOL_SOCKET, SO_REUSEADDR,(char *)&opt, sizeof(int));
/*  setsockopt(so->s, SOL_SOCKET, SO_OOBINLINE,(char *)&opt, sizeof(int)); */

    getsockname(so->s,(struct sockaddr *)&addr,&addrlen);
    so->so_hladdr = addr.sin_addr;
    so->so_hlport = addr.sin_port;

    /* XXX: wtf are we setting so_faddr/so_fport here? */
    so->so_fport = addr.sin_port;
#if 0
    /* The original check was completely broken, as the commented out
     * if statement was always true (INADDR_ANY=0). */
    /** @todo vvl - alias_addr should be set (if required)
     * later by liabalias module.
     */
    if (addr.sin_addr.s_addr == 0 || addr.sin_addr.s_addr == loopback_addr.s_addr)
        so->so_faddr = alias_addr;
    else
#endif
        so->so_faddr = addr.sin_addr;

    so->so_lport = lport;
    so->so_laddr.s_addr = laddr;
    if (flags != SS_FACCEPTONCE)
        so->so_expire = 0;

    so->so_state = SS_ISFCONNECTED;

    LogFlowFunc(("LEAVE: %R[natsock]\n", so));
    return so;
}
Esempio n. 22
0
/*
 * XXX This is ugly
 * We create and bind a socket, then fork off to another
 * process, which connects to this socket, after which we
 * exec the wanted program.  If something (strange) happens,
 * the accept() call could block us forever.
 *
 * do_pty = 0   Fork/exec inetd style
 * do_pty = 1   Fork/exec using slirp.telnetd
 * do_ptr = 2   Fork/exec using pty
 */
int fork_exec(struct socket *so, const char *ex, int do_pty)
{
	int s;
	struct sockaddr_in addr;
	socklen_t addrlen = sizeof(addr);
	int opt;
        int master = -1;
	const char *argv[256];
	/* don't want to clobber the original */
	char *bptr;
	const char *curarg;
	int c, i, ret;
	pid_t pid;

	DEBUG_CALL("fork_exec so = %lx ex = %lx do_pty = %lx", (long)so,  (long)ex,  (long)do_pty);

	if (do_pty == 2) {
                return 0;
	} else {
		addr.sin_family = AF_INET;
		addr.sin_port = 0;
		addr.sin_addr.s_addr = INADDR_ANY;

		if ((s = clo_socket(AF_INET, SOCK_STREAM, 0)) < 0 ||
		    bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
		    listen(s, 1) < 0) {
			vmiPrintf("Error: inet socket: %s\n", strerror(errno));
			closesocket(s);

			return 0;
		}
	}

	pid = fork();
	switch(pid) {
	 case -1:
		vmiPrintf("Error: fork failed: %s\n", strerror(errno));
		close(s);
		if (do_pty == 2)
		   close(master);
		return 0;

	 case 0:
                setsid();

		/* Set the DISPLAY */
		if (do_pty == 2) {
			(void) close(master);
#ifdef TIOCSCTTY /* XXXXX */
			ioctl(s, TIOCSCTTY, (char *)NULL);
#endif
		} else {
			getsockname(s, (struct sockaddr *)&addr, &addrlen);
			close(s);
			/*
			 * Connect to the socket
			 * XXX If any of these fail, we're in trouble!
	 		 */
			s = clo_socket(AF_INET, SOCK_STREAM, 0);
			addr.sin_addr = loopback_addr;
                        do {
                            ret = connect(s, (struct sockaddr *)&addr, addrlen);
                        } while (ret < 0 && errno == EINTR);
		}

		dup2(s, 0);
		dup2(s, 1);
		dup2(s, 2);
		for (s = getdtablesize() - 1; s >= 3; s--)
		   close(s);

		i = 0;
		bptr = strdup(ex);
		if (do_pty == 1) {
			/* Setup "slirp.telnetd -x" */
			argv[i++] = "slirp.telnetd";
			argv[i++] = "-x";
			argv[i++] = bptr;
		} else
		   do {
			/* Change the string into argv[] */
			curarg = bptr;
			while (*bptr != ' ' && *bptr != (char)0)
			   bptr++;
			c = *bptr;
			*bptr++ = (char)0;
			argv[i++] = strdup(curarg);
		   } while (c);

                argv[i] = NULL;
		execvp(argv[0], (char **)argv);

		/* Ooops, failed, let's tell the user why */
        fprintf(stderr, "Error: execvp of %s failed: %s\n",
                argv[0], strerror(errno));
		close(0); close(1); close(2); /* XXX */
		exit(1);

	 default:
		// MWH qemu_add_child_watch(pid);
		if (do_pty == 2) {
			close(s);
			so->s = master;
		} else {
			/*
			 * XXX this could block us...
			 * XXX Should set a timer here, and if accept() doesn't
		 	 * return after X seconds, declare it a failure
		 	 * The only reason this will block forever is if socket()
		 	 * of connect() fail in the child process
		 	 */
                        do {
                            so->s = accept(s, (struct sockaddr *)&addr, &addrlen);
                        } while (so->s < 0 && errno == EINTR);
                        closesocket(s);
			opt = 1;
			setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
			opt = 1;
			setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
		}
		fd_nonblock(so->s);

		/* Append the telnet options now */
                if (so->so_m != NULL && do_pty == 1)  {
			sbappend(so, so->so_m);
                        so->so_m = NULL;
		}

		return 1;
	}
}
Esempio n. 23
0
/*
 * XXX This is ugly
 * We create and bind a socket, then fork off to another
 * process, which connects to this socket, after which we
 * exec the wanted program.  If something (strange) happens,
 * the accept() call could block us forever.
 *
 * do_pty = 0   Fork/exec inetd style
 * do_pty = 1   Fork/exec using slirp.telnetd
 * do_ptr = 2   Fork/exec using pty
 */
int fork_exec(struct socket *so, char *ex, int do_pty)
{
	int s;
	struct sockaddr_in addr;
	socklen_t addrlen = sizeof(addr);
	int opt;
        int master;
	char *argv[256];
#if 0
	char buff[256];
#endif
	/* don't want to clobber the original */
	char *bptr;
	char *curarg;
	int c, i, ret;

	DEBUG_CALL("fork_exec");
	DEBUG_ARG("so = %lx", (long)so);
	DEBUG_ARG("ex = %lx", (long)ex);
	DEBUG_ARG("do_pty = %lx", (long)do_pty);

	if (do_pty == 2) {
		if (slirp_openpty(&master, &s) == -1) {
			lprint("Error: openpty failed: %s\n", strerror(errno));
			return 0;
		}
	} else {
		memset(&addr, 0, sizeof(struct sockaddr_in));
		addr.sin_family = AF_INET;
		addr.sin_port = 0;
		addr.sin_addr.s_addr = INADDR_ANY;

		if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0 ||
		    bind(s, (struct sockaddr *)&addr, addrlen) < 0 ||
		    listen(s, 1) < 0) {
			lprint("Error: inet socket: %s\n", strerror(errno));
			closesocket(s);

			return 0;
		}
	}

	switch(fork()) {
	 case -1:
		lprint("Error: fork failed: %s\n", strerror(errno));
		close(s);
		if (do_pty == 2)
		   close(master);
		return 0;

	 case 0:
		/* Set the DISPLAY */
		if (do_pty == 2) {
			(void) close(master);
#ifdef TIOCSCTTY /* XXXXX */
			(void) setsid();
			ioctl(s, TIOCSCTTY, (char *)NULL);
#endif
		} else {
			getsockname(s, (struct sockaddr *)&addr, &addrlen);
			close(s);
			/*
			 * Connect to the socket
			 * XXX If any of these fail, we're in trouble!
	 		 */
			s = socket(AF_INET, SOCK_STREAM, 0);
			addr.sin_addr = loopback_addr;
                        do {
                            ret = connect(s, (struct sockaddr *)&addr, addrlen);
                        } while (ret < 0 && errno == EINTR);
		}

#if 0
		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
		}
#endif
		dup2(s, 0);
		dup2(s, 1);
		dup2(s, 2);
		for (s = 3; s <= 255; s++)
		   close(s);

		i = 0;
		bptr = strdup(ex); /* No need to free() this */
		if (do_pty == 1) {
			/* Setup "slirp.telnetd -x" */
			argv[i++] = "slirp.telnetd";
			argv[i++] = "-x";
			argv[i++] = bptr;
		} else
		   do {
			/* Change the string into argv[] */
			curarg = bptr;
			while (*bptr != ' ' && *bptr != (char)0)
			   bptr++;
			c = *bptr;
			*bptr++ = (char)0;
			argv[i++] = strdup(curarg);
		   } while (c);

		argv[i] = 0;
		execvp(argv[0], argv);

		/* Ooops, failed, let's tell the user why */
		  {
			  char buff[256];

			  sprintf(buff, "Error: execvp of %s failed: %s\n",
				  argv[0], strerror(errno));
			  write(2, buff, strlen(buff)+1);
		  }
		close(0); close(1); close(2); /* XXX */
		exit(1);

	 default:
		if (do_pty == 2) {
			close(s);
			so->s = master;
		} else {
			/*
			 * XXX this could block us...
			 * XXX Should set a timer here, and if accept() doesn't
		 	 * return after X seconds, declare it a failure
		 	 * The only reason this will block forever is if socket()
		 	 * of connect() fail in the child process
		 	 */
                        do {
                            so->s = accept(s, (struct sockaddr *)&addr, &addrlen);
                        } while (so->s < 0 && errno == EINTR);
                        closesocket(s);
			opt = 1;
			setsockopt(so->s,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof(int));
			opt = 1;
			setsockopt(so->s,SOL_SOCKET,SO_OOBINLINE,(char *)&opt,sizeof(int));
		}
		fd_nonblock(so->s);

		/* Append the telnet options now */
		if (so->so_m != 0 && do_pty == 1)  {
			sbappend(so, so->so_m);
			so->so_m = 0;
		}

		return 1;
	}
}
Esempio n. 24
0
int tar_export_start(TarExport *e, const char *path, int fd, ImportCompressType compress) {
    _cleanup_close_ int sfd = -1;
    int r;

    assert(e);
    assert(path);
    assert(fd >= 0);
    assert(compress < _IMPORT_COMPRESS_TYPE_MAX);
    assert(compress != IMPORT_COMPRESS_UNKNOWN);

    if (e->output_fd >= 0)
        return -EBUSY;

    sfd = open(path, O_DIRECTORY|O_RDONLY|O_NOCTTY|O_CLOEXEC);
    if (sfd < 0)
        return -errno;

    if (fstat(sfd, &e->st) < 0)
        return -errno;

    r = fd_nonblock(fd, true);
    if (r < 0)
        return r;

    r = free_and_strdup(&e->path, path);
    if (r < 0)
        return r;

    e->quota_referenced = (uint64_t) -1;

    if (e->st.st_ino == 256) { /* might be a btrfs subvolume? */
        BtrfsQuotaInfo q;

        r = btrfs_subvol_get_subtree_quota_fd(sfd, 0, &q);
        if (r >= 0)
            e->quota_referenced = q.referenced;

        e->temp_path = mfree(e->temp_path);

        r = tempfn_random(path, NULL, &e->temp_path);
        if (r < 0)
            return r;

        /* Let's try to make a snapshot, if we can, so that the export is atomic */
        r = btrfs_subvol_snapshot_fd(sfd, e->temp_path, BTRFS_SNAPSHOT_READ_ONLY|BTRFS_SNAPSHOT_RECURSIVE);
        if (r < 0) {
            log_debug_errno(r, "Couldn't create snapshot %s of %s, not exporting atomically: %m", e->temp_path, path);
            e->temp_path = mfree(e->temp_path);
        }
    }

    r = import_compress_init(&e->compress, compress);
    if (r < 0)
        return r;

    r = sd_event_add_io(e->event, &e->output_event_source, fd, EPOLLOUT, tar_export_on_output, e);
    if (r == -EPERM) {
        r = sd_event_add_defer(e->event, &e->output_event_source, tar_export_on_defer, e);
        if (r < 0)
            return r;

        r = sd_event_source_set_enabled(e->output_event_source, SD_EVENT_ON);
    }
    if (r < 0)
        return r;

    e->tar_fd = import_fork_tar_c(e->temp_path ?: e->path, &e->tar_pid);
    if (e->tar_fd < 0) {
        e->output_event_source = sd_event_source_unref(e->output_event_source);
        return e->tar_fd;
    }

    e->output_fd = fd;
    return r;
}