/* If an explicit source binding is specified on the server and/or backend, and * this source makes use of the transparent proxy, then it is extracted now and * assigned to the session's pending connection. This function assumes that an * outgoing connection has already been assigned to s->si[1].end. */ static void assign_tproxy_address(struct session *s) { #if defined(CONFIG_HAP_CTTPROXY) || defined(CONFIG_HAP_TRANSPARENT) struct server *srv = objt_server(s->target); struct conn_src *src; struct connection *cli_conn; struct connection *srv_conn = objt_conn(s->si[1].end); if (srv && srv->conn_src.opts & CO_SRC_BIND) src = &srv->conn_src; else if (s->be->conn_src.opts & CO_SRC_BIND) src = &s->be->conn_src; else return; switch (src->opts & CO_SRC_TPROXY_MASK) { case CO_SRC_TPROXY_ADDR: srv_conn->addr.from = src->tproxy_addr; break; case CO_SRC_TPROXY_CLI: case CO_SRC_TPROXY_CIP: /* FIXME: what can we do if the client connects in IPv6 or unix socket ? */ cli_conn = objt_conn(s->si[0].end); if (cli_conn) srv_conn->addr.from = cli_conn->addr.from; else memset(&srv_conn->addr.from, 0, sizeof(srv_conn->addr.from)); break; case CO_SRC_TPROXY_DYN: if (src->bind_hdr_occ) { char *vptr; int vlen; int rewind; /* bind to the IP in a header */ ((struct sockaddr_in *)&srv_conn->addr.from)->sin_family = AF_INET; ((struct sockaddr_in *)&srv_conn->addr.from)->sin_port = 0; ((struct sockaddr_in *)&srv_conn->addr.from)->sin_addr.s_addr = 0; b_rew(s->req.buf, rewind = http_hdr_rewind(&s->txn.req)); if (http_get_hdr(&s->txn.req, src->bind_hdr_name, src->bind_hdr_len, &s->txn.hdr_idx, src->bind_hdr_occ, NULL, &vptr, &vlen)) { ((struct sockaddr_in *)&srv_conn->addr.from)->sin_addr.s_addr = htonl(inetaddr_host_lim(vptr, vptr + vlen)); } b_adv(s->req.buf, rewind); } break; default: memset(&srv_conn->addr.from, 0, sizeof(srv_conn->addr.from)); } #endif }
/* * Add data to compress */ int http_compression_buffer_add_data(struct session *s, struct buffer *in, struct buffer *out) { struct http_msg *msg = &s->txn.rsp; int consumed_data = 0; int data_process_len; int block1, block2; /* * Temporarily skip already parsed data and chunks to jump to the * actual data block. It is fixed before leaving. */ b_adv(in, msg->next); /* * select the smallest size between the announced chunk size, the input * data, and the available output buffer size. The compressors are * assumed to be able to process all the bytes we pass to them at once. */ data_process_len = MIN(in->i, msg->chunk_len); data_process_len = MIN(out->size - buffer_len(out), data_process_len); block1 = data_process_len; if (block1 > bi_contig_data(in)) block1 = bi_contig_data(in); block2 = data_process_len - block1; /* compressors return < 0 upon error or the amount of bytes read */ consumed_data = s->comp_algo->add_data(s->comp_ctx, bi_ptr(in), block1, out); if (consumed_data >= 0 && block2 > 0) { consumed_data = s->comp_algo->add_data(s->comp_ctx, in->data, block2, out); if (consumed_data >= 0) consumed_data += block1; } /* restore original buffer pointer */ b_rew(in, msg->next); if (consumed_data > 0) { msg->next += consumed_data; msg->chunk_len -= consumed_data; } return consumed_data; }
/* RDP Cookie HASH. */ struct server *get_server_rch(struct session *s) { unsigned int hash = 0; struct proxy *px = s->be; unsigned long len; int ret; struct sample smp; int rewind; /* tot_weight appears to mean srv_count */ if (px->lbprm.tot_weight == 0) return NULL; memset(&smp, 0, sizeof(smp)); b_rew(s->req.buf, rewind = s->req.buf->o); ret = fetch_rdp_cookie_name(s, &smp, px->hh_name, px->hh_len); len = smp.data.str.len; b_adv(s->req.buf, rewind); if (ret == 0 || (smp.flags & SMP_F_MAY_CHANGE) || len == 0) return NULL; /* note: we won't hash if there's only one server left */ if (px->lbprm.tot_used == 1) goto hash_done; /* Found a the hh_name in the headers. * we will compute the hash based on this value ctx.val. */ hash = gen_hash(px, smp.data.str.str, len); if ((px->lbprm.algo & BE_LB_HASH_MOD) == BE_LB_HMOD_AVAL) hash = full_hash(hash); hash_done: if (px->lbprm.algo & BE_LB_LKUP_CHTREE) return chash_get_server_hash(px, hash); else return map_get_server_hash(px, hash); }