int main(int argc, char *argv[]) { int numthreads; if (!new_listener(argv[1], echo_start, NULL)) fatal("failed to create new listener!\n"); numthreads = argc > 3 ? atoi(argv[2]) : 0; if (numthreads > 0) { int i; pthread_t thrds[numthreads]; for (i = 0; i < numthreads; ++i) if (pthread_create(&thrds[i], NULL, start_thread, conn_loop) != 0) return 1; struct pollfd pfd; pfd.fd = STDIN_FILENO; pfd.events = POLLIN; if (poll(&pfd, 1, -1) && pfd.revents & POLLIN) { printf("Key pressed, terminating...\n"); pthread_exit(NULL); } } else conn_loop(); return 0; }
/* Add a new forwarding from port -> desthost:destport sets up a listener on the local machine on port */ char *pfd_addforward(char *desthost, int destport, int port) { static struct plug_function_table fn_table = { pfd_closing, pfd_receive, /* should not happen... */ pfd_sent, /* also should not happen */ pfd_accepting }; char *err; struct PFwdPrivate *pr; Socket s; /* * Open socket. */ pr = (struct PFwdPrivate *) smalloc(sizeof(struct PFwdPrivate)); pr->fn = &fn_table; pr->c = NULL; strcpy(pr->hostname, desthost); pr->port = destport; pr->throttled = pr->throttle_override = 0; pr->ready = 0; pr->waiting = NULL; pr->s = s = new_listener(port, (Plug) pr, !cfg.lport_acceptall); if ((err = sk_socket_error(s))) { sfree(pr); return err; } sk_set_private_ptr(s, pr); return NULL; }
/* returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ int x11req(struct ChanSess * chansess) { int fd; if (!svr_pubkey_allows_x11fwd()) { return DROPBEAR_FAILURE; } /* we already have an x11 connection */ if (chansess->x11listener != NULL) { return DROPBEAR_FAILURE; } chansess->x11singleconn = buf_getbool(ses.payload); chansess->x11authprot = buf_getstring(ses.payload, NULL); chansess->x11authcookie = buf_getstring(ses.payload, NULL); chansess->x11screennum = buf_getint(ses.payload); /* create listening socket */ fd = socket(PF_INET, SOCK_STREAM, 0); if (fd < 0) { goto fail; } /* allocate port and bind */ chansess->x11port = bindport(fd); if (chansess->x11port < 0) { goto fail; } /* listen */ if (listen(fd, 20) < 0) { goto fail; } /* set non-blocking */ setnonblocking(fd); /* listener code will handle the socket now. * No cleanup handler needed, since listener_remove only happens * from our cleanup anyway */ chansess->x11listener = new_listener( &fd, 1, 0, chansess, x11accept, NULL); if (chansess->x11listener == NULL) { goto fail; } return DROPBEAR_SUCCESS; fail: /* cleanup */ m_free(chansess->x11authprot); m_free(chansess->x11authcookie); close(fd); return DROPBEAR_FAILURE; }
int parse_config(char* filename) { FILE* f = fopen(filename, "r"); if (!f) { fprintf(stderr, "Error '%s' while opening '%s'.\n", strerror(errno), filename); return 0; } bzero(config, sizeof(struct config)); char linebuffer[BUFSIZ]; unsigned int line_count = 0; struct listener* listener = NULL; struct vhost* vhost = NULL; while (fgets(linebuffer, sizeof(linebuffer), f)) { line_count++; if (linebuffer[0] == '#' || linebuffer[1] == 1) continue; char key[BUFSIZ]; char value[BUFSIZ]; if (sscanf(linebuffer, "%[a-z_] = %[^\t\n]", key, value) == 2) { if (strcmp(key, "daemon") == 0 && strcmp(value, "true") == 0) config->daemon = 1; else if (strcmp(key, "listener") == 0) { if (config->listeners == NULL) { listener = new_listener(value); if (listener) { config->listeners = malloc(sizeof(struct listener) * 2); bzero(config->listeners, sizeof(struct listener) * 2); config->listeners[0] = listener; } else { fprintf(stderr, "%s is not valid.\n", value); return 0; } } else { listener = new_listener(value); if (listener) { size_t i = 0; while (config->listeners[++i]); config->listeners = realloc(config->listeners, sizeof(struct listener) * (i + 2)); config->listeners[i] = listener; config->listeners[++i] = NULL; } else { fprintf(stderr, "%s is not valid.\n", value); return 0; } } } else if (listener && strcmp(key, "pingmode") == 0) { if (strcmp(value, "forward") == 0) listener->ping_mode = FORWARD_PING; else if (strcmp(value, "static") == 0) { listener->ping_mode = malloc(sizeof(struct ping_mode)); bzero(listener->ping_mode, sizeof(struct ping_mode)); listener->ping_mode->motd = "A Minecraft Server"; } else { fprintf(stderr, "'%s' is invalid for pingmode, only 'forward' and 'static' are valid.\n", value); return 0; } } else if (listener && !listener->logfile && strcmp(key, "logfile") == 0) { if (strcmp(value, "stderr") == 0) listener->logfile = STDERR; else if (strcmp(value, "stdout") == 0) listener->logfile = STDOUT; else if (strcmp(value, SYSLOG) == 0) listener->logfile = SYSLOG; else { FILE* f = fopen(value, "a"); if (f) { listener->logfile = strdup(value); fclose(f); } else { fprintf(stderr, "Error '%s'.\n", strerror(errno)); return 0; } } } else if (listener && strcmp(key, "vhost") == 0) { vhost = new_vhost(value); if (listener->vhosts == NULL) { listener->vhosts = malloc(sizeof(struct vhost) * 2); bzero(listener->vhosts, sizeof(struct vhost) * 2); listener->vhosts[0] = vhost; } else { size_t i = 0; while (listener->vhosts[++i]); listener->vhosts = realloc(listener->vhosts, sizeof(struct vhost) * (i + 2)); listener->vhosts[i] = vhost; listener->vhosts[++i] = NULL; } } else if (vhost && strcmp(key, "internaladdress") == 0) { if (fill_in_vhost_address(vhost, value) == 0) { fprintf(stderr, "%s is not valid.\n", value); return 0; } } else if (listener && listener->ping_mode && listener->ping_mode != FORWARD_PING) { if (strcmp(key, "version") == 0) { free(listener->ping_mode->version); listener->ping_mode->version = strdup(value); } else if (strcmp(key, "numplayers") == 0) listener->ping_mode->numplayers = atoi(value); else if (strcmp(key, "maxplayers") == 0) listener->ping_mode->maxplayers = atoi(value); DEBUG(255, "motd: %s", listener->ping_mode->motd); DEBUG(255, "version: %s", listener->ping_mode->version); DEBUG(255, "%d/%d", listener->ping_mode->numplayers, listener->ping_mode->maxplayers); } } } return line_count; };
int parse_config(char* config_file) { FILE* f = fopen(config_file, "r"); if (!f) { fprintf(stderr, "Error '%s' while opening '%s'\n", strerror(errno), config_file); return 1; } char line_buffer[BUFSIZ]; config = malloc(sizeof(struct config)); bzero(config, sizeof(struct config)); struct listener* listener = NULL; struct module* module = NULL; unsigned int line_count = 0; while (fgets(line_buffer, sizeof(line_buffer), f)) { line_count++; if (strlen(line_buffer) <= 1 || line_buffer[0] == '#') continue; char key[BUFSIZ]; char value[BUFSIZ]; if (sscanf(line_buffer, "%[a-z_] = %[^\t\n]", key, value) == 2) { if (config->disconnect_after_bytes == 0 && strcmp(key, "disconnect_after_bytes") == 0) { errno = 0; unsigned short tmp = strtol(value, NULL, 10); if (errno == 0) config->disconnect_after_bytes = tmp; } else if (!config->dateformat && strcmp(key, "dateformat") == 0) config->dateformat = strdup(value); else if (strcmp(key, "listener") == 0) { listener = new_listener(value); module = NULL; if (listener) { if (!config->listeners) config->listeners = listener; else { struct listener* l = config->listeners; while (l->next) l = l->next; l->next = listener; } } } else if (listener && strcmp(key, "module") == 0) { module = new_module(value); if (module) { if (!listener->modules) listener->modules = module; else { struct module* m = listener->modules; while (m->next) m = m->next; m->next = module; } } } else if (listener && module && !module->address && strcmp(key, "address") == 0) { char address[129]; uint16_t port; if (sscanf(value, "%128[^:]:%hd", address, &port) == 2) { module->address = strdup(address); module->port = port; } } else if (listener && module && !module->logfile && strcmp(key, "logfile") == 0) { if (strcmp(value, "stderr") == 0) module->logfile = STDERR; else if (strcmp(value, "stdout") == 0) module->logfile = STDOUT; else if (strcmp(value, "syslog") == 0) module->logfile = SYSLOG; else { FILE* f = fopen(value, "a"); if (f) { module->logfile = strdup(value); fclose(f); } else fprintf(stderr, "ERROR: %s\n", strerror(errno)); } } else if (listener && module && !module->logformat && strcmp(key, "logformat") == 0) module->logformat = strdup(value); } else { fprintf(stderr, "Error on line %ud\tCould not be parsed correctly.\n", line_count); return 1; } }; return 0; };
TRACE(("enter listen_tcpfwd")) /* first we try to bind, so don't need to do so much cleanup on failure */ snprintf(portstring, sizeof(portstring), "%u", tcpinfo->listenport); nsocks = dropbear_listen(AF_UNSPEC, tcpinfo->listenaddr, portstring, socks, DROPBEAR_MAX_SOCKS, &errstring, &ses.maxfd); if (nsocks < 0) { dropbear_log(LOG_INFO, "TCP forward failed: %s", errstring); m_free(errstring); TRACE(("leave listen_tcpfwd: dropbear_listen failed")) return DROPBEAR_FAILURE; } m_free(errstring); /* new_listener will close the socks if it fails */ listener = new_listener(socks, nsocks, CHANNEL_ID_TCPFORWARDED, tcpinfo, tcp_acceptor, cleanup_tcp); if (listener == NULL) { TRACE(("leave listen_tcpfwd: listener failed")) return DROPBEAR_FAILURE; } TRACE(("leave listen_tcpfwd: success")) return DROPBEAR_SUCCESS; } #endif /* DROPBEAR_TCP_ACCEPT */
int platform_make_x11_server(Plug *plug, const char *progname, int mindisp, const char *screen_number_suffix, ptrlen authproto, ptrlen authdata, Socket **sockets, Conf *conf) { char *tmpdir; char *authfilename = NULL; strbuf *authfiledata = NULL; char *unix_path = NULL; SockAddr *a_tcp = NULL, *a_unix = NULL; int authfd; FILE *authfp; int displayno; authfiledata = strbuf_new_nm(); int nsockets = 0; /* * Look for a free TCP port to run our server on. */ for (displayno = mindisp;; displayno++) { const char *err; int tcp_port = displayno + 6000; int addrtype = ADDRTYPE_IPV4; sockets[nsockets] = new_listener( NULL, tcp_port, plug, false, conf, addrtype); err = sk_socket_error(sockets[nsockets]); if (!err) { char *hostname = get_hostname(); if (hostname) { char *canonicalname = NULL; a_tcp = name_lookup(hostname, tcp_port, &canonicalname, conf, addrtype, NULL, ""); sfree(canonicalname); } sfree(hostname); nsockets++; break; /* success! */ } else { sk_close(sockets[nsockets]); } if (!strcmp(err, strerror(EADDRINUSE))) /* yuck! */ goto out; } if (a_tcp) { x11_format_auth_for_authfile( BinarySink_UPCAST(authfiledata), a_tcp, displayno, authproto, authdata); } /* * Try to establish the Unix-domain analogue. That may or may not * work - file permissions in /tmp may prevent it, for example - * but it's worth a try, and we don't consider it a fatal error if * it doesn't work. */ unix_path = dupprintf("/tmp/.X11-unix/X%d", displayno); a_unix = unix_sock_addr(unix_path); sockets[nsockets] = new_unix_listener(a_unix, plug); if (!sk_socket_error(sockets[nsockets])) { x11_format_auth_for_authfile( BinarySink_UPCAST(authfiledata), a_unix, displayno, authproto, authdata); nsockets++; } else { sk_close(sockets[nsockets]); sfree(unix_path); unix_path = NULL; } /* * Decide where the authority data will be written. */ tmpdir = getenv("TMPDIR"); if (!tmpdir || !*tmpdir) tmpdir = "/tmp"; authfilename = dupcat(tmpdir, "/", progname, "-Xauthority-XXXXXX", NULL); { int oldumask = umask(077); authfd = mkstemp(authfilename); umask(oldumask); } if (authfd < 0) { while (nsockets-- > 0) sk_close(sockets[nsockets]); goto out; } /* * Spawn a subprocess which will try to reliably delete our * auth file when we terminate, in case we die unexpectedly. */ { int cleanup_pipe[2]; pid_t pid; /* Don't worry if pipe or fork fails; it's not _that_ critical. */ if (!pipe(cleanup_pipe)) { if ((pid = fork()) == 0) { int buf[1024]; /* * Our parent process holds the writing end of * this pipe, and writes nothing to it. Hence, * we expect read() to return EOF as soon as * that process terminates. */ close(0); close(1); close(2); setpgid(0, 0); close(cleanup_pipe[1]); close(authfd); while (read(cleanup_pipe[0], buf, sizeof(buf)) > 0); unlink(authfilename); if (unix_path) unlink(unix_path); _exit(0); } else if (pid < 0) { close(cleanup_pipe[0]); close(cleanup_pipe[1]); } else { close(cleanup_pipe[0]); cloexec(cleanup_pipe[1]); } } } authfp = fdopen(authfd, "wb"); fwrite(authfiledata->u, 1, authfiledata->len, authfp); fclose(authfp); { char *display = dupprintf(":%d%s", displayno, screen_number_suffix); conf_set_str_str(conf, CONF_environmt, "DISPLAY", display); sfree(display); } conf_set_str_str(conf, CONF_environmt, "XAUTHORITY", authfilename); /* * FIXME: return at least the DISPLAY and XAUTHORITY env settings, * and perhaps also the display number */ out: if (a_tcp) sk_addr_free(a_tcp); /* a_unix doesn't need freeing, because new_unix_listener took it over */ sfree(authfilename); strbuf_free(authfiledata); sfree(unix_path); return nsockets; }