blob: 356caf6bb05584b210cb2aa842360750d5fff46d [file] [log] [blame]
Emeric Brun107ca302010-01-04 16:16:05 +01001/*
Willy Tarreaucd3b0942012-04-27 21:52:18 +02002 * Sample management functions.
Emeric Brun107ca302010-01-04 16:16:05 +01003 *
4 * Copyright 2009-2010 EXCELIANCE, Emeric Brun <ebrun@exceliance.fr>
Willy Tarreaucd3b0942012-04-27 21:52:18 +02005 * Copyright (C) 2012 Willy Tarreau <w@1wt.eu>
Emeric Brun107ca302010-01-04 16:16:05 +01006 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
12 */
13
14#include <string.h>
15#include <arpa/inet.h>
Willy Tarreaudd2f85e2012-09-02 22:34:23 +020016#include <stdio.h>
Emeric Brun107ca302010-01-04 16:16:05 +010017
Willy Tarreau7e2c6472012-10-29 20:44:36 +010018#include <types/global.h>
19
Willy Tarreauc7e42382012-08-24 19:22:53 +020020#include <common/chunk.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020021#include <common/standard.h>
Willy Tarreaua4312fa2013-04-02 16:34:32 +020022#include <common/uri_auth.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020023
Willy Tarreau9fcb9842012-04-20 14:45:49 +020024#include <proto/arg.h>
Willy Tarreaua4312fa2013-04-02 16:34:32 +020025#include <proto/auth.h>
26#include <proto/log.h>
Thierry FOURNIERd4373142013-12-17 01:10:10 +010027#include <proto/proto_http.h>
Willy Tarreaua4312fa2013-04-02 16:34:32 +020028#include <proto/proxy.h>
Willy Tarreaucd3b0942012-04-27 21:52:18 +020029#include <proto/sample.h>
Willy Tarreaua4312fa2013-04-02 16:34:32 +020030#include <proto/stick_table.h>
Emeric Brun107ca302010-01-04 16:16:05 +010031
Willy Tarreau1cf8f082014-02-07 12:14:54 +010032/* sample type names */
33const char *smp_to_type[SMP_TYPES] = {
34 [SMP_T_BOOL] = "bool",
35 [SMP_T_UINT] = "uint",
36 [SMP_T_SINT] = "sint",
37 [SMP_T_ADDR] = "addr",
38 [SMP_T_IPV4] = "ipv4",
39 [SMP_T_IPV6] = "ipv6",
40 [SMP_T_STR] = "str",
41 [SMP_T_BIN] = "bin",
Willy Tarreau1cf8f082014-02-07 12:14:54 +010042};
43
Willy Tarreau12785782012-04-27 21:37:17 +020044/* static sample used in sample_process() when <p> is NULL */
Willy Tarreaub4a88f02012-04-23 21:35:11 +020045static struct sample temp_smp;
Emeric Brun107ca302010-01-04 16:16:05 +010046
Willy Tarreau12785782012-04-27 21:37:17 +020047/* list head of all known sample fetch keywords */
48static struct sample_fetch_kw_list sample_fetches = {
49 .list = LIST_HEAD_INIT(sample_fetches.list)
Emeric Brun107ca302010-01-04 16:16:05 +010050};
51
Willy Tarreau12785782012-04-27 21:37:17 +020052/* list head of all known sample format conversion keywords */
53static struct sample_conv_kw_list sample_convs = {
54 .list = LIST_HEAD_INIT(sample_convs.list)
Emeric Brun107ca302010-01-04 16:16:05 +010055};
56
Willy Tarreau80aca902013-01-07 15:42:20 +010057const unsigned int fetch_cap[SMP_SRC_ENTRIES] = {
58 [SMP_SRC_INTRN] = (SMP_VAL_FE_CON_ACC | SMP_VAL_FE_SES_ACC | SMP_VAL_FE_REQ_CNT |
59 SMP_VAL_FE_HRQ_HDR | SMP_VAL_FE_HRQ_BDY | SMP_VAL_FE_SET_BCK |
60 SMP_VAL_BE_REQ_CNT | SMP_VAL_BE_HRQ_HDR | SMP_VAL_BE_HRQ_BDY |
61 SMP_VAL_BE_SET_SRV | SMP_VAL_BE_SRV_CON | SMP_VAL_BE_RES_CNT |
62 SMP_VAL_BE_HRS_HDR | SMP_VAL_BE_HRS_BDY | SMP_VAL_BE_STO_RUL |
63 SMP_VAL_FE_RES_CNT | SMP_VAL_FE_HRS_HDR | SMP_VAL_FE_HRS_BDY |
64 SMP_VAL_FE_LOG_END),
65
66 [SMP_SRC_LISTN] = (SMP_VAL_FE_CON_ACC | SMP_VAL_FE_SES_ACC | SMP_VAL_FE_REQ_CNT |
67 SMP_VAL_FE_HRQ_HDR | SMP_VAL_FE_HRQ_BDY | SMP_VAL_FE_SET_BCK |
68 SMP_VAL_BE_REQ_CNT | SMP_VAL_BE_HRQ_HDR | SMP_VAL_BE_HRQ_BDY |
69 SMP_VAL_BE_SET_SRV | SMP_VAL_BE_SRV_CON | SMP_VAL_BE_RES_CNT |
70 SMP_VAL_BE_HRS_HDR | SMP_VAL_BE_HRS_BDY | SMP_VAL_BE_STO_RUL |
71 SMP_VAL_FE_RES_CNT | SMP_VAL_FE_HRS_HDR | SMP_VAL_FE_HRS_BDY |
72 SMP_VAL_FE_LOG_END),
73
74 [SMP_SRC_FTEND] = (SMP_VAL_FE_CON_ACC | SMP_VAL_FE_SES_ACC | SMP_VAL_FE_REQ_CNT |
75 SMP_VAL_FE_HRQ_HDR | SMP_VAL_FE_HRQ_BDY | SMP_VAL_FE_SET_BCK |
76 SMP_VAL_BE_REQ_CNT | SMP_VAL_BE_HRQ_HDR | SMP_VAL_BE_HRQ_BDY |
77 SMP_VAL_BE_SET_SRV | SMP_VAL_BE_SRV_CON | SMP_VAL_BE_RES_CNT |
78 SMP_VAL_BE_HRS_HDR | SMP_VAL_BE_HRS_BDY | SMP_VAL_BE_STO_RUL |
79 SMP_VAL_FE_RES_CNT | SMP_VAL_FE_HRS_HDR | SMP_VAL_FE_HRS_BDY |
80 SMP_VAL_FE_LOG_END),
81
82 [SMP_SRC_L4CLI] = (SMP_VAL_FE_CON_ACC | SMP_VAL_FE_SES_ACC | SMP_VAL_FE_REQ_CNT |
83 SMP_VAL_FE_HRQ_HDR | SMP_VAL_FE_HRQ_BDY | SMP_VAL_FE_SET_BCK |
84 SMP_VAL_BE_REQ_CNT | SMP_VAL_BE_HRQ_HDR | SMP_VAL_BE_HRQ_BDY |
85 SMP_VAL_BE_SET_SRV | SMP_VAL_BE_SRV_CON | SMP_VAL_BE_RES_CNT |
86 SMP_VAL_BE_HRS_HDR | SMP_VAL_BE_HRS_BDY | SMP_VAL_BE_STO_RUL |
87 SMP_VAL_FE_RES_CNT | SMP_VAL_FE_HRS_HDR | SMP_VAL_FE_HRS_BDY |
88 SMP_VAL_FE_LOG_END),
89
90 [SMP_SRC_L5CLI] = (SMP_VAL___________ | SMP_VAL_FE_SES_ACC | SMP_VAL_FE_REQ_CNT |
91 SMP_VAL_FE_HRQ_HDR | SMP_VAL_FE_HRQ_BDY | SMP_VAL_FE_SET_BCK |
92 SMP_VAL_BE_REQ_CNT | SMP_VAL_BE_HRQ_HDR | SMP_VAL_BE_HRQ_BDY |
93 SMP_VAL_BE_SET_SRV | SMP_VAL_BE_SRV_CON | SMP_VAL_BE_RES_CNT |
94 SMP_VAL_BE_HRS_HDR | SMP_VAL_BE_HRS_BDY | SMP_VAL_BE_STO_RUL |
95 SMP_VAL_FE_RES_CNT | SMP_VAL_FE_HRS_HDR | SMP_VAL_FE_HRS_BDY |
96 SMP_VAL_FE_LOG_END),
97
98 [SMP_SRC_TRACK] = (SMP_VAL_FE_CON_ACC | SMP_VAL_FE_SES_ACC | SMP_VAL_FE_REQ_CNT |
99 SMP_VAL_FE_HRQ_HDR | SMP_VAL_FE_HRQ_BDY | SMP_VAL_FE_SET_BCK |
100 SMP_VAL_BE_REQ_CNT | SMP_VAL_BE_HRQ_HDR | SMP_VAL_BE_HRQ_BDY |
101 SMP_VAL_BE_SET_SRV | SMP_VAL_BE_SRV_CON | SMP_VAL_BE_RES_CNT |
102 SMP_VAL_BE_HRS_HDR | SMP_VAL_BE_HRS_BDY | SMP_VAL_BE_STO_RUL |
103 SMP_VAL_FE_RES_CNT | SMP_VAL_FE_HRS_HDR | SMP_VAL_FE_HRS_BDY |
104 SMP_VAL_FE_LOG_END),
105
106 [SMP_SRC_L6REQ] = (SMP_VAL___________ | SMP_VAL___________ | SMP_VAL_FE_REQ_CNT |
107 SMP_VAL_FE_HRQ_HDR | SMP_VAL_FE_HRQ_BDY | SMP_VAL_FE_SET_BCK |
108 SMP_VAL_BE_REQ_CNT | SMP_VAL_BE_HRQ_HDR | SMP_VAL_BE_HRQ_BDY |
109 SMP_VAL_BE_SET_SRV | SMP_VAL_BE_SRV_CON | SMP_VAL___________ |
110 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
111 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
112 SMP_VAL___________),
113
114 [SMP_SRC_HRQHV] = (SMP_VAL___________ | SMP_VAL___________ | SMP_VAL_FE_REQ_CNT |
115 SMP_VAL_FE_HRQ_HDR | SMP_VAL_FE_HRQ_BDY | SMP_VAL_FE_SET_BCK |
116 SMP_VAL_BE_REQ_CNT | SMP_VAL_BE_HRQ_HDR | SMP_VAL_BE_HRQ_BDY |
117 SMP_VAL_BE_SET_SRV | SMP_VAL_BE_SRV_CON | SMP_VAL___________ |
118 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
119 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
120 SMP_VAL___________),
121
122 [SMP_SRC_HRQHP] = (SMP_VAL___________ | SMP_VAL___________ | SMP_VAL_FE_REQ_CNT |
123 SMP_VAL_FE_HRQ_HDR | SMP_VAL_FE_HRQ_BDY | SMP_VAL_FE_SET_BCK |
124 SMP_VAL_BE_REQ_CNT | SMP_VAL_BE_HRQ_HDR | SMP_VAL_BE_HRQ_BDY |
125 SMP_VAL_BE_SET_SRV | SMP_VAL_BE_SRV_CON | SMP_VAL_BE_RES_CNT |
126 SMP_VAL_BE_HRS_HDR | SMP_VAL_BE_HRS_BDY | SMP_VAL_BE_STO_RUL |
127 SMP_VAL_FE_RES_CNT | SMP_VAL_FE_HRS_HDR | SMP_VAL_FE_HRS_BDY |
128 SMP_VAL_FE_LOG_END),
129
130 [SMP_SRC_HRQBO] = (SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
131 SMP_VAL___________ | SMP_VAL_FE_HRQ_BDY | SMP_VAL_FE_SET_BCK |
132 SMP_VAL_BE_REQ_CNT | SMP_VAL_BE_HRQ_HDR | SMP_VAL_BE_HRQ_BDY |
133 SMP_VAL_BE_SET_SRV | SMP_VAL_BE_SRV_CON | SMP_VAL___________ |
134 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
135 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
136 SMP_VAL___________),
137
138 [SMP_SRC_BKEND] = (SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
139 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
140 SMP_VAL_BE_REQ_CNT | SMP_VAL_BE_HRQ_HDR | SMP_VAL_BE_HRQ_BDY |
141 SMP_VAL_BE_SET_SRV | SMP_VAL_BE_SRV_CON | SMP_VAL_BE_RES_CNT |
142 SMP_VAL_BE_HRS_HDR | SMP_VAL_BE_HRS_BDY | SMP_VAL_BE_STO_RUL |
143 SMP_VAL_FE_RES_CNT | SMP_VAL_FE_HRS_HDR | SMP_VAL_FE_HRS_BDY |
144 SMP_VAL_FE_LOG_END),
145
146 [SMP_SRC_SERVR] = (SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
147 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
148 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
149 SMP_VAL___________ | SMP_VAL_BE_SRV_CON | SMP_VAL_BE_RES_CNT |
150 SMP_VAL_BE_HRS_HDR | SMP_VAL_BE_HRS_BDY | SMP_VAL_BE_STO_RUL |
151 SMP_VAL_FE_RES_CNT | SMP_VAL_FE_HRS_HDR | SMP_VAL_FE_HRS_BDY |
152 SMP_VAL_FE_LOG_END),
153
154 [SMP_SRC_L4SRV] = (SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
155 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
156 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
157 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL_BE_RES_CNT |
158 SMP_VAL_BE_HRS_HDR | SMP_VAL_BE_HRS_BDY | SMP_VAL_BE_STO_RUL |
159 SMP_VAL_FE_RES_CNT | SMP_VAL_FE_HRS_HDR | SMP_VAL_FE_HRS_BDY |
160 SMP_VAL_FE_LOG_END),
161
162 [SMP_SRC_L5SRV] = (SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
163 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
164 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
165 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL_BE_RES_CNT |
166 SMP_VAL_BE_HRS_HDR | SMP_VAL_BE_HRS_BDY | SMP_VAL_BE_STO_RUL |
167 SMP_VAL_FE_RES_CNT | SMP_VAL_FE_HRS_HDR | SMP_VAL_FE_HRS_BDY |
168 SMP_VAL_FE_LOG_END),
169
170 [SMP_SRC_L6RES] = (SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
171 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
172 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
173 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL_BE_RES_CNT |
174 SMP_VAL_BE_HRS_HDR | SMP_VAL_BE_HRS_BDY | SMP_VAL_BE_STO_RUL |
175 SMP_VAL_FE_RES_CNT | SMP_VAL_FE_HRS_HDR | SMP_VAL_FE_HRS_BDY |
176 SMP_VAL___________),
177
178 [SMP_SRC_HRSHV] = (SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
179 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
180 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
181 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL_BE_RES_CNT |
182 SMP_VAL_BE_HRS_HDR | SMP_VAL_BE_HRS_BDY | SMP_VAL_BE_STO_RUL |
183 SMP_VAL_FE_RES_CNT | SMP_VAL_FE_HRS_HDR | SMP_VAL_FE_HRS_BDY |
184 SMP_VAL___________),
185
186 [SMP_SRC_HRSHP] = (SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
187 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
188 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
189 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL_BE_RES_CNT |
190 SMP_VAL_BE_HRS_HDR | SMP_VAL_BE_HRS_BDY | SMP_VAL_BE_STO_RUL |
191 SMP_VAL_FE_RES_CNT | SMP_VAL_FE_HRS_HDR | SMP_VAL_FE_HRS_BDY |
192 SMP_VAL_FE_LOG_END),
193
194 [SMP_SRC_HRSBO] = (SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
195 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
196 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
197 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
198 SMP_VAL___________ | SMP_VAL_BE_HRS_BDY | SMP_VAL_BE_STO_RUL |
199 SMP_VAL_FE_RES_CNT | SMP_VAL_FE_HRS_HDR | SMP_VAL_FE_HRS_BDY |
200 SMP_VAL___________),
201
202 [SMP_SRC_RQFIN] = (SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
203 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
204 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
205 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
206 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
207 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
208 SMP_VAL_FE_LOG_END),
209
210 [SMP_SRC_RSFIN] = (SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
211 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
212 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
213 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
214 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
215 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
216 SMP_VAL_FE_LOG_END),
217
218 [SMP_SRC_TXFIN] = (SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
219 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
220 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
221 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
222 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
223 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
224 SMP_VAL_FE_LOG_END),
225
226 [SMP_SRC_SSFIN] = (SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
227 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
228 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
229 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
230 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
231 SMP_VAL___________ | SMP_VAL___________ | SMP_VAL___________ |
232 SMP_VAL_FE_LOG_END),
233};
234
235static const char *fetch_src_names[SMP_SRC_ENTRIES] = {
236 [SMP_SRC_INTRN] = "internal state",
237 [SMP_SRC_LISTN] = "listener",
238 [SMP_SRC_FTEND] = "frontend",
239 [SMP_SRC_L4CLI] = "client address",
240 [SMP_SRC_L5CLI] = "client-side connection",
241 [SMP_SRC_TRACK] = "track counters",
242 [SMP_SRC_L6REQ] = "request buffer",
243 [SMP_SRC_HRQHV] = "HTTP request headers",
244 [SMP_SRC_HRQHP] = "HTTP request",
245 [SMP_SRC_HRQBO] = "HTTP request body",
246 [SMP_SRC_BKEND] = "backend",
247 [SMP_SRC_SERVR] = "server",
248 [SMP_SRC_L4SRV] = "server address",
249 [SMP_SRC_L5SRV] = "server-side connection",
250 [SMP_SRC_L6RES] = "response buffer",
251 [SMP_SRC_HRSHV] = "HTTP response headers",
252 [SMP_SRC_HRSHP] = "HTTP response",
253 [SMP_SRC_HRSBO] = "HTTP response body",
254 [SMP_SRC_RQFIN] = "request buffer statistics",
255 [SMP_SRC_RSFIN] = "response buffer statistics",
256 [SMP_SRC_TXFIN] = "transaction statistics",
257 [SMP_SRC_SSFIN] = "session statistics",
258};
259
Willy Tarreaubf8e2512013-03-25 14:52:41 +0100260static const char *fetch_ckp_names[SMP_CKP_ENTRIES] = {
261 [SMP_CKP_FE_CON_ACC] = "frontend tcp-request connection rule",
262 [SMP_CKP_FE_SES_ACC] = "frontend tcp-request session rule",
263 [SMP_CKP_FE_REQ_CNT] = "frontend tcp-request content rule",
264 [SMP_CKP_FE_HRQ_HDR] = "frontend http-request header rule",
265 [SMP_CKP_FE_HRQ_BDY] = "frontend http-request body rule",
266 [SMP_CKP_FE_SET_BCK] = "frontend use-backend rule",
267 [SMP_CKP_BE_REQ_CNT] = "backend tcp-request content rule",
268 [SMP_CKP_BE_HRQ_HDR] = "backend http-request header rule",
269 [SMP_CKP_BE_HRQ_BDY] = "backend http-request body rule",
270 [SMP_CKP_BE_SET_SRV] = "backend use-server, balance or stick-match rule",
271 [SMP_CKP_BE_SRV_CON] = "server source selection",
272 [SMP_CKP_BE_RES_CNT] = "backend tcp-response content rule",
273 [SMP_CKP_BE_HRS_HDR] = "backend http-response header rule",
274 [SMP_CKP_BE_HRS_BDY] = "backend http-response body rule",
275 [SMP_CKP_BE_STO_RUL] = "backend stick-store rule",
276 [SMP_CKP_FE_RES_CNT] = "frontend tcp-response content rule",
277 [SMP_CKP_FE_HRS_HDR] = "frontend http-response header rule",
278 [SMP_CKP_FE_HRS_BDY] = "frontend http-response body rule",
279 [SMP_CKP_FE_LOG_END] = "logs",
280};
281
Thierry FOURNIER348971e2013-11-21 10:50:10 +0100282/* This function returns the type of the data returned by the sample_expr.
283 * It assumes that the <expr> and all of its converters are properly
284 * initialized.
285 */
286inline
287int smp_expr_output_type(struct sample_expr *expr)
288{
289 struct sample_conv_expr *smp_expr;
290
291 if (!LIST_ISEMPTY(&expr->conv_exprs)) {
292 smp_expr = LIST_PREV(&expr->conv_exprs, struct sample_conv_expr *, list);
293 return smp_expr->conv->out_type;
294 }
295 return expr->fetch->out_type;
296}
297
298
Willy Tarreau80aca902013-01-07 15:42:20 +0100299/* fill the trash with a comma-delimited list of source names for the <use> bit
300 * field which must be composed of a non-null set of SMP_USE_* flags. The return
301 * value is the pointer to the string in the trash buffer.
302 */
303const char *sample_src_names(unsigned int use)
304{
305 int bit;
306
307 trash.len = 0;
308 trash.str[0] = '\0';
309 for (bit = 0; bit < SMP_SRC_ENTRIES; bit++) {
310 if (!(use & ~((1 << bit) - 1)))
311 break; /* no more bits */
312
313 if (!(use & (1 << bit)))
314 continue; /* bit not set */
315
316 trash.len += snprintf(trash.str + trash.len, trash.size - trash.len, "%s%s",
317 (use & ((1 << bit) - 1)) ? "," : "",
318 fetch_src_names[bit]);
319 }
320 return trash.str;
321}
322
Willy Tarreaubf8e2512013-03-25 14:52:41 +0100323/* return a pointer to the correct sample checkpoint name, or "unknown" when
324 * the flags are invalid. Only the lowest bit is used, higher bits are ignored
325 * if set.
326 */
327const char *sample_ckp_names(unsigned int use)
328{
329 int bit;
330
331 for (bit = 0; bit < SMP_CKP_ENTRIES; bit++)
332 if (use & (1 << bit))
333 return fetch_ckp_names[bit];
334 return "unknown sample check place, please report this bug";
335}
336
Emeric Brun107ca302010-01-04 16:16:05 +0100337/*
Willy Tarreau80aca902013-01-07 15:42:20 +0100338 * Registers the sample fetch keyword list <kwl> as a list of valid keywords
339 * for next parsing sessions. The fetch keywords capabilities are also computed
340 * from their ->use field.
Emeric Brun107ca302010-01-04 16:16:05 +0100341 */
Willy Tarreau80aca902013-01-07 15:42:20 +0100342void sample_register_fetches(struct sample_fetch_kw_list *kwl)
Emeric Brun107ca302010-01-04 16:16:05 +0100343{
Willy Tarreau80aca902013-01-07 15:42:20 +0100344 struct sample_fetch *sf;
345 int bit;
346
347 for (sf = kwl->kw; sf->kw != NULL; sf++) {
348 for (bit = 0; bit < SMP_SRC_ENTRIES; bit++)
349 if (sf->use & (1 << bit))
350 sf->val |= fetch_cap[bit];
351 }
352 LIST_ADDQ(&sample_fetches.list, &kwl->list);
Emeric Brun107ca302010-01-04 16:16:05 +0100353}
354
355/*
Willy Tarreau12785782012-04-27 21:37:17 +0200356 * Registers the sample format coverstion keyword list <pckl> as a list of valid keywords for next
Emeric Brun107ca302010-01-04 16:16:05 +0100357 * parsing sessions.
358 */
Willy Tarreau12785782012-04-27 21:37:17 +0200359void sample_register_convs(struct sample_conv_kw_list *pckl)
Emeric Brun107ca302010-01-04 16:16:05 +0100360{
Willy Tarreau12785782012-04-27 21:37:17 +0200361 LIST_ADDQ(&sample_convs.list, &pckl->list);
Emeric Brun107ca302010-01-04 16:16:05 +0100362}
363
364/*
Willy Tarreau12785782012-04-27 21:37:17 +0200365 * Returns the pointer on sample fetch keyword structure identified by
Emeric Brun107ca302010-01-04 16:16:05 +0100366 * string of <len> in buffer <kw>.
367 *
368 */
Willy Tarreau12785782012-04-27 21:37:17 +0200369struct sample_fetch *find_sample_fetch(const char *kw, int len)
Emeric Brun107ca302010-01-04 16:16:05 +0100370{
371 int index;
Willy Tarreau12785782012-04-27 21:37:17 +0200372 struct sample_fetch_kw_list *kwl;
Emeric Brun107ca302010-01-04 16:16:05 +0100373
Willy Tarreau12785782012-04-27 21:37:17 +0200374 list_for_each_entry(kwl, &sample_fetches.list, list) {
Emeric Brun107ca302010-01-04 16:16:05 +0100375 for (index = 0; kwl->kw[index].kw != NULL; index++) {
376 if (strncmp(kwl->kw[index].kw, kw, len) == 0 &&
377 kwl->kw[index].kw[len] == '\0')
378 return &kwl->kw[index];
379 }
380 }
381 return NULL;
382}
383
384/*
Willy Tarreau12785782012-04-27 21:37:17 +0200385 * Returns the pointer on sample format conversion keyword structure identified by
Emeric Brun107ca302010-01-04 16:16:05 +0100386 * string of <len> in buffer <kw>.
387 *
388 */
Willy Tarreau12785782012-04-27 21:37:17 +0200389struct sample_conv *find_sample_conv(const char *kw, int len)
Emeric Brun107ca302010-01-04 16:16:05 +0100390{
391 int index;
Willy Tarreau12785782012-04-27 21:37:17 +0200392 struct sample_conv_kw_list *kwl;
Emeric Brun107ca302010-01-04 16:16:05 +0100393
Willy Tarreau12785782012-04-27 21:37:17 +0200394 list_for_each_entry(kwl, &sample_convs.list, list) {
Emeric Brun107ca302010-01-04 16:16:05 +0100395 for (index = 0; kwl->kw[index].kw != NULL; index++) {
396 if (strncmp(kwl->kw[index].kw, kw, len) == 0 &&
397 kwl->kw[index].kw[len] == '\0')
398 return &kwl->kw[index];
399 }
400 }
401 return NULL;
402}
403
Emeric Brun107ca302010-01-04 16:16:05 +0100404/******************************************************************/
Willy Tarreau12785782012-04-27 21:37:17 +0200405/* Sample casts functions */
Willy Tarreaub8c8f1f2012-04-23 22:38:26 +0200406/* Note: these functions do *NOT* set the output type on the */
407/* sample, the caller is responsible for doing this on return. */
Emeric Brun107ca302010-01-04 16:16:05 +0100408/******************************************************************/
409
Willy Tarreau342acb42012-04-23 22:03:39 +0200410static int c_ip2int(struct sample *smp)
Emeric Brun107ca302010-01-04 16:16:05 +0100411{
Willy Tarreau342acb42012-04-23 22:03:39 +0200412 smp->data.uint = ntohl(smp->data.ipv4.s_addr);
Thierry FOURNIERb805f712013-11-26 20:47:54 +0100413 smp->type = SMP_T_UINT;
Emeric Brun107ca302010-01-04 16:16:05 +0100414 return 1;
415}
416
Willy Tarreau342acb42012-04-23 22:03:39 +0200417static int c_ip2str(struct sample *smp)
Emeric Brun107ca302010-01-04 16:16:05 +0100418{
Willy Tarreau47ca5452012-12-23 20:22:19 +0100419 struct chunk *trash = get_trash_chunk();
Emeric Brun107ca302010-01-04 16:16:05 +0100420
Willy Tarreau342acb42012-04-23 22:03:39 +0200421 if (!inet_ntop(AF_INET, (void *)&smp->data.ipv4, trash->str, trash->size))
Emeric Brun107ca302010-01-04 16:16:05 +0100422 return 0;
423
424 trash->len = strlen(trash->str);
Willy Tarreau342acb42012-04-23 22:03:39 +0200425 smp->data.str = *trash;
Thierry FOURNIERb805f712013-11-26 20:47:54 +0100426 smp->type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +0100427 smp->flags &= ~SMP_F_CONST;
Emeric Brun107ca302010-01-04 16:16:05 +0100428
429 return 1;
430}
431
Willy Tarreau342acb42012-04-23 22:03:39 +0200432static int c_ip2ipv6(struct sample *smp)
David du Colombier4f92d322011-03-24 11:09:31 +0100433{
Willy Tarreau342acb42012-04-23 22:03:39 +0200434 v4tov6(&smp->data.ipv6, &smp->data.ipv4);
Thierry FOURNIERb805f712013-11-26 20:47:54 +0100435 smp->type = SMP_T_IPV6;
David du Colombier4f92d322011-03-24 11:09:31 +0100436 return 1;
437}
438
Willy Tarreau342acb42012-04-23 22:03:39 +0200439static int c_ipv62str(struct sample *smp)
David du Colombier4f92d322011-03-24 11:09:31 +0100440{
Willy Tarreau47ca5452012-12-23 20:22:19 +0100441 struct chunk *trash = get_trash_chunk();
David du Colombier4f92d322011-03-24 11:09:31 +0100442
Willy Tarreau342acb42012-04-23 22:03:39 +0200443 if (!inet_ntop(AF_INET6, (void *)&smp->data.ipv6, trash->str, trash->size))
David du Colombier4f92d322011-03-24 11:09:31 +0100444 return 0;
445
446 trash->len = strlen(trash->str);
Willy Tarreau342acb42012-04-23 22:03:39 +0200447 smp->data.str = *trash;
Thierry FOURNIERb805f712013-11-26 20:47:54 +0100448 smp->type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +0100449 smp->flags &= ~SMP_F_CONST;
David du Colombier4f92d322011-03-24 11:09:31 +0100450 return 1;
451}
452
453/*
Willy Tarreau342acb42012-04-23 22:03:39 +0200454static int c_ipv62ip(struct sample *smp)
David du Colombier4f92d322011-03-24 11:09:31 +0100455{
Willy Tarreau342acb42012-04-23 22:03:39 +0200456 return v6tov4(&smp->data.ipv4, &smp->data.ipv6);
David du Colombier4f92d322011-03-24 11:09:31 +0100457}
458*/
459
Willy Tarreau342acb42012-04-23 22:03:39 +0200460static int c_int2ip(struct sample *smp)
Emeric Brun107ca302010-01-04 16:16:05 +0100461{
Willy Tarreau342acb42012-04-23 22:03:39 +0200462 smp->data.ipv4.s_addr = htonl(smp->data.uint);
Thierry FOURNIERb805f712013-11-26 20:47:54 +0100463 smp->type = SMP_T_IPV4;
Emeric Brun107ca302010-01-04 16:16:05 +0100464 return 1;
465}
466
Thierry FOURNIERb805f712013-11-26 20:47:54 +0100467static int c_str2addr(struct sample *smp)
468{
Thierry FOURNIERb805f712013-11-26 20:47:54 +0100469 if (!buf2ip(smp->data.str.str, smp->data.str.len, &smp->data.ipv4)) {
Thierry FOURNIERfd139902013-12-11 12:38:57 +0100470 if (!buf2ip6(smp->data.str.str, smp->data.str.len, &smp->data.ipv6))
471 return 0;
472 smp->type = SMP_T_IPV6;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +0100473 smp->flags &= ~SMP_F_CONST;
Thierry FOURNIERfd139902013-12-11 12:38:57 +0100474 return 1;
Thierry FOURNIERb805f712013-11-26 20:47:54 +0100475 }
476 smp->type = SMP_T_IPV4;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +0100477 smp->flags &= ~SMP_F_CONST;
Thierry FOURNIERb805f712013-11-26 20:47:54 +0100478 return 1;
479}
480
Willy Tarreau342acb42012-04-23 22:03:39 +0200481static int c_str2ip(struct sample *smp)
Emeric Brun107ca302010-01-04 16:16:05 +0100482{
Willy Tarreau342acb42012-04-23 22:03:39 +0200483 if (!buf2ip(smp->data.str.str, smp->data.str.len, &smp->data.ipv4))
Emeric Brun107ca302010-01-04 16:16:05 +0100484 return 0;
Thierry FOURNIERb805f712013-11-26 20:47:54 +0100485 smp->type = SMP_T_IPV4;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +0100486 smp->flags &= ~SMP_F_CONST;
Emeric Brun107ca302010-01-04 16:16:05 +0100487 return 1;
488}
489
Willy Tarreau342acb42012-04-23 22:03:39 +0200490static int c_str2ipv6(struct sample *smp)
David du Colombier4f92d322011-03-24 11:09:31 +0100491{
Thierry FOURNIERfd139902013-12-11 12:38:57 +0100492 if (!buf2ip6(smp->data.str.str, smp->data.str.len, &smp->data.ipv6))
493 return 0;
494 smp->type = SMP_T_IPV6;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +0100495 smp->flags &= ~SMP_F_CONST;
Thierry FOURNIERfd139902013-12-11 12:38:57 +0100496 return 1;
David du Colombier4f92d322011-03-24 11:09:31 +0100497}
498
Thierry FOURNIERe87cac12014-03-12 15:07:59 +0100499/* The sample is always copied into a new one so that smp->size is always
500 * valid. The NULL char always enforces the end of string if it is met.
501 */
Emeric Brun8ac33d92012-10-17 13:36:06 +0200502static int c_bin2str(struct sample *smp)
503{
Willy Tarreau47ca5452012-12-23 20:22:19 +0100504 struct chunk *trash = get_trash_chunk();
Emeric Brun8ac33d92012-10-17 13:36:06 +0200505 unsigned char c;
506 int ptr = 0;
507
Thierry FOURNIERe87cac12014-03-12 15:07:59 +0100508 while (ptr < smp->data.str.len) {
509 c = smp->data.str.str[ptr];
510 if (!c)
511 break;
512 trash->str[ptr] = c;
513 ptr++;
Emeric Brun8ac33d92012-10-17 13:36:06 +0200514 }
Thierry FOURNIERe87cac12014-03-12 15:07:59 +0100515 trash->len = ptr;
516 trash->str[ptr] = 0;
Emeric Brun8ac33d92012-10-17 13:36:06 +0200517 smp->data.str = *trash;
Thierry FOURNIERb805f712013-11-26 20:47:54 +0100518 smp->type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +0100519 smp->flags &= ~SMP_F_CONST;
Emeric Brun8ac33d92012-10-17 13:36:06 +0200520 return 1;
521}
522
Willy Tarreau342acb42012-04-23 22:03:39 +0200523static int c_int2str(struct sample *smp)
Emeric Brun107ca302010-01-04 16:16:05 +0100524{
Willy Tarreau47ca5452012-12-23 20:22:19 +0100525 struct chunk *trash = get_trash_chunk();
Emeric Brun107ca302010-01-04 16:16:05 +0100526 char *pos;
527
Willy Tarreau342acb42012-04-23 22:03:39 +0200528 pos = ultoa_r(smp->data.uint, trash->str, trash->size);
Emeric Brun107ca302010-01-04 16:16:05 +0100529
530 if (!pos)
531 return 0;
532
Emeric Brun485479d2010-09-23 18:02:19 +0200533 trash->size = trash->size - (pos - trash->str);
Emeric Brun107ca302010-01-04 16:16:05 +0100534 trash->str = pos;
535 trash->len = strlen(pos);
Willy Tarreau342acb42012-04-23 22:03:39 +0200536 smp->data.str = *trash;
Thierry FOURNIERb805f712013-11-26 20:47:54 +0100537 smp->type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +0100538 smp->flags &= ~SMP_F_CONST;
Emeric Brun107ca302010-01-04 16:16:05 +0100539 return 1;
540}
541
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +0100542/* This function duplicates data and removes the flag "const". */
543int smp_dup(struct sample *smp)
Emeric Brun485479d2010-09-23 18:02:19 +0200544{
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +0100545 struct chunk *trash;
Emeric Brun485479d2010-09-23 18:02:19 +0200546
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +0100547 /* If the const flag is not set, we don't need to duplicate the
548 * pattern as it can be modified in place.
549 */
550 if (!(smp->flags & SMP_F_CONST))
551 return 1;
Thierry FOURNIERb805f712013-11-26 20:47:54 +0100552
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +0100553 switch (smp->type) {
554 case SMP_T_BOOL:
555 case SMP_T_UINT:
556 case SMP_T_SINT:
557 case SMP_T_ADDR:
558 case SMP_T_IPV4:
559 case SMP_T_IPV6:
560 /* These type are not const. */
561 break;
562 case SMP_T_STR:
563 case SMP_T_BIN:
564 /* Duplicate data. */
565 trash = get_trash_chunk();
566 trash->len = smp->data.str.len < trash->size ? smp->data.str.len : trash->size;
567 memcpy(trash->str, smp->data.str.str, trash->len);
568 smp->data.str = *trash;
569 break;
570 default:
571 /* Other cases are unexpected. */
572 return 0;
573 }
Thierry FOURNIERb805f712013-11-26 20:47:54 +0100574
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +0100575 /* remove const flag */
576 smp->flags &= ~SMP_F_CONST;
Emeric Brun485479d2010-09-23 18:02:19 +0200577 return 1;
578}
579
Thierry FOURNIER0e9af552013-12-14 14:55:04 +0100580int c_none(struct sample *smp)
Emeric Brun107ca302010-01-04 16:16:05 +0100581{
582 return 1;
583}
584
Willy Tarreau342acb42012-04-23 22:03:39 +0200585static int c_str2int(struct sample *smp)
Emeric Brun107ca302010-01-04 16:16:05 +0100586{
587 int i;
588 uint32_t ret = 0;
589
Thierry FOURNIER60bb0202014-01-27 18:20:48 +0100590 if (smp->data.str.len == 0)
591 return 0;
592
Willy Tarreau342acb42012-04-23 22:03:39 +0200593 for (i = 0; i < smp->data.str.len; i++) {
594 uint32_t val = smp->data.str.str[i] - '0';
Emeric Brun107ca302010-01-04 16:16:05 +0100595
Thierry FOURNIER60bb0202014-01-27 18:20:48 +0100596 if (val > 9) {
597 if (i == 0)
598 return 0;
Emeric Brun107ca302010-01-04 16:16:05 +0100599 break;
Thierry FOURNIER60bb0202014-01-27 18:20:48 +0100600 }
Emeric Brun107ca302010-01-04 16:16:05 +0100601
602 ret = ret * 10 + val;
603 }
604
Willy Tarreau342acb42012-04-23 22:03:39 +0200605 smp->data.uint = ret;
Thierry FOURNIERb805f712013-11-26 20:47:54 +0100606 smp->type = SMP_T_UINT;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +0100607 smp->flags &= ~SMP_F_CONST;
Emeric Brun107ca302010-01-04 16:16:05 +0100608 return 1;
609}
610
Thierry FOURNIERd4373142013-12-17 01:10:10 +0100611static int c_str2meth(struct sample *smp)
612{
613 enum http_meth_t meth;
614 int len;
615
616 meth = find_http_meth(smp->data.str.str, smp->data.str.len);
617 if (meth == HTTP_METH_OTHER) {
618 len = smp->data.str.len;
619 smp->data.meth.str.str = smp->data.str.str;
620 smp->data.meth.str.len = len;
621 }
622 else
623 smp->flags &= ~SMP_F_CONST;
624 smp->data.meth.meth = meth;
625 smp->type = SMP_T_METH;
626 return 1;
627}
628
629static int c_meth2str(struct sample *smp)
630{
631 int len;
632 enum http_meth_t meth;
633
634 if (smp->data.meth.meth == HTTP_METH_OTHER) {
635 /* The method is unknown. Copy the original pointer. */
636 len = smp->data.meth.str.len;
637 smp->data.str.str = smp->data.meth.str.str;
638 smp->data.str.len = len;
639 smp->type = SMP_T_STR;
640 }
641 else if (smp->data.meth.meth < HTTP_METH_OTHER) {
642 /* The method is known, copy the pointer containing the string. */
643 meth = smp->data.meth.meth;
644 smp->data.str.str = http_known_methods[meth].name;
645 smp->data.str.len = http_known_methods[meth].len;
646 smp->flags |= SMP_F_CONST;
647 smp->type = SMP_T_STR;
648 }
649 else {
650 /* Unknown method */
651 return 0;
652 }
653 return 1;
654}
655
Emeric Brun107ca302010-01-04 16:16:05 +0100656/*****************************************************************/
Willy Tarreau12785782012-04-27 21:37:17 +0200657/* Sample casts matrix: */
658/* sample_casts[from type][to type] */
659/* NULL pointer used for impossible sample casts */
Emeric Brun107ca302010-01-04 16:16:05 +0100660/*****************************************************************/
Emeric Brun107ca302010-01-04 16:16:05 +0100661
Thierry FOURNIER8af6ff12013-11-21 10:53:12 +0100662sample_cast_fct sample_casts[SMP_TYPES][SMP_TYPES] = {
Thierry FOURNIERd4373142013-12-17 01:10:10 +0100663/* to: BOOL UINT SINT ADDR IPV4 IPV6 STR BIN METH */
664/* from: BOOL */ { c_none, c_none, c_none, NULL, NULL, NULL, c_int2str, NULL, NULL, },
665/* UINT */ { c_none, c_none, c_none, c_int2ip, c_int2ip, NULL, c_int2str, NULL, NULL, },
666/* SINT */ { c_none, c_none, c_none, c_int2ip, c_int2ip, NULL, c_int2str, NULL, NULL, },
667/* ADDR */ { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, },
668/* IPV4 */ { NULL, c_ip2int, c_ip2int, c_none, c_none, c_ip2ipv6, c_ip2str, NULL, NULL, },
669/* IPV6 */ { NULL, NULL, NULL, c_none, NULL, c_none, c_ipv62str, NULL, NULL, },
670/* STR */ { c_str2int, c_str2int, c_str2int, c_str2addr, c_str2ip, c_str2ipv6, c_none, c_none, c_str2meth, },
671/* BIN */ { NULL, NULL, NULL, NULL, NULL, NULL, c_bin2str, c_none, c_str2meth, },
672/* METH */ { NULL, NULL, NULL, NULL, NULL, NULL, c_meth2str, c_meth2str, c_none, },
Willy Tarreauf0b38bf2010-06-06 13:22:23 +0200673};
Emeric Brun107ca302010-01-04 16:16:05 +0100674
Emeric Brun107ca302010-01-04 16:16:05 +0100675/*
Willy Tarreau12785782012-04-27 21:37:17 +0200676 * Parse a sample expression configuration:
Emeric Brun107ca302010-01-04 16:16:05 +0100677 * fetch keyword followed by format conversion keywords.
Willy Tarreau12785782012-04-27 21:37:17 +0200678 * Returns a pointer on allocated sample expression structure.
Willy Tarreaua4312fa2013-04-02 16:34:32 +0200679 * The caller must have set al->ctx.
Emeric Brun107ca302010-01-04 16:16:05 +0100680 */
Willy Tarreau975c1782013-12-12 23:16:54 +0100681struct sample_expr *sample_parse_expr(char **str, int *idx, char **err_msg, struct arg_list *al)
Emeric Brun107ca302010-01-04 16:16:05 +0100682{
Willy Tarreau833cc792013-07-24 15:34:19 +0200683 const char *begw; /* beginning of word */
684 const char *endw; /* end of word */
685 const char *endt; /* end of term */
Willy Tarreau12785782012-04-27 21:37:17 +0200686 struct sample_expr *expr;
687 struct sample_fetch *fetch;
688 struct sample_conv *conv;
Emeric Brun107ca302010-01-04 16:16:05 +0100689 unsigned long prev_type;
Willy Tarreau833cc792013-07-24 15:34:19 +0200690 char *fkw = NULL;
691 char *ckw = NULL;
Willy Tarreau689a1df2013-12-13 00:40:11 +0100692 int err_arg;
Emeric Brun107ca302010-01-04 16:16:05 +0100693
Willy Tarreau833cc792013-07-24 15:34:19 +0200694 begw = str[*idx];
695 for (endw = begw; *endw && *endw != '(' && *endw != ','; endw++);
696
697 if (endw == begw) {
Willy Tarreau975c1782013-12-12 23:16:54 +0100698 memprintf(err_msg, "missing fetch method");
Emeric Brun107ca302010-01-04 16:16:05 +0100699 goto out_error;
Emeric Brun485479d2010-09-23 18:02:19 +0200700 }
Emeric Brun107ca302010-01-04 16:16:05 +0100701
Willy Tarreau833cc792013-07-24 15:34:19 +0200702 /* keep a copy of the current fetch keyword for error reporting */
703 fkw = my_strndup(begw, endw - begw);
Emeric Brun107ca302010-01-04 16:16:05 +0100704
Willy Tarreau833cc792013-07-24 15:34:19 +0200705 fetch = find_sample_fetch(begw, endw - begw);
706 if (!fetch) {
Willy Tarreau975c1782013-12-12 23:16:54 +0100707 memprintf(err_msg, "unknown fetch method '%s'", fkw);
Emeric Brun107ca302010-01-04 16:16:05 +0100708 goto out_error;
Emeric Brun485479d2010-09-23 18:02:19 +0200709 }
Emeric Brun107ca302010-01-04 16:16:05 +0100710
Willy Tarreau833cc792013-07-24 15:34:19 +0200711 endt = endw;
712 if (*endt == '(') {
Willy Tarreau689a1df2013-12-13 00:40:11 +0100713 /* look for the end of this term and skip the opening parenthesis */
714 endt = ++endw;
Willy Tarreau833cc792013-07-24 15:34:19 +0200715 while (*endt && *endt != ')')
716 endt++;
717 if (*endt != ')') {
Willy Tarreau975c1782013-12-12 23:16:54 +0100718 memprintf(err_msg, "missing closing ')' after arguments to fetch keyword '%s'", fkw);
Willy Tarreau833cc792013-07-24 15:34:19 +0200719 goto out_error;
Emeric Brun485479d2010-09-23 18:02:19 +0200720 }
Emeric Brun485479d2010-09-23 18:02:19 +0200721 }
Emeric Brun107ca302010-01-04 16:16:05 +0100722
Willy Tarreau833cc792013-07-24 15:34:19 +0200723 /* At this point, we have :
724 * - begw : beginning of the keyword
Willy Tarreau689a1df2013-12-13 00:40:11 +0100725 * - endw : end of the keyword, first character not part of keyword
726 * nor the opening parenthesis (so first character of args
727 * if present).
Willy Tarreau833cc792013-07-24 15:34:19 +0200728 * - endt : end of the term (=endw or last parenthesis if args are present)
729 */
730
731 if (fetch->out_type >= SMP_TYPES) {
Willy Tarreau975c1782013-12-12 23:16:54 +0100732 memprintf(err_msg, "returns type of fetch method '%s' is unknown", fkw);
Emeric Brun107ca302010-01-04 16:16:05 +0100733 goto out_error;
Emeric Brun485479d2010-09-23 18:02:19 +0200734 }
Emeric Brun107ca302010-01-04 16:16:05 +0100735 prev_type = fetch->out_type;
Willy Tarreau833cc792013-07-24 15:34:19 +0200736
Willy Tarreau12785782012-04-27 21:37:17 +0200737 expr = calloc(1, sizeof(struct sample_expr));
Emeric Brun485479d2010-09-23 18:02:19 +0200738 if (!expr)
739 goto out_error;
Emeric Brun107ca302010-01-04 16:16:05 +0100740
741 LIST_INIT(&(expr->conv_exprs));
742 expr->fetch = fetch;
Willy Tarreau2e845be2012-10-19 19:49:09 +0200743 expr->arg_p = empty_arg_list;
Emeric Brun107ca302010-01-04 16:16:05 +0100744
Willy Tarreau689a1df2013-12-13 00:40:11 +0100745 /* Note that we call the argument parser even with an empty string,
746 * this allows it to automatically create entries for mandatory
747 * implicit arguments (eg: local proxy name).
748 */
749 al->kw = expr->fetch->kw;
750 al->conv = NULL;
751 if (make_arg_list(endw, endt - endw, fetch->arg_mask, &expr->arg_p, err_msg, NULL, &err_arg, al) < 0) {
752 memprintf(err_msg, "fetch method '%s' : %s", fkw, *err_msg);
753 goto out_error;
754 }
Willy Tarreau2e845be2012-10-19 19:49:09 +0200755
Willy Tarreau689a1df2013-12-13 00:40:11 +0100756 if (!expr->arg_p) {
757 expr->arg_p = empty_arg_list;
Emeric Brun485479d2010-09-23 18:02:19 +0200758 }
Willy Tarreau689a1df2013-12-13 00:40:11 +0100759 else if (fetch->val_args && !fetch->val_args(expr->arg_p, err_msg)) {
760 memprintf(err_msg, "invalid args in fetch method '%s' : %s", fkw, *err_msg);
Emeric Brun485479d2010-09-23 18:02:19 +0200761 goto out_error;
Emeric Brun107ca302010-01-04 16:16:05 +0100762 }
763
Willy Tarreau833cc792013-07-24 15:34:19 +0200764 /* Now process the converters if any. We have two supported syntaxes
765 * for the converters, which can be combined :
766 * - comma-delimited list of converters just after the keyword and args ;
767 * - one converter per keyword
768 * The combination allows to have each keyword being a comma-delimited
769 * series of converters.
770 *
771 * We want to process the former first, then the latter. For this we start
772 * from the beginning of the supposed place in the exiting conv chain, which
773 * starts at the last comma (endt).
774 */
775
776 while (1) {
Willy Tarreau12785782012-04-27 21:37:17 +0200777 struct sample_conv_expr *conv_expr;
Emeric Brun107ca302010-01-04 16:16:05 +0100778
Willy Tarreau833cc792013-07-24 15:34:19 +0200779 if (*endt == ')') /* skip last closing parenthesis */
780 endt++;
Emeric Brun107ca302010-01-04 16:16:05 +0100781
Willy Tarreau833cc792013-07-24 15:34:19 +0200782 if (*endt && *endt != ',') {
783 if (ckw)
Willy Tarreau975c1782013-12-12 23:16:54 +0100784 memprintf(err_msg, "missing comma after conv keyword '%s'", ckw);
Willy Tarreau833cc792013-07-24 15:34:19 +0200785 else
Willy Tarreau975c1782013-12-12 23:16:54 +0100786 memprintf(err_msg, "missing comma after fetch keyword '%s'", fkw);
Emeric Brun107ca302010-01-04 16:16:05 +0100787 goto out_error;
Emeric Brun485479d2010-09-23 18:02:19 +0200788 }
Emeric Brun107ca302010-01-04 16:16:05 +0100789
Willy Tarreau833cc792013-07-24 15:34:19 +0200790 while (*endt == ',') /* then trailing commas */
791 endt++;
792
793 begw = endt; /* start of conv keyword */
794
795 if (!*begw) {
796 /* none ? skip to next string */
797 (*idx)++;
798 begw = str[*idx];
799 if (!begw || !*begw)
800 break;
801 }
802
803 for (endw = begw; *endw && *endw != '(' && *endw != ','; endw++);
804
805 free(ckw);
806 ckw = my_strndup(begw, endw - begw);
807
808 conv = find_sample_conv(begw, endw - begw);
809 if (!conv) {
810 /* we found an isolated keyword that we don't know, it's not ours */
811 if (begw == str[*idx])
812 break;
Willy Tarreau975c1782013-12-12 23:16:54 +0100813 memprintf(err_msg, "unknown conv method '%s'", ckw);
Willy Tarreau833cc792013-07-24 15:34:19 +0200814 goto out_error;
815 }
Emeric Brun107ca302010-01-04 16:16:05 +0100816
Willy Tarreau833cc792013-07-24 15:34:19 +0200817 endt = endw;
818 if (*endt == '(') {
819 /* look for the end of this term */
820 while (*endt && *endt != ')')
821 endt++;
822 if (*endt != ')') {
Willy Tarreau975c1782013-12-12 23:16:54 +0100823 memprintf(err_msg, "syntax error: missing ')' after conv keyword '%s'", ckw);
Willy Tarreau833cc792013-07-24 15:34:19 +0200824 goto out_error;
Emeric Brun485479d2010-09-23 18:02:19 +0200825 }
Willy Tarreau833cc792013-07-24 15:34:19 +0200826 }
827
828 if (conv->in_type >= SMP_TYPES || conv->out_type >= SMP_TYPES) {
Willy Tarreau975c1782013-12-12 23:16:54 +0100829 memprintf(err_msg, "returns type of conv method '%s' is unknown", ckw);
Emeric Brun107ca302010-01-04 16:16:05 +0100830 goto out_error;
Emeric Brun485479d2010-09-23 18:02:19 +0200831 }
Emeric Brun107ca302010-01-04 16:16:05 +0100832
833 /* If impossible type conversion */
Willy Tarreau12785782012-04-27 21:37:17 +0200834 if (!sample_casts[prev_type][conv->in_type]) {
Willy Tarreau975c1782013-12-12 23:16:54 +0100835 memprintf(err_msg, "conv method '%s' cannot be applied", ckw);
Emeric Brun107ca302010-01-04 16:16:05 +0100836 goto out_error;
Emeric Brun485479d2010-09-23 18:02:19 +0200837 }
Emeric Brun107ca302010-01-04 16:16:05 +0100838
839 prev_type = conv->out_type;
Willy Tarreau12785782012-04-27 21:37:17 +0200840 conv_expr = calloc(1, sizeof(struct sample_conv_expr));
Emeric Brun485479d2010-09-23 18:02:19 +0200841 if (!conv_expr)
842 goto out_error;
Emeric Brun107ca302010-01-04 16:16:05 +0100843
844 LIST_ADDQ(&(expr->conv_exprs), &(conv_expr->list));
845 conv_expr->conv = conv;
846
Willy Tarreau833cc792013-07-24 15:34:19 +0200847 if (endt != endw) {
Willy Tarreaub27c0d32012-04-20 16:04:47 +0200848 int err_arg;
Willy Tarreau21d68a62012-04-20 15:52:36 +0200849
Willy Tarreau9fcb9842012-04-20 14:45:49 +0200850 if (!conv->arg_mask) {
Willy Tarreau975c1782013-12-12 23:16:54 +0100851 memprintf(err_msg, "conv method '%s' does not support any args", ckw);
Emeric Brun485479d2010-09-23 18:02:19 +0200852 goto out_error;
853 }
Willy Tarreau9e92d322010-01-26 17:58:06 +0100854
Willy Tarreaua4312fa2013-04-02 16:34:32 +0200855 al->kw = expr->fetch->kw;
856 al->conv = conv_expr->conv->kw;
Willy Tarreau975c1782013-12-12 23:16:54 +0100857 if (make_arg_list(endw + 1, endt - endw - 1, conv->arg_mask, &conv_expr->arg_p, err_msg, NULL, &err_arg, al) < 0) {
858 memprintf(err_msg, "invalid arg %d in conv method '%s' : %s", err_arg+1, ckw, *err_msg);
Willy Tarreau21d68a62012-04-20 15:52:36 +0200859 goto out_error;
860 }
861
Willy Tarreau2e845be2012-10-19 19:49:09 +0200862 if (!conv_expr->arg_p)
863 conv_expr->arg_p = empty_arg_list;
864
Willy Tarreau975c1782013-12-12 23:16:54 +0100865 if (conv->val_args && !conv->val_args(conv_expr->arg_p, conv, err_msg)) {
866 memprintf(err_msg, "invalid args in conv method '%s' : %s", ckw, *err_msg);
Emeric Brun485479d2010-09-23 18:02:19 +0200867 goto out_error;
868 }
869 }
Willy Tarreau833cc792013-07-24 15:34:19 +0200870 else if (ARGM(conv->arg_mask)) {
Willy Tarreau975c1782013-12-12 23:16:54 +0100871 memprintf(err_msg, "missing args for conv method '%s'", ckw);
Emeric Brun485479d2010-09-23 18:02:19 +0200872 goto out_error;
Emeric Brun107ca302010-01-04 16:16:05 +0100873 }
874 }
Emeric Brun485479d2010-09-23 18:02:19 +0200875
Willy Tarreau833cc792013-07-24 15:34:19 +0200876 out:
877 free(fkw);
878 free(ckw);
Emeric Brun107ca302010-01-04 16:16:05 +0100879 return expr;
880
881out_error:
Willy Tarreau12785782012-04-27 21:37:17 +0200882 /* TODO: prune_sample_expr(expr); */
Willy Tarreau833cc792013-07-24 15:34:19 +0200883 expr = NULL;
884 goto out;
Emeric Brun107ca302010-01-04 16:16:05 +0100885}
886
887/*
Willy Tarreau12785782012-04-27 21:37:17 +0200888 * Process a fetch + format conversion of defined by the sample expression <expr>
Willy Tarreau32a6f2e2012-04-25 10:13:36 +0200889 * on request or response considering the <opt> parameter.
Willy Tarreau12785782012-04-27 21:37:17 +0200890 * Returns a pointer on a typed sample structure containing the result or NULL if
891 * sample is not found or when format conversion failed.
Emeric Brun107ca302010-01-04 16:16:05 +0100892 * If <p> is not null, function returns results in structure pointed by <p>.
Willy Tarreau12785782012-04-27 21:37:17 +0200893 * If <p> is null, functions returns a pointer on a static sample structure.
Willy Tarreaub8c8f1f2012-04-23 22:38:26 +0200894 *
895 * Note: the fetch functions are required to properly set the return type. The
896 * conversion functions must do so too. However the cast functions do not need
897 * to since they're made to cast mutiple types according to what is required.
Emeric Brun107ca302010-01-04 16:16:05 +0100898 */
Willy Tarreau12785782012-04-27 21:37:17 +0200899struct sample *sample_process(struct proxy *px, struct session *l4, void *l7,
900 unsigned int opt,
901 struct sample_expr *expr, struct sample *p)
Emeric Brun107ca302010-01-04 16:16:05 +0100902{
Willy Tarreau12785782012-04-27 21:37:17 +0200903 struct sample_conv_expr *conv_expr;
Emeric Brun107ca302010-01-04 16:16:05 +0100904
Willy Tarreau18387e22013-07-25 12:02:38 +0200905 if (p == NULL) {
Willy Tarreaub4a88f02012-04-23 21:35:11 +0200906 p = &temp_smp;
Willy Tarreau18387e22013-07-25 12:02:38 +0200907 p->flags = 0;
908 }
Emeric Brun107ca302010-01-04 16:16:05 +0100909
Willy Tarreauef38c392013-07-22 16:29:32 +0200910 if (!expr->fetch->process(px, l4, l7, opt, expr->arg_p, p, expr->fetch->kw))
Emeric Brun107ca302010-01-04 16:16:05 +0100911 return NULL;
912
Emeric Brun107ca302010-01-04 16:16:05 +0100913 list_for_each_entry(conv_expr, &expr->conv_exprs, list) {
Willy Tarreau12e50112012-04-25 17:21:49 +0200914 /* we want to ensure that p->type can be casted into
915 * conv_expr->conv->in_type. We have 3 possibilities :
916 * - NULL => not castable.
917 * - c_none => nothing to do (let's optimize it)
918 * - other => apply cast and prepare to fail
919 */
Willy Tarreau12785782012-04-27 21:37:17 +0200920 if (!sample_casts[p->type][conv_expr->conv->in_type])
Willy Tarreau12e50112012-04-25 17:21:49 +0200921 return NULL;
922
Willy Tarreau12785782012-04-27 21:37:17 +0200923 if (sample_casts[p->type][conv_expr->conv->in_type] != c_none &&
924 !sample_casts[p->type][conv_expr->conv->in_type](p))
Emeric Brun107ca302010-01-04 16:16:05 +0100925 return NULL;
926
Willy Tarreau12e50112012-04-25 17:21:49 +0200927 /* OK cast succeeded */
928
Willy Tarreau342acb42012-04-23 22:03:39 +0200929 if (!conv_expr->conv->process(conv_expr->arg_p, p))
Emeric Brun107ca302010-01-04 16:16:05 +0100930 return NULL;
Emeric Brun107ca302010-01-04 16:16:05 +0100931 }
932 return p;
933}
934
Willy Tarreaue7ad4bb2012-12-21 00:02:32 +0100935/*
Willy Tarreaua4312fa2013-04-02 16:34:32 +0200936 * Resolve all remaining arguments in proxy <p>. Returns the number of
937 * errors or 0 if everything is fine.
938 */
939int smp_resolve_args(struct proxy *p)
940{
941 struct arg_list *cur, *bak;
942 const char *ctx, *where;
943 const char *conv_ctx, *conv_pre, *conv_pos;
944 struct userlist *ul;
945 struct arg *arg;
946 int cfgerr = 0;
947
948 list_for_each_entry_safe(cur, bak, &p->conf.args.list, list) {
949 struct proxy *px;
950 struct server *srv;
951 char *pname, *sname;
952
953 arg = cur->arg;
954
955 /* prepare output messages */
956 conv_pre = conv_pos = conv_ctx = "";
957 if (cur->conv) {
958 conv_ctx = cur->conv;
959 conv_pre = "conversion keyword '";
960 conv_pos = "' for ";
961 }
962
963 where = "in";
964 ctx = "sample fetch keyword";
965 switch (cur->ctx) {
966 case ARGC_STK:where = "in stick rule in"; break;
967 case ARGC_TRK: where = "in tracking rule in"; break;
968 case ARGC_LOG: where = "in log-format string in"; break;
Thierry FOURNIER1c0054f2013-11-20 15:09:52 +0100969 case ARGC_HRQ: where = "in http-request header format string in"; break;
970 case ARGC_HRS: where = "in http-response header format string in"; break;
Willy Tarreaua4312fa2013-04-02 16:34:32 +0200971 case ARGC_UIF: where = "in unique-id-format string in"; break;
Thierry FOURNIERd18cd0f2013-11-29 12:15:45 +0100972 case ARGC_RDR: where = "in redirect format string in"; break;
Willy Tarreaua4312fa2013-04-02 16:34:32 +0200973 case ARGC_ACL: ctx = "ACL keyword"; break;
974 }
975
976 /* set a few default settings */
977 px = p;
978 pname = p->id;
979
980 switch (arg->type) {
981 case ARGT_SRV:
982 if (!arg->data.str.len) {
983 Alert("parsing [%s:%d] : missing server name in arg %d of %s%s%s%s '%s' %s proxy '%s'.\n",
984 cur->file, cur->line,
985 cur->arg_pos + 1, conv_pre, conv_ctx, conv_pos, ctx, cur->kw, where, p->id);
986 cfgerr++;
987 continue;
988 }
989
990 /* we support two formats : "bck/srv" and "srv" */
991 sname = strrchr(arg->data.str.str, '/');
992
993 if (sname) {
994 *sname++ = '\0';
995 pname = arg->data.str.str;
996
997 px = findproxy(pname, PR_CAP_BE);
998 if (!px) {
999 Alert("parsing [%s:%d] : unable to find proxy '%s' referenced in arg %d of %s%s%s%s '%s' %s proxy '%s'.\n",
1000 cur->file, cur->line, pname,
1001 cur->arg_pos + 1, conv_pre, conv_ctx, conv_pos, ctx, cur->kw, where, p->id);
1002 cfgerr++;
1003 break;
1004 }
1005 }
1006 else
1007 sname = arg->data.str.str;
1008
1009 srv = findserver(px, sname);
1010 if (!srv) {
1011 Alert("parsing [%s:%d] : unable to find server '%s' in proxy '%s', referenced in arg %d of %s%s%s%s '%s' %s proxy '%s'.\n",
1012 cur->file, cur->line, sname, pname,
1013 cur->arg_pos + 1, conv_pre, conv_ctx, conv_pos, ctx, cur->kw, where, p->id);
1014 cfgerr++;
1015 break;
1016 }
1017
1018 free(arg->data.str.str);
1019 arg->data.str.str = NULL;
1020 arg->unresolved = 0;
1021 arg->data.srv = srv;
1022 break;
1023
1024 case ARGT_FE:
1025 if (arg->data.str.len) {
1026 pname = arg->data.str.str;
1027 px = findproxy(pname, PR_CAP_FE);
1028 }
1029
1030 if (!px) {
1031 Alert("parsing [%s:%d] : unable to find frontend '%s' referenced in arg %d of %s%s%s%s '%s' %s proxy '%s'.\n",
1032 cur->file, cur->line, pname,
1033 cur->arg_pos + 1, conv_pre, conv_ctx, conv_pos, ctx, cur->kw, where, p->id);
1034 cfgerr++;
1035 break;
1036 }
1037
1038 if (!(px->cap & PR_CAP_FE)) {
1039 Alert("parsing [%s:%d] : proxy '%s', referenced in arg %d of %s%s%s%s '%s' %s proxy '%s', has not frontend capability.\n",
1040 cur->file, cur->line, pname,
1041 cur->arg_pos + 1, conv_pre, conv_ctx, conv_pos, ctx, cur->kw, where, p->id);
1042 cfgerr++;
1043 break;
1044 }
1045
1046 free(arg->data.str.str);
1047 arg->data.str.str = NULL;
1048 arg->unresolved = 0;
1049 arg->data.prx = px;
1050 break;
1051
1052 case ARGT_BE:
1053 if (arg->data.str.len) {
1054 pname = arg->data.str.str;
1055 px = findproxy(pname, PR_CAP_BE);
1056 }
1057
1058 if (!px) {
1059 Alert("parsing [%s:%d] : unable to find backend '%s' referenced in arg %d of %s%s%s%s '%s' %s proxy '%s'.\n",
1060 cur->file, cur->line, pname,
1061 cur->arg_pos + 1, conv_pre, conv_ctx, conv_pos, ctx, cur->kw, where, p->id);
1062 cfgerr++;
1063 break;
1064 }
1065
1066 if (!(px->cap & PR_CAP_BE)) {
1067 Alert("parsing [%s:%d] : proxy '%s', referenced in arg %d of %s%s%s%s '%s' %s proxy '%s', has not backend capability.\n",
1068 cur->file, cur->line, pname,
1069 cur->arg_pos + 1, conv_pre, conv_ctx, conv_pos, ctx, cur->kw, where, p->id);
1070 cfgerr++;
1071 break;
1072 }
1073
1074 free(arg->data.str.str);
1075 arg->data.str.str = NULL;
1076 arg->unresolved = 0;
1077 arg->data.prx = px;
1078 break;
1079
1080 case ARGT_TAB:
1081 if (arg->data.str.len) {
1082 pname = arg->data.str.str;
1083 px = find_stktable(pname);
1084 }
1085
1086 if (!px) {
1087 Alert("parsing [%s:%d] : unable to find table '%s' referenced in arg %d of %s%s%s%s '%s' %s proxy '%s'.\n",
1088 cur->file, cur->line, pname,
1089 cur->arg_pos + 1, conv_pre, conv_ctx, conv_pos, ctx, cur->kw, where, p->id);
1090 cfgerr++;
1091 break;
1092 }
1093
1094 if (!px->table.size) {
1095 Alert("parsing [%s:%d] : no table in proxy '%s' referenced in arg %d of %s%s%s%s '%s' %s proxy '%s'.\n",
1096 cur->file, cur->line, pname,
1097 cur->arg_pos + 1, conv_pre, conv_ctx, conv_pos, ctx, cur->kw, where, p->id);
1098 cfgerr++;
1099 break;
1100 }
1101
1102 free(arg->data.str.str);
1103 arg->data.str.str = NULL;
1104 arg->unresolved = 0;
1105 arg->data.prx = px;
1106 break;
1107
1108 case ARGT_USR:
1109 if (!arg->data.str.len) {
1110 Alert("parsing [%s:%d] : missing userlist name in arg %d of %s%s%s%s '%s' %s proxy '%s'.\n",
1111 cur->file, cur->line,
1112 cur->arg_pos + 1, conv_pre, conv_ctx, conv_pos, ctx, cur->kw, where, p->id);
1113 cfgerr++;
1114 break;
1115 }
1116
1117 if (p->uri_auth && p->uri_auth->userlist &&
1118 !strcmp(p->uri_auth->userlist->name, arg->data.str.str))
1119 ul = p->uri_auth->userlist;
1120 else
1121 ul = auth_find_userlist(arg->data.str.str);
1122
1123 if (!ul) {
1124 Alert("parsing [%s:%d] : unable to find userlist '%s' referenced in arg %d of %s%s%s%s '%s' %s proxy '%s'.\n",
1125 cur->file, cur->line, arg->data.str.str,
1126 cur->arg_pos + 1, conv_pre, conv_ctx, conv_pos, ctx, cur->kw, where, p->id);
1127 cfgerr++;
1128 break;
1129 }
1130
1131 free(arg->data.str.str);
1132 arg->data.str.str = NULL;
1133 arg->unresolved = 0;
1134 arg->data.usr = ul;
1135 break;
1136 }
1137
1138 LIST_DEL(&cur->list);
1139 free(cur);
1140 } /* end of args processing */
1141
1142 return cfgerr;
1143}
1144
1145/*
Willy Tarreaue7ad4bb2012-12-21 00:02:32 +01001146 * Process a fetch + format conversion as defined by the sample expression <expr>
1147 * on request or response considering the <opt> parameter. The output is always of
1148 * type string. Returns either NULL if no sample could be extracted, or a pointer
1149 * to the converted result stored in static temp_smp in format string.
1150 */
1151struct sample *sample_fetch_string(struct proxy *px, struct session *l4, void *l7,
1152 unsigned int opt, struct sample_expr *expr)
1153{
1154 struct sample *smp;
1155
1156 smp = sample_process(px, l4, l7, opt, expr, NULL);
1157 if (!smp)
1158 return NULL;
1159
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01001160 if (!sample_casts[smp->type][SMP_T_STR])
Willy Tarreaue7ad4bb2012-12-21 00:02:32 +01001161 return NULL;
1162
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01001163 if (!sample_casts[smp->type][SMP_T_STR](smp))
Willy Tarreaue7ad4bb2012-12-21 00:02:32 +01001164 return NULL;
1165
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01001166 smp->type = SMP_T_STR;
Willy Tarreaue7ad4bb2012-12-21 00:02:32 +01001167 return smp;
1168}
1169
Emeric Brun107ca302010-01-04 16:16:05 +01001170/*****************************************************************/
Willy Tarreau12785782012-04-27 21:37:17 +02001171/* Sample format convert functions */
Willy Tarreaub8c8f1f2012-04-23 22:38:26 +02001172/* These functions set the data type on return. */
Emeric Brun107ca302010-01-04 16:16:05 +01001173/*****************************************************************/
1174
Thierry FOURNIER2f49d6d2014-03-12 15:01:52 +01001175static int sample_conv_bin2hex(const struct arg *arg_p, struct sample *smp)
1176{
1177 struct chunk *trash = get_trash_chunk();
1178 unsigned char c;
1179 int ptr = 0;
1180
1181 trash->len = 0;
1182 while (ptr < smp->data.str.len && trash->len <= trash->size - 2) {
1183 c = smp->data.str.str[ptr++];
1184 trash->str[trash->len++] = hextab[(c >> 4) & 0xF];
1185 trash->str[trash->len++] = hextab[c & 0xF];
1186 }
1187 smp->data.str = *trash;
1188 smp->type = SMP_T_STR;
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01001189 smp->flags &= ~SMP_F_CONST;
Thierry FOURNIER2f49d6d2014-03-12 15:01:52 +01001190 return 1;
1191}
1192
Willy Tarreau12785782012-04-27 21:37:17 +02001193static int sample_conv_str2lower(const struct arg *arg_p, struct sample *smp)
Emeric Brun107ca302010-01-04 16:16:05 +01001194{
1195 int i;
1196
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01001197 if (!smp_dup(smp))
1198 return 0;
1199
Willy Tarreau342acb42012-04-23 22:03:39 +02001200 if (!smp->data.str.size)
Emeric Brun485479d2010-09-23 18:02:19 +02001201 return 0;
1202
Willy Tarreau342acb42012-04-23 22:03:39 +02001203 for (i = 0; i < smp->data.str.len; i++) {
1204 if ((smp->data.str.str[i] >= 'A') && (smp->data.str.str[i] <= 'Z'))
1205 smp->data.str.str[i] += 'a' - 'A';
Emeric Brun107ca302010-01-04 16:16:05 +01001206 }
1207 return 1;
1208}
1209
Willy Tarreau12785782012-04-27 21:37:17 +02001210static int sample_conv_str2upper(const struct arg *arg_p, struct sample *smp)
Emeric Brun107ca302010-01-04 16:16:05 +01001211{
1212 int i;
1213
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01001214 if (!smp_dup(smp))
1215 return 0;
1216
Willy Tarreau342acb42012-04-23 22:03:39 +02001217 if (!smp->data.str.size)
Emeric Brun485479d2010-09-23 18:02:19 +02001218 return 0;
1219
Willy Tarreau342acb42012-04-23 22:03:39 +02001220 for (i = 0; i < smp->data.str.len; i++) {
1221 if ((smp->data.str.str[i] >= 'a') && (smp->data.str.str[i] <= 'z'))
1222 smp->data.str.str[i] += 'A' - 'a';
Emeric Brun107ca302010-01-04 16:16:05 +01001223 }
1224 return 1;
1225}
1226
Willy Tarreauf9954102012-04-20 14:03:29 +02001227/* takes the netmask in arg_p */
Willy Tarreau12785782012-04-27 21:37:17 +02001228static int sample_conv_ipmask(const struct arg *arg_p, struct sample *smp)
Willy Tarreaud31d6eb2010-01-26 18:01:41 +01001229{
Willy Tarreau342acb42012-04-23 22:03:39 +02001230 smp->data.ipv4.s_addr &= arg_p->data.ipv4.s_addr;
Willy Tarreaub8c8f1f2012-04-23 22:38:26 +02001231 smp->type = SMP_T_IPV4;
Willy Tarreaud31d6eb2010-01-26 18:01:41 +01001232 return 1;
1233}
1234
Willy Tarreau5b8ad222013-07-25 12:17:57 +02001235/************************************************************************/
1236/* All supported sample fetch functions must be declared here */
1237/************************************************************************/
1238
1239/* force TRUE to be returned at the fetch level */
1240static int
1241smp_fetch_true(struct proxy *px, struct session *s, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001242 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau5b8ad222013-07-25 12:17:57 +02001243{
1244 smp->type = SMP_T_BOOL;
1245 smp->data.uint = 1;
1246 return 1;
1247}
1248
1249/* force FALSE to be returned at the fetch level */
1250static int
1251smp_fetch_false(struct proxy *px, struct session *s, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001252 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau5b8ad222013-07-25 12:17:57 +02001253{
1254 smp->type = SMP_T_BOOL;
1255 smp->data.uint = 0;
1256 return 1;
1257}
1258
1259/* retrieve environment variable $1 as a string */
1260static int
1261smp_fetch_env(struct proxy *px, struct session *s, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001262 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau5b8ad222013-07-25 12:17:57 +02001263{
1264 char *env;
1265
1266 if (!args || args[0].type != ARGT_STR)
1267 return 0;
1268
1269 env = getenv(args[0].data.str.str);
1270 if (!env)
1271 return 0;
1272
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01001273 smp->type = SMP_T_STR;
1274 smp->flags = SMP_F_CONST;
Willy Tarreau5b8ad222013-07-25 12:17:57 +02001275 smp->data.str.str = env;
1276 smp->data.str.len = strlen(env);
1277 return 1;
1278}
1279
Willy Tarreau6236d3a2013-07-25 14:28:25 +02001280/* retrieve the current local date in epoch time, and applies an optional offset
1281 * of args[0] seconds.
1282 */
1283static int
1284smp_fetch_date(struct proxy *px, struct session *s, void *l7, unsigned int opt,
Willy Tarreauef38c392013-07-22 16:29:32 +02001285 const struct arg *args, struct sample *smp, const char *kw)
Willy Tarreau6236d3a2013-07-25 14:28:25 +02001286{
1287 smp->data.uint = date.tv_sec;
1288
1289 /* add offset */
1290 if (args && (args[0].type == ARGT_SINT || args[0].type == ARGT_UINT))
1291 smp->data.uint += args[0].data.sint;
1292
1293 smp->type = SMP_T_UINT;
1294 smp->flags |= SMP_F_VOL_TEST | SMP_F_MAY_CHANGE;
1295 return 1;
1296}
1297
Willy Tarreau84310e22014-02-14 11:59:04 +01001298/* generate a random 32-bit integer for whatever purpose, with an optional
1299 * range specified in argument.
1300 */
1301static int
1302smp_fetch_rand(struct proxy *px, struct session *s, void *l7, unsigned int opt,
1303 const struct arg *args, struct sample *smp, const char *kw)
1304{
1305 smp->data.uint = random();
1306
1307 /* reduce if needed. Don't do a modulo, use all bits! */
1308 if (args && args[0].type == ARGT_UINT)
1309 smp->data.uint = ((uint64_t)smp->data.uint * args[0].data.uint) >> 32;
1310
1311 smp->type = SMP_T_UINT;
1312 smp->flags |= SMP_F_VOL_TEST | SMP_F_MAY_CHANGE;
1313 return 1;
1314}
1315
Willy Tarreau5b8ad222013-07-25 12:17:57 +02001316/* Note: must not be declared <const> as its list will be overwritten.
1317 * Note: fetches that may return multiple types must be declared as the lowest
1318 * common denominator, the type that can be casted into all other ones. For
1319 * instance IPv4/IPv6 must be declared IPv4.
1320 */
1321static struct sample_fetch_kw_list smp_kws = {ILH, {
1322 { "always_false", smp_fetch_false, 0, NULL, SMP_T_BOOL, SMP_USE_INTRN },
1323 { "always_true", smp_fetch_true, 0, NULL, SMP_T_BOOL, SMP_USE_INTRN },
Thierry FOURNIER7654c9f2013-12-17 00:20:33 +01001324 { "env", smp_fetch_env, ARG1(1,STR), NULL, SMP_T_STR, SMP_USE_INTRN },
Willy Tarreau6236d3a2013-07-25 14:28:25 +02001325 { "date", smp_fetch_date, ARG1(0,SINT), NULL, SMP_T_UINT, SMP_USE_INTRN },
Willy Tarreau84310e22014-02-14 11:59:04 +01001326 { "rand", smp_fetch_rand, ARG1(0,UINT), NULL, SMP_T_UINT, SMP_USE_INTRN },
Willy Tarreau5b8ad222013-07-25 12:17:57 +02001327 { /* END */ },
1328}};
1329
Emeric Brun107ca302010-01-04 16:16:05 +01001330/* Note: must not be declared <const> as its list will be overwritten */
Willy Tarreaudc13c112013-06-21 23:16:39 +02001331static struct sample_conv_kw_list sample_conv_kws = {ILH, {
Willy Tarreau12785782012-04-27 21:37:17 +02001332 { "upper", sample_conv_str2upper, 0, NULL, SMP_T_STR, SMP_T_STR },
1333 { "lower", sample_conv_str2lower, 0, NULL, SMP_T_STR, SMP_T_STR },
Thierry FOURNIER2f49d6d2014-03-12 15:01:52 +01001334 { "hex", sample_conv_bin2hex, 0, NULL, SMP_T_BIN, SMP_T_STR },
Willy Tarreau12785782012-04-27 21:37:17 +02001335 { "ipmask", sample_conv_ipmask, ARG1(1,MSK4), NULL, SMP_T_IPV4, SMP_T_IPV4 },
Willy Tarreau9fcb9842012-04-20 14:45:49 +02001336 { NULL, NULL, 0, 0, 0 },
Emeric Brun107ca302010-01-04 16:16:05 +01001337}};
1338
1339__attribute__((constructor))
Willy Tarreau12785782012-04-27 21:37:17 +02001340static void __sample_init(void)
Emeric Brun107ca302010-01-04 16:16:05 +01001341{
Willy Tarreau5b8ad222013-07-25 12:17:57 +02001342 /* register sample fetch and format conversion keywords */
1343 sample_register_fetches(&smp_kws);
Willy Tarreau12785782012-04-27 21:37:17 +02001344 sample_register_convs(&sample_conv_kws);
Emeric Brun107ca302010-01-04 16:16:05 +01001345}