]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: http: replace get_ip_from_hdr2() with http_get_hdr()
authorWilly Tarreau <w@1wt.eu>
Fri, 16 Dec 2011 20:35:50 +0000 (21:35 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 30 Dec 2011 16:33:26 +0000 (17:33 +0100)
The new function does not return IP addresses but header values instead,
so that the caller is free to make what it want of them. The conversion
is not quite clean yet, as the previous test which considered that address
0.0.0.0 meant "no address" is still used. A different IP parsing function
should be used to take this into account.

include/proto/proto_http.h
src/backend.c
src/proto_http.c

index 4cb4f0b253dfb2067ec82a9e45509dd26e1b7d16..f5dcbce30cacae011bc53072e18cf2ff67221347 100644 (file)
@@ -97,8 +97,9 @@ void http_return_srv_error(struct session *s, struct stream_interface *si);
 void http_capture_bad_message(struct error_snapshot *es, struct session *s,
                               struct buffer *buf, struct http_msg *msg,
                              int state, struct proxy *other_end);
-unsigned int get_ip_from_hdr2(struct http_msg *msg, const char *hname, int hlen,
-                             struct hdr_idx *idx, int occ);
+unsigned int http_get_hdr(struct http_msg *msg, const char *hname, int hlen,
+                         struct hdr_idx *idx, int occ,
+                         struct hdr_ctx *ctx, char **vptr, int *vlen);
 
 void http_init_txn(struct session *s);
 void http_end_txn(struct session *s);
index 5e88f62c97891dec618a71d7832e16d26e720f7f..5dbdec37a88649fb187871649a7e9b22b247b76c 100644 (file)
@@ -881,15 +881,19 @@ static void assign_tproxy_address(struct session *s)
                        break;
                case SRV_TPROXY_DYN:
                        if (srv->bind_hdr_occ) {
+                               char *vptr;
+                               int vlen;
+
                                /* bind to the IP in a header */
                                ((struct sockaddr_in *)&s->req->cons->addr.from)->sin_family = AF_INET;
                                ((struct sockaddr_in *)&s->req->cons->addr.from)->sin_port = 0;
-                               ((struct sockaddr_in *)&s->req->cons->addr.from)->sin_addr.s_addr =
-                                       htonl(get_ip_from_hdr2(&s->txn.req,
-                                                              srv->bind_hdr_name,
-                                                              srv->bind_hdr_len,
-                                                              &s->txn.hdr_idx,
-                                                              srv->bind_hdr_occ));
+                               ((struct sockaddr_in *)&s->req->cons->addr.from)->sin_addr.s_addr = 0;
+
+                               if (http_get_hdr(&s->txn.req, srv->bind_hdr_name, srv->bind_hdr_len,
+                                                &s->txn.hdr_idx, srv->bind_hdr_occ, NULL, &vptr, &vlen)) {
+                                       ((struct sockaddr_in *)&s->req->cons->addr.from)->sin_addr.s_addr =
+                                               htonl(inetaddr_host_lim(vptr, vptr + vlen));
+                               }
                        }
                        break;
                default:
@@ -908,15 +912,19 @@ static void assign_tproxy_address(struct session *s)
                        break;
                case PR_O_TPXY_DYN:
                        if (s->be->bind_hdr_occ) {
+                               char *vptr;
+                               int vlen;
+
                                /* bind to the IP in a header */
                                ((struct sockaddr_in *)&s->req->cons->addr.from)->sin_family = AF_INET;
                                ((struct sockaddr_in *)&s->req->cons->addr.from)->sin_port = 0;
-                               ((struct sockaddr_in *)&s->req->cons->addr.from)->sin_addr.s_addr =
-                                       htonl(get_ip_from_hdr2(&s->txn.req,
-                                                              s->be->bind_hdr_name,
-                                                              s->be->bind_hdr_len,
-                                                              &s->txn.hdr_idx,
-                                                              s->be->bind_hdr_occ));
+                               ((struct sockaddr_in *)&s->req->cons->addr.from)->sin_addr.s_addr = 0;
+
+                               if (http_get_hdr(&s->txn.req, s->be->bind_hdr_name, s->be->bind_hdr_len,
+                                                &s->txn.hdr_idx, s->be->bind_hdr_occ, NULL, &vptr, &vlen)) {
+                                       ((struct sockaddr_in *)&s->req->cons->addr.from)->sin_addr.s_addr =
+                                               htonl(inetaddr_host_lim(vptr, vptr + vlen));
+                               }
                        }
                        break;
                default:
index 10a4bddb7f467d01427c25d32bd80a68f9202863..da785bb4838a2199f8c2039f4f61da072dbe72b6 100644 (file)
@@ -7483,45 +7483,53 @@ void http_capture_bad_message(struct error_snapshot *es, struct session *s,
        es->ev_id = error_snapshot_id++;
 }
 
-/* return the IP address pointed to by occurrence <occ> of header <hname> in
- * HTTP message <msg> indexed in <idx>. If <occ> is strictly positive, the
- * occurrence number corresponding to this value is returned. If <occ> is
- * strictly negative, the occurrence number before the end corresponding to
- * this value is returned. If <occ> is null, any value is returned, so it is
- * not recommended to use it that way. Negative occurrences are limited to
- * a small value because it is required to keep them in memory while scanning.
- * IP address 0.0.0.0 is returned if no match is found.
+/* Return in <vptr> and <vlen> the pointer and length of occurrence <occ> of
+ * header whose name is <hname> of length <hlen>. If <ctx> is null, lookup is
+ * performed over the whole headers. Otherwise it must contain a valid header
+ * context, initialised with ctx->idx=0 for the first lookup in a series. If
+ * <occ> is positive or null, occurrence #occ from the beginning (or last ctx)
+ * is returned. Occ #0 and #1 are equivalent. If <occ> is negative (and no less
+ * than -MAX_HDR_HISTORY), the occurrence is counted from the last one which is
+ * -1.
+ * The return value is 0 if nothing was found, or non-zero otherwise.
  */
-unsigned int get_ip_from_hdr2(struct http_msg *msg, const char *hname, int hlen, struct hdr_idx *idx, int occ)
+unsigned int http_get_hdr(struct http_msg *msg, const char *hname, int hlen,
+                         struct hdr_idx *idx, int occ,
+                         struct hdr_ctx *ctx, char **vptr, int *vlen)
 {
-       struct hdr_ctx ctx;
-       unsigned int hdr_hist[MAX_HDR_HISTORY];
+       struct hdr_ctx local_ctx;
+       char *ptr_hist[MAX_HDR_HISTORY];
+       int len_hist[MAX_HDR_HISTORY];
        unsigned int hist_ptr;
-       int found = 0;
+       int found;
+
+       if (!ctx) {
+               local_ctx.idx = 0;
+               ctx = &local_ctx;
+       }
 
-       ctx.idx = 0;
        if (occ >= 0) {
-               while (http_find_header2(hname, hlen, msg->sol, idx, &ctx)) {
+               /* search from the beginning */
+               while (http_find_header2(hname, hlen, msg->sol, idx, ctx)) {
                        occ--;
                        if (occ <= 0) {
-                               found = 1;
-                               break;
+                               *vptr = ctx->line + ctx->val;
+                               *vlen = ctx->vlen;
+                               return 1;
                        }
                }
-               if (!found)
-                       return 0;
-               return inetaddr_host_lim(ctx.line+ctx.val, ctx.line+ctx.val+ctx.vlen);
+               return 0;
        }
 
        /* negative occurrence, we scan all the list then walk back */
        if (-occ > MAX_HDR_HISTORY)
                return 0;
 
-       hist_ptr = 0;
-       hdr_hist[hist_ptr] = 0;
-       while (http_find_header2(hname, hlen, msg->sol, idx, &ctx)) {
-               hdr_hist[hist_ptr++] = inetaddr_host_lim(ctx.line+ctx.val, ctx.line+ctx.val+ctx.vlen);
-               if (hist_ptr >= MAX_HDR_HISTORY)
+       found = hist_ptr = 0;
+       while (http_find_header2(hname, hlen, msg->sol, idx, ctx)) {
+               ptr_hist[hist_ptr] = ctx->line + ctx->val;
+               len_hist[hist_ptr] = ctx->vlen;
+               if (++hist_ptr >= MAX_HDR_HISTORY)
                        hist_ptr = 0;
                found++;
        }
@@ -7533,7 +7541,9 @@ unsigned int get_ip_from_hdr2(struct http_msg *msg, const char *hname, int hlen,
        hist_ptr += occ;
        if (hist_ptr >= MAX_HDR_HISTORY)
                hist_ptr -= MAX_HDR_HISTORY;
-       return hdr_hist[hist_ptr];
+       *vptr = ptr_hist[hist_ptr];
+       *vlen = len_hist[hist_ptr];
+       return 1;
 }
 
 /*
@@ -8489,8 +8499,13 @@ pattern_fetch_hdr_ip(struct proxy *px, struct session *l4, void *l7, int dir,
                      const struct pattern_arg *arg_p, int arg_i, union pattern_data *data)
 {
        struct http_txn *txn = l7;
+       const char *vptr;
+       int vlen;
+
+       if (!http_get_hdr(&txn->req, arg_p->data.str.str, arg_p->data.str.len, &txn->hdr_idx, -1, NULL, &vptr, &vlen))
+               return 0;
 
-       data->ip.s_addr = htonl(get_ip_from_hdr2(&txn->req, arg_p->data.str.str, arg_p->data.str.len, &txn->hdr_idx, -1));
+       data->ip.s_addr = htonl(inetaddr_host_lim(vptr, vptr + vlen));
        return data->ip.s_addr != 0;
 }