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); }
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; }
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); } }
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; }
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; }
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; }
/* 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); }
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; }
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); }
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; }
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; }
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); }
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; }
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; }
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; }
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; }
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; }
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; }
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); } }
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; }
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; }
/* * 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; } }
/* * 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; } }
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; }