int mm_answer_pty(int socket, Buffer *m) { extern struct monitor *pmonitor; Session *s; int res, fd0; debug3("%s entering", __func__); buffer_clear(m); s = session_new(); if (s == NULL) goto error; s->authctxt = authctxt; s->pw = authctxt->pw; s->pid = pmonitor->m_pid; res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)); if (res == 0) goto error; fatal_add_cleanup(session_pty_cleanup2, (void *)s); pty_setowner(authctxt->pw, s->tty); buffer_put_int(m, 1); buffer_put_cstring(m, s->tty); mm_request_send(socket, MONITOR_ANS_PTY, m); mm_send_fd(socket, s->ptyfd); mm_send_fd(socket, s->ttyfd); /* We need to trick ttyslot */ if (dup2(s->ttyfd, 0) == -1) fatal("%s: dup2", __func__); mm_record_login(s, authctxt->pw); /* Now we can close the file descriptor again */ close(0); /* make sure nothing uses fd 0 */ if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) < 0) fatal("%s: open(/dev/null): %s", __func__, strerror(errno)); if (fd0 != 0) error("%s: fd0 %d != 0", __func__, fd0); /* slave is not needed */ close(s->ttyfd); s->ttyfd = s->ptyfd; /* no need to dup() because nobody closes ptyfd */ s->ptymaster = s->ptyfd; debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ttyfd); return (0); error: if (s != NULL) mm_session_close(s); buffer_put_int(m, 0); mm_request_send(socket, MONITOR_ANS_PTY, m); return (0); }
static gboolean reload_database (NMSessionMonitor *self, GError **error) { struct stat statbuf; char **groups = NULL; gsize len = 0, i; Session *s; free_database (self); errno = 0; if (stat (CKDB_PATH, &statbuf) != 0) { g_set_error (error, NM_SESSION_MONITOR_ERROR, errno == ENOENT ? NM_SESSION_MONITOR_ERROR_NO_DATABASE : NM_SESSION_MONITOR_ERROR_IO_ERROR, "Error statting file " CKDB_PATH ": %s", strerror (errno)); goto error; } self->database_mtime = statbuf.st_mtime; self->database = g_key_file_new (); if (!g_key_file_load_from_file (self->database, CKDB_PATH, G_KEY_FILE_NONE, error)) goto error; groups = g_key_file_get_groups (self->database, &len); if (!groups) { g_set_error_literal (error, NM_SESSION_MONITOR_ERROR, NM_SESSION_MONITOR_ERROR_IO_ERROR, "Could not load groups from " CKDB_PATH ""); goto error; } for (i = 0; i < len; i++) { Session *found; if (!g_str_has_prefix (groups[i], "Session ")) continue; s = session_new (self->database, groups[i], error); if (!s) goto error; found = g_hash_table_lookup (self->sessions_by_user, (gpointer) s->user); if (found) { session_merge (s, found); session_free (s); } else { /* Entirely new user */ g_hash_table_insert (self->sessions_by_user, (gpointer) s->user, s); g_hash_table_insert (self->sessions_by_uid, GUINT_TO_POINTER (s->uid), s); } } g_strfreev (groups); return TRUE; error: if (groups) g_strfreev (groups); free_database (self); return FALSE; }
*/ if (unix_user && conf_path && session->conf_path && strcmp (conf_path, session->conf_path)) { nih_free (session->conf_path); session->conf_path = NULL; } if (! session->conf_path) session_create_conf_source (session); return session; } /* Didn't find one, make a new one */ session = NIH_MUST (session_new (parent, unix_process_id ? root : NULL, unix_user)); session_create_conf_source (session); return session; } /** * session_create_conf_source: * @session: Session. * * Create a new ConfSouce object and associate the specified session * with it. **/ static void session_create_conf_source (Session *session) {
/* * Create a new peer session in assigned state (connect will start automatically) */ static struct stream *peer_session_create(struct peer *peer, struct peer_session *ps) { struct listener *l = LIST_NEXT(&peer->peers->peers_fe->conf.listeners, struct listener *, by_fe); struct proxy *p = (struct proxy *)l->frontend; /* attached frontend */ struct appctx *appctx; struct session *sess; struct stream *s; struct task *t; struct connection *conn; ps->reconnect = tick_add(now_ms, MS_TO_TICKS(5000)); ps->statuscode = PEER_SESS_SC_CONNECTCODE; s = NULL; appctx = appctx_new(&peer_applet); if (!appctx) goto out_close; appctx->st0 = PEER_SESS_ST_CONNECT; appctx->ctx.peers.ptr = (void *)ps; sess = session_new(p, l, &appctx->obj_type); if (!sess) { Alert("out of memory in peer_session_create().\n"); goto out_free_appctx; } if ((t = task_new()) == NULL) { Alert("out of memory in peer_session_create().\n"); goto out_free_sess; } t->nice = l->nice; if ((s = stream_new(sess, t, &appctx->obj_type)) == NULL) { Alert("Failed to initialize stream in peer_session_create().\n"); goto out_free_task; } /* The tasks below are normally what is supposed to be done by * fe->accept(). */ s->flags = SF_ASSIGNED|SF_ADDR_SET; /* applet is waiting for data */ si_applet_cant_get(&s->si[0]); appctx_wakeup(appctx); /* initiate an outgoing connection */ si_set_state(&s->si[1], SI_ST_ASS); /* automatically prepare the stream interface to connect to the * pre-initialized connection in si->conn. */ if (unlikely((conn = conn_new()) == NULL)) goto out_free_strm; conn_prepare(conn, peer->proto, peer->xprt); si_attach_conn(&s->si[1], conn); conn->target = s->target = &s->be->obj_type; memcpy(&conn->addr.to, &peer->addr, sizeof(conn->addr.to)); s->do_log = NULL; s->uniq_id = 0; s->res.flags |= CF_READ_DONTWAIT; l->nbconn++; /* warning! right now, it's up to the handler to decrease this */ p->feconn++;/* beconn will be increased later */ jobs++; if (!(s->sess->listener->options & LI_O_UNLIMITED)) actconn++; totalconn++; ps->appctx = appctx; ps->stream = s; return s; /* Error unrolling */ out_free_strm: LIST_DEL(&s->list); pool_free2(pool2_stream, s); out_free_task: task_free(t); out_free_sess: session_free(sess); out_free_appctx: appctx_free(appctx); out_close: return s; }
enum cmd_retval cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct session *s; struct winlink *wl; struct client *c; const char *cmd, *template; char *cause, *cp; int idx, last, detached, cwd, fd = -1; struct format_tree *ft; if (args_has(args, 'a')) { wl = cmd_find_window(cmdq, args_get(args, 't'), &s); if (wl == NULL) return (CMD_RETURN_ERROR); idx = wl->idx + 1; /* Find the next free index. */ for (last = idx; last < INT_MAX; last++) { if (winlink_find_by_index(&s->windows, last) == NULL) break; } if (last == INT_MAX) { cmdq_error(cmdq, "no free window indexes"); return (CMD_RETURN_ERROR); } /* Move everything from last - 1 to idx up a bit. */ for (; last > idx; last--) { wl = winlink_find_by_index(&s->windows, last - 1); server_link_window(s, wl, s, last, 0, 0, NULL); server_unlink_window(s, wl); } } else { if ((idx = cmd_find_index(cmdq, args_get(args, 't'), &s)) == -2) return (CMD_RETURN_ERROR); } detached = args_has(args, 'd'); if (args->argc == 0) cmd = options_get_string(&s->options, "default-command"); else cmd = args->argv[0]; if (args_has(args, 'c')) { ft = format_create(); if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL) format_client(ft, c); format_session(ft, s); format_winlink(ft, s, s->curw); format_window_pane(ft, s->curw->window->active); cp = format_expand(ft, args_get(args, 'c')); format_free(ft); if (cp != NULL && *cp != '\0') { fd = open(cp, O_RDONLY|O_DIRECTORY); free(cp); if (fd == -1) { cmdq_error(cmdq, "bad working directory: %s", strerror(errno)); return (CMD_RETURN_ERROR); } } else if (cp != NULL) free(cp); cwd = fd; } else if (cmdq->client != NULL && cmdq->client->session == NULL) cwd = cmdq->client->cwd; else cwd = s->cwd; wl = NULL; if (idx != -1) wl = winlink_find_by_index(&s->windows, idx); if (wl != NULL && args_has(args, 'k')) { /* * Can't use session_detach as it will destroy session if this * makes it empty. */ notify_window_unlinked(s, wl->window); wl->flags &= ~WINLINK_ALERTFLAGS; winlink_stack_remove(&s->lastw, wl); winlink_remove(&s->windows, wl); /* Force select/redraw if current. */ if (wl == s->curw) { detached = 0; s->curw = NULL; } } if (idx == -1) idx = -1 - options_get_number(&s->options, "base-index"); wl = session_new(s, args_get(args, 'n'), cmd, cwd, idx, &cause); if (wl == NULL) { cmdq_error(cmdq, "create window failed: %s", cause); free(cause); goto error; } if (!detached) { session_select(s, wl->idx); server_redraw_session_group(s); } else server_status_session_group(s); if (args_has(args, 'P')) { if ((template = args_get(args, 'F')) == NULL)
int cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx) { struct cmd_new_window_data *data = self->data; struct session *s; struct winlink *wl; char *cmd, *cwd, *cause; int idx, last; if (data == NULL) return (0); if (data->flag_insert_after) { if ((wl = cmd_find_window(ctx, data->target, &s)) == NULL) return (-1); idx = wl->idx + 1; /* Find the next free index. */ for (last = idx; last < INT_MAX; last++) { if (winlink_find_by_index(&s->windows, last) == NULL) break; } if (last == INT_MAX) { ctx->error(ctx, "no free window indexes"); return (-1); } /* Move everything from last - 1 to idx up a bit. */ for (; last > idx; last--) { wl = winlink_find_by_index(&s->windows, last - 1); server_link_window(s, wl, s, last, 0, 0, NULL); server_unlink_window(s, wl); } } else { if ((idx = cmd_find_index(ctx, data->target, &s)) == -2) return (-1); } wl = NULL; if (idx != -1) wl = winlink_find_by_index(&s->windows, idx); if (wl != NULL && data->flag_kill) { /* * Can't use session_detach as it will destroy session if this * makes it empty. */ wl->flags &= ~WINLINK_ALERTFLAGS; winlink_stack_remove(&s->lastw, wl); winlink_remove(&s->windows, wl); /* Force select/redraw if current. */ if (wl == s->curw) { data->flag_detached = 0; s->curw = NULL; } } cmd = data->cmd; if (cmd == NULL) cmd = options_get_string(&s->options, "default-command"); cwd = options_get_string(&s->options, "default-path"); if (*cwd == '\0') { if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL) cwd = ctx->cmdclient->cwd; else cwd = s->cwd; } if (idx == -1) idx = -1 - options_get_number(&s->options, "base-index"); wl = session_new(s, data->name, cmd, cwd, idx, &cause); if (wl == NULL) { ctx->error(ctx, "create window failed: %s", cause); xfree(cause); return (-1); } if (!data->flag_detached) { session_select(s, wl->idx); server_redraw_session_group(s); } else server_status_session_group(s); if (data->flag_print) ctx->print(ctx, "%s:%u", s->name, wl->idx); return (0); }
int cmd_new_window_exec(struct cmd *self, struct cmd_ctx *ctx) { struct args *args = self->args; struct session *s; struct winlink *wl; struct client *c; const char *cmd, *cwd; char *cause; int idx, last, detached; if (args_has(args, 'a')) { wl = cmd_find_window(ctx, args_get(args, 't'), &s); if (wl == NULL) return (-1); idx = wl->idx + 1; /* Find the next free index. */ for (last = idx; last < INT_MAX; last++) { if (winlink_find_by_index(&s->windows, last) == NULL) break; } if (last == INT_MAX) { ctx->error(ctx, "no free window indexes"); return (-1); } /* Move everything from last - 1 to idx up a bit. */ for (; last > idx; last--) { wl = winlink_find_by_index(&s->windows, last - 1); server_link_window(s, wl, s, last, 0, 0, NULL); server_unlink_window(s, wl); } } else { if ((idx = cmd_find_index(ctx, args_get(args, 't'), &s)) == -2) return (-1); } detached = args_has(args, 'd'); wl = NULL; if (idx != -1) wl = winlink_find_by_index(&s->windows, idx); if (wl != NULL && args_has(args, 'k')) { /* * Can't use session_detach as it will destroy session if this * makes it empty. */ control_notify_window_removed(wl->window); wl->flags &= ~WINLINK_ALERTFLAGS; winlink_stack_remove(&s->lastw, wl); winlink_remove(&s->windows, wl); /* Force select/redraw if current. */ if (wl == s->curw) { detached = 0; s->curw = NULL; } } if (args->argc == 0) cmd = options_get_string(&s->options, "default-command"); else cmd = args->argv[0]; cwd = cmd_get_default_path(ctx); if (idx == -1) idx = -1 - options_get_number(&s->options, "base-index"); wl = session_new(s, args_get(args, 'n'), cmd, cwd, idx, &cause); if (wl == NULL) { ctx->error(ctx, "create window failed: %s", cause); xfree(cause); return (-1); } if (!detached) { session_select(s, wl->idx); server_redraw_session_group(s); } else server_status_session_group(s); if (args_has(args, 'P')) ctx->print(ctx, "%s:%u", s->name, wl->idx); // TODO: Use a -F instead c = cmd_find_client(ctx, NULL); if (c && c->flags & CLIENT_CONTROL) ctx->print(ctx, "%u", wl->window->id); return (0); }
int mm_answer_pty(int sock, struct sshbuf *m) { extern struct monitor *pmonitor; Session *s; int r, res, fd0; debug3("%s entering", __func__); sshbuf_reset(m); s = session_new(); if (s == NULL) goto error; s->authctxt = authctxt; s->pw = authctxt->pw; s->pid = pmonitor->m_pid; res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)); if (res == 0) goto error; pty_setowner(authctxt->pw, s->tty); if ((r = sshbuf_put_u32(m, 1)) != 0 || (r = sshbuf_put_cstring(m, s->tty)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); /* We need to trick ttyslot */ if (dup2(s->ttyfd, 0) == -1) fatal("%s: dup2", __func__); mm_record_login(s, authctxt->pw); /* Now we can close the file descriptor again */ close(0); /* send messages generated by record_login */ if ((r = sshbuf_put_stringb(m, loginmsg)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); sshbuf_reset(loginmsg); mm_request_send(sock, MONITOR_ANS_PTY, m); if (mm_send_fd(sock, s->ptyfd) == -1 || mm_send_fd(sock, s->ttyfd) == -1) fatal("%s: send fds failed", __func__); /* make sure nothing uses fd 0 */ if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) < 0) fatal("%s: open(/dev/null): %s", __func__, strerror(errno)); if (fd0 != 0) error("%s: fd0 %d != 0", __func__, fd0); /* slave is not needed */ close(s->ttyfd); s->ttyfd = s->ptyfd; /* no need to dup() because nobody closes ptyfd */ s->ptymaster = s->ptyfd; debug3("%s: tty %s ptyfd %d", __func__, s->tty, s->ttyfd); return (0); error: if (s != NULL) mm_session_close(s); if ((r = sshbuf_put_u32(m, 0)) != 0) fatal("%s: buffer error: %s", __func__, ssh_err(r)); mm_request_send(sock, MONITOR_ANS_PTY, m); return (0); }
void session_upload_new(struct incident *i) { GHashTableIter iter; gpointer key, value; GString *gstemp; struct session *session = NULL; char *url = NULL; if (incident_value_string_get(i, "_url", &gstemp) == false ) { g_debug("dionaea.upload.request got no _url in incident!"); return; } session = session_new(); session->type = session_type_upload; url = gstemp->str; session->url = g_strdup(url); g_hash_table_iter_init (&iter, i->data); while( g_hash_table_iter_next (&iter, &key, &value) ) { char *name = key; struct opaque_data *d = value; char name_and_param[1024]; if( d->type == opaque_type_int ) { g_warning("incident key %s has integer value. all post fields must be string values.", name); } else if( d->type == opaque_type_string) { /* ignore help field values */ if( strstr(name, "_ct") != NULL || strcmp(name, "_url") == 0) continue; if( strcmp(name, "_callback") == 0 ) { /* incident callback */ session->action.upload.callback = g_strdup(d->opaque.string->str); session->action.upload.file = tempfile_new(curl_runtime.download_dir, "httpupload-"); }else if( strcmp(name, "_userdata") == 0 ) { /* incident callback userdata */ session->action.upload.userdata = g_strdup(d->opaque.string->str); }else if( strcmp(name, "user") == 0 ) { /* http auth user */ session->action.upload.username = g_strdup(d->opaque.string->str); curl_easy_setopt(session->easy, CURLOPT_USERNAME, session->action.upload.username); }else if( strcmp(name, "pass") == 0 ) { /* http auth password */ session->action.upload.password = g_strdup(d->opaque.string->str); curl_easy_setopt(session->easy, CURLOPT_PASSWORD, session->action.upload.password); }else if( strncmp(name, "file://", 7) == 0 ) { /* we upload this file */ curl_formadd(&session->action.upload.formpost, &session->action.upload.last, CURLFORM_COPYNAME, name + 7, CURLFORM_FILE, d->opaque.string->str, CURLFORM_END); }else { /* all other values */ snprintf(name_and_param, 1024, "%s_ct", name); if ( incident_value_string_get(i, name_and_param, &gstemp) == true) { /* with content type */ curl_formadd(&session->action.upload.formpost, &session->action.upload.last, CURLFORM_COPYNAME, name, CURLFORM_CONTENTTYPE, gstemp->str, CURLFORM_COPYCONTENTS, d->opaque.string->str, CURLFORM_END); } else { /* without content type */ curl_formadd(&session->action.upload.formpost, &session->action.upload.last, CURLFORM_COPYNAME, name, CURLFORM_COPYCONTENTS, d->opaque.string->str, CURLFORM_END); } } } } char buf[] = "Expect:"; session->action.upload.headers = curl_slist_append(session->action.upload.headers, buf); curl_easy_setopt(session->easy, CURLOPT_URL, session->url); curl_easy_setopt(session->easy, CURLOPT_HTTPPOST, session->action.upload.formpost); curl_easy_setopt(session->easy, CURLOPT_HTTPHEADER, session->action.upload.headers); curl_easy_setopt(session->easy, CURLOPT_WRITEFUNCTION, curl_writefunction_cb); curl_easy_setopt(session->easy, CURLOPT_WRITEDATA, session); curl_easy_setopt(session->easy, CURLOPT_DEBUGFUNCTION, curl_debugfunction_cb); // curl_easy_setopt(session->easy, CURLOPT_VERBOSE, 1L); curl_easy_setopt(session->easy, CURLOPT_ERRORBUFFER, session->error); curl_easy_setopt(session->easy, CURLOPT_PRIVATE, session); curl_easy_setopt(session->easy, CURLOPT_NOPROGRESS, 0L); curl_easy_setopt(session->easy, CURLOPT_PROGRESSFUNCTION, curl_progressfunction_cb); curl_easy_setopt(session->easy, CURLOPT_PROGRESSDATA, session); curl_easy_setopt(session->easy, CURLOPT_LOW_SPEED_TIME, 3L); curl_easy_setopt(session->easy, CURLOPT_LOW_SPEED_LIMIT, 10L); curl_easy_setopt(session->easy, CURLOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)"); curl_easy_setopt(session->easy, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(session->easy, CURLOPT_SSL_VERIFYHOST, 0); g_debug("Adding easy %p to multi %p (%s)", session->easy, curl_runtime.multi, url); curl_multi_add_handle(curl_runtime.multi, session->easy); curl_runtime.queued++; check_run_count(); }
/* This function is called from the protocol layer accept() in order to * instanciate a new session on behalf of a given listener and frontend. It * returns a positive value upon success, 0 if the connection can be ignored, * or a negative value upon critical failure. The accepted file descriptor is * closed if we return <= 0. If no handshake is needed, it immediately tries * to instanciate a new stream. */ int session_accept_fd(struct listener *l, int cfd, struct sockaddr_storage *addr) { struct connection *cli_conn; struct proxy *p = l->frontend; struct session *sess; struct stream *strm; struct task *t; int ret; ret = -1; /* assume unrecoverable error by default */ if (unlikely((cli_conn = conn_new()) == NULL)) goto out_close; conn_prepare(cli_conn, l->proto, l->xprt); cli_conn->t.sock.fd = cfd; cli_conn->addr.from = *addr; cli_conn->flags |= CO_FL_ADDR_FROM_SET; cli_conn->target = &l->obj_type; cli_conn->proxy_netns = l->netns; conn_ctrl_init(cli_conn); /* wait for a PROXY protocol header */ if (l->options & LI_O_ACC_PROXY) { cli_conn->flags |= CO_FL_ACCEPT_PROXY; conn_sock_want_recv(cli_conn); } conn_data_want_recv(cli_conn); if (conn_xprt_init(cli_conn) < 0) goto out_free_conn; sess = session_new(p, l, &cli_conn->obj_type); if (!sess) goto out_free_conn; p->feconn++; /* This session was accepted, count it now */ if (p->feconn > p->fe_counters.conn_max) p->fe_counters.conn_max = p->feconn; proxy_inc_fe_conn_ctr(l, p); /* now evaluate the tcp-request layer4 rules. We only need a session * and no stream for these rules. */ if ((l->options & LI_O_TCP_RULES) && !tcp_exec_req_rules(sess)) { /* let's do a no-linger now to close with a single RST. */ setsockopt(cfd, SOL_SOCKET, SO_LINGER, (struct linger *) &nolinger, sizeof(struct linger)); ret = 0; /* successful termination */ goto out_free_sess; } /* monitor-net and health mode are processed immediately after TCP * connection rules. This way it's possible to block them, but they * never use the lower data layers, they send directly over the socket, * as they were designed for. We first flush the socket receive buffer * in order to avoid emission of an RST by the system. We ignore any * error. */ if (unlikely((p->mode == PR_MODE_HEALTH) || ((l->options & LI_O_CHK_MONNET) && addr->ss_family == AF_INET && (((struct sockaddr_in *)addr)->sin_addr.s_addr & p->mon_mask.s_addr) == p->mon_net.s_addr))) { /* we have 4 possibilities here : * - HTTP mode, from monitoring address => send "HTTP/1.0 200 OK" * - HEALTH mode with HTTP check => send "HTTP/1.0 200 OK" * - HEALTH mode without HTTP check => just send "OK" * - TCP mode from monitoring address => just close */ if (l->proto->drain) l->proto->drain(cfd); if (p->mode == PR_MODE_HTTP || (p->mode == PR_MODE_HEALTH && (p->options2 & PR_O2_CHK_ANY) == PR_O2_HTTP_CHK)) send(cfd, "HTTP/1.0 200 OK\r\n\r\n", 19, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_MORE); else if (p->mode == PR_MODE_HEALTH) send(cfd, "OK\n", 3, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_MORE); ret = 0; goto out_free_sess; } /* Adjust some socket options */ if (l->addr.ss_family == AF_INET || l->addr.ss_family == AF_INET6) { setsockopt(cfd, IPPROTO_TCP, TCP_NODELAY, (char *) &one, sizeof(one)); if (p->options & PR_O_TCP_CLI_KA) setsockopt(cfd, SOL_SOCKET, SO_KEEPALIVE, (char *) &one, sizeof(one)); if (p->options & PR_O_TCP_NOLING) fdtab[cfd].linger_risk = 1; #if defined(TCP_MAXSEG) if (l->maxseg < 0) { /* we just want to reduce the current MSS by that value */ int mss; socklen_t mss_len = sizeof(mss); if (getsockopt(cfd, IPPROTO_TCP, TCP_MAXSEG, &mss, &mss_len) == 0) { mss += l->maxseg; /* remember, it's < 0 */ setsockopt(cfd, IPPROTO_TCP, TCP_MAXSEG, &mss, sizeof(mss)); } } #endif } if (global.tune.client_sndbuf) setsockopt(cfd, SOL_SOCKET, SO_SNDBUF, &global.tune.client_sndbuf, sizeof(global.tune.client_sndbuf)); if (global.tune.client_rcvbuf) setsockopt(cfd, SOL_SOCKET, SO_RCVBUF, &global.tune.client_rcvbuf, sizeof(global.tune.client_rcvbuf)); if (unlikely((t = task_new()) == NULL)) goto out_free_sess; t->context = sess; t->nice = l->nice; /* OK, now either we have a pending handshake to execute with and * then we must return to the I/O layer, or we can proceed with the * end of the stream initialization. In case of handshake, we also * set the I/O timeout to the frontend's client timeout. * * At this point we set the relation between sess/task/conn this way : * * orig -- sess <-- context * | | * v | * conn -- owner ---> task */ if (cli_conn->flags & CO_FL_HANDSHAKE) { conn_attach(cli_conn, t, &sess_conn_cb); t->process = session_expire_embryonic; t->expire = tick_add_ifset(now_ms, p->timeout.client); task_queue(t); cli_conn->flags |= CO_FL_INIT_DATA | CO_FL_WAKE_DATA; return 1; } /* OK let's complete stream initialization since there is no handshake */ cli_conn->flags |= CO_FL_CONNECTED; /* we want the connection handler to notify the stream interface about updates. */ cli_conn->flags |= CO_FL_WAKE_DATA; /* if logs require transport layer information, note it on the connection */ if (sess->fe->to_log & LW_XPRT) cli_conn->flags |= CO_FL_XPRT_TRACKED; session_count_new(sess); strm = stream_new(sess, t, &cli_conn->obj_type); if (!strm) goto out_free_task; strm->target = sess->listener->default_target; strm->req.analysers = sess->listener->analysers; return 1; out_free_task: task_free(t); out_free_sess: p->feconn--; session_free(sess); out_free_conn: cli_conn->flags &= ~CO_FL_XPRT_TRACKED; conn_xprt_close(cli_conn); conn_free(cli_conn); out_close: if (ret < 0 && l->xprt == &raw_sock && p->mode == PR_MODE_HTTP) { /* critical error, no more memory, try to emit a 500 response */ struct chunk *err_msg = &p->errmsg[HTTP_ERR_500]; if (!err_msg->str) err_msg = &http_err_chunks[HTTP_ERR_500]; send(cfd, err_msg->str, err_msg->len, MSG_DONTWAIT|MSG_NOSIGNAL); } if (fdtab[cfd].owner) fd_delete(cfd); else close(cfd); return ret; }