]> git.pld-linux.org Git - packages/lighttpd.git/blob - lighttpd-branch.diff
- updated to 1706
[packages/lighttpd.git] / lighttpd-branch.diff
1 Index: configure.in
2 ===================================================================
3 --- configure.in        (.../tags/lighttpd-1.4.13)      (revision 1706)
4 +++ configure.in        (.../branches/lighttpd-1.4.x)   (revision 1706)
5 @@ -398,7 +398,7 @@
6  
7  AC_MSG_RESULT($WITH_LUA)
8  if test "$WITH_LUA" != "no"; then
9 - if test "$WITH_LUA" == "yes"; then
10 + if test "$WITH_LUA" = "yes"; then
11    WITH_LUA=lua
12   fi
13   PKG_CHECK_MODULES(LUA, $WITH_LUA >= 5.1, [
14 @@ -538,7 +538,7 @@
15  AC_OUTPUT
16  
17  
18 -do_build="mod_cgi mod_fastcgi mod_proxy mod_evhost mod_simple_vhost mod_access mod_alias mod_setenv mod_usertrack mod_auth mod_status mod_accesslog mod_rrdtool mod_secdownload mod_expire mod_compress mod_dirlisting mod_indexfiles mod_userdir mod_webdav mod_staticfile mod_scgi mod_flv_streaming"
19 +do_build="mod_cgi mod_fastcgi mod_extforward mod_proxy mod_evhost mod_simple_vhost mod_access mod_alias mod_setenv mod_usertrack mod_auth mod_status mod_accesslog mod_rrdtool mod_secdownload mod_expire mod_compress mod_dirlisting mod_indexfiles mod_userdir mod_webdav mod_staticfile mod_scgi mod_flv_streaming"
20  
21  plugins="mod_rewrite mod_redirect mod_ssi mod_trigger_b4_dl"
22  features="regex-conditionals"
23 Index: src/mod_cgi.c
24 ===================================================================
25 --- src/mod_cgi.c       (.../tags/lighttpd-1.4.13)      (revision 1706)
26 +++ src/mod_cgi.c       (.../branches/lighttpd-1.4.x)   (revision 1706)
27 @@ -842,6 +842,12 @@
28                                     CONST_BUF_LEN(con->authed_user));
29                 }
30  
31 +#ifdef USE_OPENSSL
32 +       if (srv_sock->is_ssl) {
33 +               cgi_env_add(&env, CONST_STR_LEN("HTTPS"), CONST_STR_LEN("on"));
34 +       }
35 +#endif
36 +
37                 /* request.content_length < SSIZE_MAX, see request.c */
38                 ltostr(buf, con->request.content_length);
39                 cgi_env_add(&env, CONST_STR_LEN("CONTENT_LENGTH"), buf, strlen(buf));
40 Index: src/base.h
41 ===================================================================
42 --- src/base.h  (.../tags/lighttpd-1.4.13)      (revision 1706)
43 +++ src/base.h  (.../branches/lighttpd-1.4.x)   (revision 1706)
44 @@ -481,7 +481,9 @@
45         enum { STAT_CACHE_ENGINE_UNSET,
46                         STAT_CACHE_ENGINE_NONE,
47                         STAT_CACHE_ENGINE_SIMPLE,
48 +#ifdef HAVE_FAM_H
49                         STAT_CACHE_ENGINE_FAM
50 +#endif
51         } stat_cache_engine;
52         unsigned short enable_cores;
53  } server_config;
54 Index: src/connections.c
55 ===================================================================
56 --- src/connections.c   (.../tags/lighttpd-1.4.13)      (revision 1706)
57 +++ src/connections.c   (.../branches/lighttpd-1.4.x)   (revision 1706)
58 @@ -500,6 +500,7 @@
59         case 201:
60         case 301:
61         case 302:
62 +       case 303:
63                 break;
64  
65         case 206: /* write_queue is already prepared */
66 @@ -970,7 +971,7 @@
67                                                                 }
68                                                         } else {
69                                                                 /* a splited \r \n */
70 -                                                               return -1;
71 +                                                               break;
72                                                         }
73                                                 }
74                                         }
75 Index: src/configfile.c
76 ===================================================================
77 --- src/configfile.c    (.../tags/lighttpd-1.4.13)      (revision 1706)
78 +++ src/configfile.c    (.../branches/lighttpd-1.4.x)   (revision 1706)
79 @@ -218,13 +218,19 @@
80                 srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_SIMPLE;
81         } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("simple"))) {
82                 srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_SIMPLE;
83 +#ifdef HAVE_FAM_H
84         } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("fam"))) {
85                 srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_FAM;
86 +#endif
87         } else if (buffer_is_equal_string(stat_cache_string, CONST_STR_LEN("disable"))) {
88                 srv->srvconf.stat_cache_engine = STAT_CACHE_ENGINE_NONE;
89         } else {
90                 log_error_write(srv, __FILE__, __LINE__, "sb",
91 -                               "server.stat-cache-engine can be one of \"disable\", \"simple\", \"fam\", but not:", stat_cache_string);
92 +                               "server.stat-cache-engine can be one of \"disable\", \"simple\","
93 +#ifdef HAVE_FAM_H
94 +                               " \"fam\","
95 +#endif
96 +                               " but not:", stat_cache_string);
97                 ret = HANDLER_ERROR;
98         }
99  
100 Index: src/mod_scgi.c
101 ===================================================================
102 --- src/mod_scgi.c      (.../tags/lighttpd-1.4.13)      (revision 1706)
103 +++ src/mod_scgi.c      (.../branches/lighttpd-1.4.x)   (revision 1706)
104 @@ -2528,7 +2528,7 @@
105                                     hctx->reconnects < 5) {
106                                         scgi_reconnect(srv, hctx);
107  
108 -                                       log_error_write(srv, __FILE__, __LINE__, "sdsdsd",
109 +                                       log_error_write(srv, __FILE__, __LINE__, "ssdsd",
110                                                 "response not sent, request not sent, reconnection.",
111                                                 "connection-fd:", con->fd,
112                                                 "fcgi-fd:", hctx->fd);
113 Index: src/request.c
114 ===================================================================
115 --- src/request.c       (.../tags/lighttpd-1.4.13)      (revision 1706)
116 +++ src/request.c       (.../branches/lighttpd-1.4.x)   (revision 1706)
117 @@ -85,6 +85,9 @@
118         /* Host is empty */
119         if (host_len == 0) return -1;
120  
121 +       /* if the hostname ends in a "." strip it */
122 +       if (host->ptr[host_len-1] == '.') host_len -= 1;
123 +
124         /* scan from the right and skip the \0 */
125         for (i = host_len - 1; i + 1 > 0; i--) {
126                 const char c = host->ptr[i];
127 Index: src/network_backends.h
128 ===================================================================
129 --- src/network_backends.h      (.../tags/lighttpd-1.4.13)      (revision 1706)
130 +++ src/network_backends.h      (.../branches/lighttpd-1.4.x)   (revision 1706)
131 @@ -14,7 +14,7 @@
132  # include <sys/uio.h>
133  #endif
134  
135 -#if defined HAVE_SYS_UIO_H && defined HAVE_SENDFILE && defined HAVE_WRITEV && defined(__FreeBSD__)
136 +#if defined HAVE_SYS_UIO_H && defined HAVE_SENDFILE && defined HAVE_WRITEV && (defined(__FreeBSD__) || defined(__DragonFly__))
137  # define USE_FREEBSD_SENDFILE
138  # include <sys/uio.h>
139  #endif
140 Index: src/mod_proxy.c
141 ===================================================================
142 --- src/mod_proxy.c     (.../tags/lighttpd-1.4.13)      (revision 1706)
143 +++ src/mod_proxy.c     (.../branches/lighttpd-1.4.x)   (revision 1706)
144 @@ -656,6 +656,7 @@
145                 }
146  
147                 if (-1 == (r = read(hctx->fd, hctx->response->ptr + hctx->response->used - 1, b))) {
148 +                       if (errno == EAGAIN) return 0;
149                         log_error_write(srv, __FILE__, __LINE__, "sds",
150                                         "unexpected end-of-file (perhaps the proxy process died):",
151                                         proxy_fd, strerror(errno));
152 Index: src/mod_extforward.c
153 ===================================================================
154 --- src/mod_extforward.c        (.../tags/lighttpd-1.4.13)      (revision 0)
155 +++ src/mod_extforward.c        (.../branches/lighttpd-1.4.x)   (revision 1706)
156 @@ -0,0 +1,490 @@
157 +#include <ctype.h>
158 +#include <stdlib.h>
159 +#include <string.h>
160 +#include <stdio.h>
161 +#include <netinet/in.h>
162 +
163 +#include "base.h"
164 +#include "log.h"
165 +#include "buffer.h"
166 +
167 +#include "plugin.h"
168 +
169 +#include "inet_ntop_cache.h"
170 +#ifdef HAVE_CONFIG_H
171 +#include "config.h"
172 +#endif
173 +
174 +/**
175 + * mod_extforward.c for lighttpd, by comman.kang <at> gmail <dot> com
176 + *                  extended, modified by Lionel Elie Mamane (LEM), lionel <at> mamane <dot> lu
177 + *
178 + * Config example:
179 + *
180 + *       Trust proxy 10.0.0.232 and 10.0.0.232
181 + *       extforward.forwarder = ( "10.0.0.232" => "trust",
182 + *                                "10.0.0.233" => "trust" )
183 + *
184 + *       Trust all proxies  (NOT RECOMMENDED!)
185 + *       extforward.forwarder = ( "all" => "trust")
186 + *
187 + *       Note that "all" has precedence over specific entries,
188 + *       so "all except" setups will not work.
189 + *
190 + * Note: The effect of this module is variable on $HTTP["remotip"] directives and
191 + *       other module's remote ip dependent actions.
192 + *  Things done by modules before we change the remoteip or after we reset it will match on the proxy's IP.
193 + *  Things done in between these two moments will match on the real client's IP.
194 + *  The moment things are done by a module depends on in which hook it does things and within the same hook
195 + *  on whether they are before/after us in the module loading order
196 + *  (order in the server.modules directive in the config file).
197 + *
198 + * Tested behaviours:
199 + *
200 + *  mod_access: Will match on the real client.
201 + *
202 + *  mod_accesslog:
203 + *   In order to see the "real" ip address in access log ,
204 + *   you'll have to load mod_extforward after mod_accesslog.
205 + *   like this:
206 + *
207 + *    server.modules  = (
208 + *       .....
209 + *       mod_accesslog,
210 + *       mod_extforward
211 + *    )
212 + *
213 + * Known issues:
214 + *      seems causing segfault with mod_ssl and $HTTP{"socket"} directives
215 + *      LEM 2006.05.26: Fixed segfault $SERVER["socket"] directive. Untested with SSL.
216 + *
217 + * ChangeLog:
218 + *     2005.12.19   Initial Version
219 + *     2005.12.19   fixed conflict with conditional directives
220 + *     2006.05.26   LEM: IPv6 support
221 + *     2006.05.26   LEM: Fix a segfault with $SERVER["socket"] directive.
222 + *     2006.05.26   LEM: Run at uri_raw time, as we don't need to see the URI
223 + *                       In this manner, we run before mod_access and $HTTP["remoteip"] directives work!
224 + *     2006.05.26   LEM: Clean config_cond cache of tests whose result we probably change.
225 + */
226 +
227 +
228 +/* plugin config for all request/connections */
229 +
230 +typedef struct {
231 +       array *forwarder;
232 +} plugin_config;
233 +
234 +typedef struct {
235 +       PLUGIN_DATA;
236 +
237 +       plugin_config **config_storage;
238 +
239 +       plugin_config conf;
240 +} plugin_data;
241 +
242 +
243 +/* context , used for restore remote ip */
244 +
245 +typedef struct {
246 +       sock_addr saved_remote_addr;
247 +       buffer *saved_remote_addr_buf;
248 +} handler_ctx;
249 +
250 +
251 +static handler_ctx * handler_ctx_init(sock_addr oldaddr, buffer *oldaddr_buf) {
252 +       handler_ctx * hctx;
253 +       hctx = calloc(1, sizeof(*hctx));
254 +       hctx->saved_remote_addr = oldaddr;
255 +       hctx->saved_remote_addr_buf = oldaddr_buf;
256 +       return hctx;
257 +}
258 +
259 +static void handler_ctx_free(handler_ctx *hctx) {
260 +       free(hctx);
261 +}
262 +
263 +/* init the plugin data */
264 +INIT_FUNC(mod_extforward_init) {
265 +       plugin_data *p;
266 +       p = calloc(1, sizeof(*p));
267 +       return p;
268 +}
269 +
270 +/* destroy the plugin data */
271 +FREE_FUNC(mod_extforward_free) {
272 +       plugin_data *p = p_d;
273 +
274 +       UNUSED(srv);
275 +
276 +       if (!p) return HANDLER_GO_ON;
277 +
278 +       if (p->config_storage) {
279 +               size_t i;
280 +
281 +               for (i = 0; i < srv->config_context->used; i++) {
282 +                       plugin_config *s = p->config_storage[i];
283 +
284 +                       if (!s) continue;
285 +
286 +                       array_free(s->forwarder);
287 +
288 +                       free(s);
289 +               }
290 +               free(p->config_storage);
291 +       }
292 +
293 +
294 +       free(p);
295 +
296 +       return HANDLER_GO_ON;
297 +}
298 +
299 +/* handle plugin config and check values */
300 +
301 +SETDEFAULTS_FUNC(mod_extforward_set_defaults) {
302 +       plugin_data *p = p_d;
303 +       size_t i = 0;
304 +
305 +       config_values_t cv[] = {
306 +               { "extforward.forwarder",             NULL, T_CONFIG_ARRAY, T_CONFIG_SCOPE_CONNECTION },       /* 0 */
307 +               { NULL,                         NULL, T_CONFIG_UNSET, T_CONFIG_SCOPE_UNSET }
308 +       };
309 +
310 +       if (!p) return HANDLER_ERROR;
311 +
312 +       p->config_storage = calloc(1, srv->config_context->used * sizeof(specific_config *));
313 +
314 +       for (i = 0; i < srv->config_context->used; i++) {
315 +               plugin_config *s;
316 +
317 +               s = calloc(1, sizeof(plugin_config));
318 +               s->forwarder    = array_init();
319 +
320 +               cv[0].destination = s->forwarder;
321 +
322 +               p->config_storage[i] = s;
323 +
324 +               if (0 != config_insert_values_global(srv, ((data_config *)srv->config_context->data[i])->value, cv)) {
325 +                       return HANDLER_ERROR;
326 +               }
327 +       }
328 +
329 +       return HANDLER_GO_ON;
330 +}
331 +
332 +#define PATCH(x) \
333 +       p->conf.x = s->x;
334 +static int mod_extforward_patch_connection(server *srv, connection *con, plugin_data *p) {
335 +       size_t i, j;
336 +       plugin_config *s = p->config_storage[0];
337 +
338 +       PATCH(forwarder);
339 +
340 +       /* LEM: The purpose of this seems to match extforward configuration
341 +               stanzas that are not in the global context, but in some sub-context.
342 +                I fear this will break contexts of the form HTTP['remote'] = .
343 +               (in the form that they do not work with the real remote, but matching on
344 +               the proxy instead).
345 +
346 +               I'm not sure this this is all thread-safe. Is the p we are passed different
347 +               for each connection or is it global?
348 +
349 +               mod_fastcgi does the same, so it must be safe.
350 +        */
351 +       /* skip the first, the global context */
352 +       for (i = 1; i < srv->config_context->used; i++) {
353 +               data_config *dc = (data_config *)srv->config_context->data[i];
354 +               s = p->config_storage[i];
355 +
356 +               /* condition didn't match */
357 +               if (!config_check_cond(srv, con, dc)) continue;
358 +
359 +               /* merge config */
360 +               for (j = 0; j < dc->value->used; j++) {
361 +                       data_unset *du = dc->value->data[j];
362 +
363 +                       if (buffer_is_equal_string(du->key, CONST_STR_LEN("extforward.forwarder"))) {
364 +                               PATCH(forwarder);
365 +                       }
366 +               }
367 +       }
368 +
369 +       return 0;
370 +}
371 +#undef PATCH
372 +
373 +
374 +static void put_string_into_array_len(array *ary, const char *str, int len)
375 +{
376 +       data_string *tempdata;
377 +       if (len == 0)
378 +               return;
379 +       tempdata = data_string_init();
380 +       buffer_copy_string_len(tempdata->value,str,len);
381 +       array_insert_unique(ary,(data_unset *)tempdata);
382 +}
383 +/*
384 +   extract a forward array from the environment
385 +*/
386 +static array *extract_forward_array(buffer *pbuffer)
387 +{
388 +       array *result = array_init();
389 +       if (pbuffer->used > 0) {
390 +               char *base, *curr;
391 +               /* state variable, 0 means not in string, 1 means in string */
392 +               int in_str = 0;
393 +               for (base = pbuffer->ptr, curr = pbuffer->ptr; *curr; curr++)
394 +               {
395 +                       if (in_str) {
396 +                               if ( (*curr > '9' || *curr < '0') && *curr != '.' && *curr != ':' ) {
397 +                                       /* found an separator , insert value into result array */
398 +                                       put_string_into_array_len(result, base, curr-base);
399 +                                       /* change state to not in string */
400 +                                       in_str = 0;
401 +                               }
402 +                       } else {
403 +                               if (*curr >= '0' && *curr <= '9')
404 +                               {
405 +                                       /* found leading char of an IP address, move base pointer and change state */
406 +                                       base = curr;
407 +                                       in_str = 1;
408 +                               }
409 +                       }
410 +               }
411 +               /* if breaking out while in str, we got to the end of string, so add it */
412 +               if (in_str)
413 +               {
414 +                       put_string_into_array_len(result, base, curr-base);
415 +               }
416 +       }
417 +       return result;
418 +}
419 +
420 +#define IP_TRUSTED 1
421 +#define IP_UNTRUSTED 0
422 +/*
423 +   check whether ip is trusted, return 1 for trusted , 0 for untrusted
424 +*/
425 +static int is_proxy_trusted(const char *ipstr, plugin_data *p)
426 +{
427 +       data_string* allds = (data_string *) array_get_element(p->conf.forwarder,"all");
428 +       if (allds) {
429 +               if (strcasecmp(allds->value->ptr,"trust") == 0)
430 +                       return IP_TRUSTED;
431 +               else
432 +                       return IP_UNTRUSTED;
433 +       }
434 +       return (data_string *)array_get_element(p->conf.forwarder,ipstr) ? IP_TRUSTED : IP_UNTRUSTED ;
435 +}
436 +
437 +struct addrinfo *ipstr_to_sockaddr(const char *host)
438 +{
439 +   struct addrinfo hints, *res0;
440 +   int result;
441 +   memset(&hints, 0, sizeof(hints));
442 +   hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
443 +
444 +   result = getaddrinfo(host, NULL, &hints, &res0);
445 +   if ( result != 0 )
446 +   {
447 +      fprintf(stderr,"could not resolve hostname %s because %s\n", host,gai_strerror(result));
448 +      if (result == EAI_SYSTEM)
449 +         perror("The system error is ");
450 +      return NULL;
451 +   }
452 +   else
453 +      if (res0==0)
454 +         fprintf(stderr, "Problem in resolving hostname %s: succeeded, but no information returned\n", host);
455 +
456 +   return res0;
457 +}
458 +
459 +
460 +static void clean_cond_cache(server *srv, connection *con)
461 +{
462 +       size_t i;
463 +
464 +       for (i = 0; i < srv->config_context->used; i++) {
465 +               data_config *dc = (data_config *)srv->config_context->data[i];
466 +
467 +               if (dc->comp == COMP_HTTP_REMOTEIP)
468 +               {
469 +                       con->cond_cache[i].result = COND_RESULT_UNSET;
470 +                       con->cond_cache[i].patterncount = 0;
471 +               }
472 +       }
473 +}
474 +
475 +URIHANDLER_FUNC(mod_extforward_uri_handler) {
476 +       plugin_data *p = p_d;
477 +       data_string *forwarded = NULL;
478 +#ifdef HAVE_IPV6
479 +       char b2[INET6_ADDRSTRLEN + 1];
480 +#endif
481 +       const char *s;
482 +       UNUSED(srv);
483 +       mod_extforward_patch_connection(srv, con, p);
484 +
485 +/*     log_error_write(srv, __FILE__, __LINE__,"s","mod_extforward_uri_handler called\n"); */
486 +
487 +       /* if the remote ip itself is not trusted , then do nothing */
488 +#ifdef HAVE_IPV6
489 +       s = inet_ntop(con->dst_addr.plain.sa_family,
490 +                     con->dst_addr.plain.sa_family == AF_INET6 ?
491 +                      &(con->dst_addr.ipv6.sin6_addr) :
492 +                      &(con->dst_addr.ipv4.sin_addr),
493 +                     b2,
494 +                     (sizeof b2) - 1);
495 +#else
496 +       s = inet_ntoa(con->dst_addr.ipv4.sin_addr);
497 +#endif
498 +       if (IP_UNTRUSTED == is_proxy_trusted (s, p) )
499 +               return HANDLER_GO_ON;
500 +
501 +       /* log_error_write(srv, __FILE__, __LINE__,"s","remote address is trusted proxy, go on\n");*/
502 +       if (con->request.headers &&
503 +           ((forwarded = (data_string *) array_get_element(con->request.headers,"X-Forwarded-For")) ||
504 +            (forwarded = (data_string *) array_get_element(con->request.headers,  "Forwarded-For"))))
505 +       {
506 +               /* log_error_write(srv, __FILE__, __LINE__,"s","found forwarded header\n");*/
507 +               /* found forwarded for header */
508 +               int i;
509 +               array *forward_array = extract_forward_array(forwarded->value);
510 +               char *real_remote_addr = NULL;
511 +#ifdef HAVE_IPV6
512 +               struct addrinfo *addrlist = NULL;
513 +#endif
514 +               /* Testing shows that multiple headers and multiple values in one header
515 +                  come in _reverse_ order. So the first one we get is the last one in the request. */
516 +               for (i = forward_array->used - 1; i >= 0; i--)
517 +               {
518 +                       data_string *ds = (data_string *) forward_array->data[i];
519 +                       if (ds) {
520 +/*                             log_error_write(srv, __FILE__, __LINE__,"ss","forward",ds->value->ptr); */
521 +                               real_remote_addr = ds->value->ptr;
522 +                               break;
523 +                               /* LEM: What the hell is this about?
524 +                                       We test whether the forwarded for IP is trusted?
525 +                                       This looks like an ugly hack to handle multiple Forwarded-For's
526 +                                       and avoid those set to our proxies, or something like that.
527 +                                       My testing shows that reverse proxies add a new X-Forwarded-For header,
528 +                                       and we should thus take the last one, which is the first one we see.
529 +
530 +                                       The net result of the old code is that we use the first untrusted IP,
531 +                                       or if all are trusted, the last trusted IP.
532 +                                       That's crazy. So I've disabled this.
533 +                                */
534 +                               /* check whether it is trusted */
535 +/*                             if (IP_UNTRUSTED == is_proxy_trusted(ds->value->ptr,p) ) */
536 +/*                                     break; */
537 +/*                             log_error_write(srv, __FILE__, __LINE__,"ss",ds->value->ptr," is trusted."); */
538 +
539 +                       }
540 +                       else {
541 +                               /* bug ?  bailing out here */
542 +                               break;
543 +                       }
544 +               }
545 +               if (real_remote_addr != NULL) /* parsed */
546 +               {
547 +                       sock_addr s;
548 +                       struct addrinfo *addrs_left;
549 +/*                     log_error_write(srv, __FILE__, __LINE__,"ss","use forward",real_remote_addr); */
550 +#ifdef HAVE_IPV6
551 +                       addrlist = ipstr_to_sockaddr(real_remote_addr);
552 +                       s.plain.sa_family = AF_UNSPEC;
553 +                       for (addrs_left = addrlist; addrs_left != NULL;
554 +                            addrs_left = addrs_left -> ai_next)
555 +                       {
556 +                               s.plain.sa_family = addrs_left->ai_family;
557 +                               if ( s.plain.sa_family == AF_INET )
558 +                               {
559 +                                       s.ipv4.sin_addr = ((struct sockaddr_in*)addrs_left->ai_addr)->sin_addr;
560 +                                       break;
561 +                               }
562 +                               else if ( s.plain.sa_family == AF_INET6 )
563 +                               {
564 +                                       s.ipv6.sin6_addr = ((struct sockaddr_in6*)addrs_left->ai_addr)->sin6_addr;
565 +                                       break;
566 +                               }
567 +                       }
568 +#else
569 +                       s.ipv4.sin_addr.s_addr = inet_addr(real_remote_addr);
570 +                       s.plain.sa_family = (s.ipv4.sin_addr.s_addr == 0xFFFFFFFF) ? AF_UNSPEC : AF_INET;
571 +#endif
572 +                       if (s.plain.sa_family != AF_UNSPEC)
573 +                       {
574 +                               /* we found the remote address, modify current connection and save the old address */
575 +                               if (con->plugin_ctx[p->id]) {
576 +                                       log_error_write(srv, __FILE__, __LINE__,"patching an already patched connection!");
577 +                                       handler_ctx_free(con->plugin_ctx[p->id]);
578 +                                       con->plugin_ctx[p->id] = NULL;
579 +                               }
580 +                               /* save old address */
581 +                               con->plugin_ctx[p->id] = handler_ctx_init(con->dst_addr, con->dst_addr_buf);
582 +                               /* patch connection address */
583 +                               con->dst_addr = s;
584 +                               con->dst_addr_buf = buffer_init();
585 +                               buffer_copy_string(con->dst_addr_buf, real_remote_addr);
586 +/*                             log_error_write(srv, __FILE__, __LINE__,"ss","Set dst_addr_buf to ", real_remote_addr); */
587 +                               /* Now, clean the conf_cond cache, because we may have changed the results of tests */
588 +                               clean_cond_cache(srv, con);
589 +                       }
590 +#ifdef HAVE_IPV6
591 +                       if (addrlist != NULL ) freeaddrinfo(addrlist);
592 +#endif
593 +               }
594 +               array_free(forward_array);
595 +       }
596 +
597 +       /* not found */
598 +       return HANDLER_GO_ON;
599 +}
600 +
601 +CONNECTION_FUNC(mod_extforward_restore) {
602 +       plugin_data *p = p_d;
603 +       UNUSED(srv);
604 +
605 +       /* LEM: This seems completely unuseful, as we are not using
606 +               p->conf in this function. Furthermore, it brings a
607 +               segfault if one of the conditional configuration
608 +               blocks is "SERVER['socket'] == foo", because the
609 +               socket is not known yet in the srv/con structure.
610 +        */
611 +       /* mod_extforward_patch_connection(srv, con, p); */
612 +
613 +       /* restore this connection's remote ip */
614 +       if (con->plugin_ctx[p->id]) {
615 +               handler_ctx *hctx = con->plugin_ctx[p->id];
616 +               con->dst_addr = hctx->saved_remote_addr;
617 +               buffer_free(con->dst_addr_buf);
618 +               con->dst_addr_buf = hctx->saved_remote_addr_buf;
619 +/*             log_error_write(srv, __FILE__, __LINE__,"s","LEM: Reset dst_addr_buf"); */
620 +               handler_ctx_free(hctx);
621 +               con->plugin_ctx[p->id] = NULL;
622 +               /* Now, clean the conf_cond cache, because we may have changed the results of tests */
623 +               clean_cond_cache(srv, con);
624 +       }
625 +       return HANDLER_GO_ON;
626 +}
627 +
628 +
629 +/* this function is called at dlopen() time and inits the callbacks */
630 +
631 +int mod_extforward_plugin_init(plugin *p) {
632 +       p->version     = LIGHTTPD_VERSION_ID;
633 +       p->name        = buffer_init_string("extforward");
634 +
635 +       p->init        = mod_extforward_init;
636 +       p->handle_uri_raw = mod_extforward_uri_handler;
637 +       p->handle_request_done = mod_extforward_restore;
638 +       p->connection_reset = mod_extforward_restore;
639 +       p->set_defaults  = mod_extforward_set_defaults;
640 +       p->cleanup     = mod_extforward_free;
641 +
642 +       p->data        = NULL;
643 +
644 +       return 0;
645 +}
646 +
647
648 Property changes on: src/mod_extforward.c
649 ___________________________________________________________________
650 Name: svn:eol-style
651    + native
652
653 Index: src/Makefile.am
654 ===================================================================
655 --- src/Makefile.am     (.../tags/lighttpd-1.4.13)      (revision 1706)
656 +++ src/Makefile.am     (.../branches/lighttpd-1.4.x)   (revision 1706)
657 @@ -199,6 +199,11 @@
658  mod_fastcgi_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
659  mod_fastcgi_la_LIBADD = $(common_libadd)
660  
661 +lib_LTLIBRARIES += mod_extforward.la
662 +mod_extforward_la_SOURCES = mod_extforward.c
663 +mod_extforward_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
664 +mod_extforward_la_LIBADD = $(common_libadd)
665 +
666  lib_LTLIBRARIES += mod_access.la
667  mod_access_la_SOURCES = mod_access.c
668  mod_access_la_LDFLAGS = -module -export-dynamic -avoid-version -no-undefined
669 Index: src/network_writev.c
670 ===================================================================
671 --- src/network_writev.c        (.../tags/lighttpd-1.4.13)      (revision 1706)
672 +++ src/network_writev.c        (.../branches/lighttpd-1.4.x)   (revision 1706)
673 @@ -55,7 +55,7 @@
674                         const size_t max_chunks = MAX_IOVEC;
675  #elif defined(UIO_MAXIOV) /* Linux x86 (glibc-2.2.5-233) */
676                         const size_t max_chunks = UIO_MAXIOV;
677 -#elif (defined(__FreeBSD__) && __FreeBSD_version < 500000) /* FreeBSD 4.x */
678 +#elif (defined(__FreeBSD__) && __FreeBSD_version < 500000) || defined(__DragonFly__) /* FreeBSD 4.x */
679                         const size_t max_chunks = 1024; /* UIO_MAXIOV value from sys/uio.h */
680  #else
681  #error "sysconf() doesnt return _SC_IOV_MAX ..., check the output of 'man writev' for the EINVAL error and send the output to jan@kneschke.de"
682 Index: src/mod_expire.c
683 ===================================================================
684 --- src/mod_expire.c    (.../tags/lighttpd-1.4.13)      (revision 1706)
685 +++ src/mod_expire.c    (.../branches/lighttpd-1.4.x)   (revision 1706)
686 @@ -85,7 +85,7 @@
687         /*
688          * parse
689          *
690 -        * '(access|modification) [plus] {<num> <type>}*'
691 +        * '(access|now|modification) [plus] {<num> <type>}*'
692          *
693          * e.g. 'access 1 years'
694          */
695 @@ -101,6 +101,9 @@
696         if (0 == strncmp(ts, "access ", 7)) {
697                 type  = 0;
698                 ts   += 7;
699 +       } else if (0 == strncmp(ts, "now ", 4)) {
700 +               type  = 0;
701 +               ts   += 4;
702         } else if (0 == strncmp(ts, "modification ", 13)) {
703                 type  = 1;
704                 ts   += 13;
705 @@ -116,7 +119,7 @@
706                 ts   += 5;
707         }
708  
709 -       /* the rest is just <number> (years|months|days|hours|minutes|seconds) */
710 +       /* the rest is just <number> (years|months|weeks|days|hours|minutes|seconds) */
711         while (1) {
712                 char *space, *err;
713                 int num;
714 @@ -148,6 +151,9 @@
715                         } else if (slen == 6 &&
716                                    0 == strncmp(ts, "months", slen)) {
717                                 num *= 60 * 60 * 24 * 30;
718 +                       } else if (slen == 5 &&
719 +                                  0 == strncmp(ts, "weeks", slen)) {
720 +                               num *= 60 * 60 * 24 * 7;
721                         } else if (slen == 4 &&
722                                    0 == strncmp(ts, "days", slen)) {
723                                 num *= 60 * 60 * 24;
724 @@ -174,6 +180,8 @@
725                                 num *= 60 * 60 * 24 * 30 * 12;
726                         } else if (0 == strcmp(ts, "months")) {
727                                 num *= 60 * 60 * 24 * 30;
728 +                       } else if (0 == strcmp(ts, "weeks")) {
729 +                               num *= 60 * 60 * 24 * 7;
730                         } else if (0 == strcmp(ts, "days")) {
731                                 num *= 60 * 60 * 24;
732                         } else if (0 == strcmp(ts, "hours")) {
733 Index: src/network_freebsd_sendfile.c
734 ===================================================================
735 --- src/network_freebsd_sendfile.c      (.../tags/lighttpd-1.4.13)      (revision 1706)
736 +++ src/network_freebsd_sendfile.c      (.../branches/lighttpd-1.4.x)   (revision 1706)
737 @@ -25,7 +25,7 @@
738  
739  
740  #ifndef UIO_MAXIOV
741 -# ifdef __FreeBSD__
742 +# if defined(__FreeBSD__) || defined(__DragonFly__)
743  /* FreeBSD 4.7, 4.9 defined it in sys/uio.h only if _KERNEL is specified */
744  #  define UIO_MAXIOV 1024
745  # endif
746 Index: src/http_auth.c
747 ===================================================================
748 --- src/http_auth.c     (.../tags/lighttpd-1.4.13)      (revision 1706)
749 +++ src/http_auth.c     (.../branches/lighttpd-1.4.x)   (revision 1706)
750 @@ -733,8 +733,9 @@
751                         }
752                 }
753  
754 +               if (p->conf.auth_ldap_allow_empty_pw != 1 && pw[0] == '\0')
755 +                       return -1;
756  
757 -
758                 /* build filter */
759                 buffer_copy_string_buffer(p->ldap_filter, p->conf.ldap_filter_pre);
760                 buffer_append_string_buffer(p->ldap_filter, username);
761 Index: src/http_auth.h
762 ===================================================================
763 --- src/http_auth.h     (.../tags/lighttpd-1.4.13)      (revision 1706)
764 +++ src/http_auth.h     (.../branches/lighttpd-1.4.x)   (revision 1706)
765 @@ -36,6 +36,7 @@
766         buffer *auth_ldap_filter;
767         buffer *auth_ldap_cafile;
768         unsigned short auth_ldap_starttls;
769 +       unsigned short auth_ldap_allow_empty_pw;
770  
771         unsigned short auth_debug;
772  
773 Index: src/mod_auth.c
774 ===================================================================
775 --- src/mod_auth.c      (.../tags/lighttpd-1.4.13)      (revision 1706)
776 +++ src/mod_auth.c      (.../branches/lighttpd-1.4.x)   (revision 1706)
777 @@ -113,6 +113,7 @@
778         PATCH(auth_ldap_filter);
779         PATCH(auth_ldap_cafile);
780         PATCH(auth_ldap_starttls);
781 +       PATCH(auth_ldap_allow_empty_pw);
782  #ifdef USE_LDAP
783         PATCH(ldap);
784         PATCH(ldap_filter_pre);
785 @@ -160,6 +161,8 @@
786                                 PATCH(auth_ldap_cafile);
787                         } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.starttls"))) {
788                                 PATCH(auth_ldap_starttls);
789 +                       } else if (buffer_is_equal_string(du->key, CONST_STR_LEN("auth.backend.ldap.allow-empty-pw"))) {
790 +                               PATCH(auth_ldap_allow_empty_pw);
791                         }
792                 }
793         }
794 @@ -312,6 +315,7 @@
795                 { "auth.backend.ldap.starttls",     NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
796                 { "auth.backend.ldap.bind-dn",      NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
797                 { "auth.backend.ldap.bind-pw",      NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION }, /* 10 */
798 +               { "auth.backend.ldap.allow-empty-pw",     NULL, T_CONFIG_BOOLEAN, T_CONFIG_SCOPE_CONNECTION },
799                 { "auth.backend.htdigest.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
800                 { "auth.backend.htpasswd.userfile", NULL, T_CONFIG_STRING, T_CONFIG_SCOPE_CONNECTION },
801                 { "auth.debug",                     NULL, T_CONFIG_SHORT, T_CONFIG_SCOPE_CONNECTION },  /* 13 */
802 @@ -359,11 +363,12 @@
803                 cv[6].destination = s->auth_ldap_filter;
804                 cv[7].destination = s->auth_ldap_cafile;
805                 cv[8].destination = &(s->auth_ldap_starttls);
806 -               cv[9].destination = s->auth_ldap_binddn;
807 -               cv[10].destination = s->auth_ldap_bindpw;
808 -               cv[11].destination = s->auth_htdigest_userfile;
809 -               cv[12].destination = s->auth_htpasswd_userfile;
810 -               cv[13].destination = &(s->auth_debug);
811 +               cv[9].destination = s->auth_ldap_binddn;
812 +               cv[10].destination = s->auth_ldap_bindpw;
813 +               cv[11].destination = &(s->auth_ldap_allow_empty_pw);
814 +               cv[12].destination = s->auth_htdigest_userfile;
815 +               cv[13].destination = s->auth_htpasswd_userfile;
816 +               cv[14].destination = &(s->auth_debug);
817  
818                 p->config_storage[i] = s;
819                 ca = ((data_config *)srv->config_context->data[i])->value;
820 Index: src/mod_fastcgi.c
821 ===================================================================
822 --- src/mod_fastcgi.c   (.../tags/lighttpd-1.4.13)      (revision 1706)
823 +++ src/mod_fastcgi.c   (.../branches/lighttpd-1.4.x)   (revision 1706)
824 @@ -275,6 +275,7 @@
825         buffer *key; /* like .php */
826  
827         int note_is_sent;
828 +       int last_used_ndx;
829  
830         fcgi_extension_host **hosts;
831  
832 @@ -563,6 +564,7 @@
833                 fe = calloc(1, sizeof(*fe));
834                 assert(fe);
835                 fe->key = buffer_init();
836 +               fe->last_used_ndx = -1;
837                 buffer_copy_string_buffer(fe->key, key);
838  
839                 /* */
840 @@ -2365,6 +2367,7 @@
841          * check how much we have to read
842          */
843         if (ioctl(hctx->fd, FIONREAD, &toread)) {
844 +               if (errno == EAGAIN) return 0;
845                 log_error_write(srv, __FILE__, __LINE__, "sd",
846                                 "unexpected end-of-file (perhaps the fastcgi process died):",
847                                 fcgi_fd);
848 @@ -2375,12 +2378,23 @@
849  
850         if (toread > 0) {
851                 buffer *b;
852 +               chunk *cq_first = hctx->rb->first;
853 +               chunk *cq_last = hctx->rb->last;
854  
855                 b = chunkqueue_get_append_buffer(hctx->rb);
856                 buffer_prepare_copy(b, toread + 1);
857  
858                 /* append to read-buffer */
859                 if (-1 == (r = read(hctx->fd, b->ptr, toread))) {
860 +                       if (errno == EAGAIN) {
861 +                               /* roll back the last chunk allocation,
862 +                                   and continue on next iteration        */
863 +                               buffer_free(hctx->rb->last->mem);
864 +                               free(hctx->rb->last);
865 +                               hctx->rb->first = cq_first;
866 +                               hctx->rb->last = cq_last;
867 +                               return 0;
868 +                       }
869                         log_error_write(srv, __FILE__, __LINE__, "sds",
870                                         "unexpected end-of-file (perhaps the fastcgi process died):",
871                                         fcgi_fd, strerror(errno));
872 @@ -2393,6 +2407,7 @@
873                 b->used = r + 1; /* one extra for the fake \0 */
874                 b->ptr[b->used - 1] = '\0';
875         } else {
876 +               if (errno == EAGAIN) return 0;
877                 log_error_write(srv, __FILE__, __LINE__, "ssdsb",
878                                 "unexpected end-of-file (perhaps the fastcgi process died):",
879                                 "pid:", proc->pid,
880 @@ -2499,6 +2514,8 @@
881                         }
882                         break;
883                 case FCGI_STDERR:
884 +                       if (packet.len == 0) break;
885 +
886                         log_error_write(srv, __FILE__, __LINE__, "sb",
887                                         "FastCGI-stderr:", packet.b);
888  
889 @@ -2979,17 +2996,23 @@
890                 size_t k;
891                 int ndx, used = -1;
892  
893 -               /* get best server */
894 -               for (k = 0, ndx = -1; k < hctx->ext->used; k++) {
895 -                       host = hctx->ext->hosts[k];
896 +               /* check if the next server has no load. */
897 +               ndx = hctx->ext->last_used_ndx + 1;
898 +               if(ndx >= hctx->ext->used || ndx < 0) ndx = 0;
899 +               host = hctx->ext->hosts[ndx];
900 +               if (host->load > 0) {
901 +                       /* get backend with the least load. */
902 +                       for (k = 0, ndx = -1; k < hctx->ext->used; k++) {
903 +                               host = hctx->ext->hosts[k];
904  
905 -                       /* we should have at least one proc that can do something */
906 -                       if (host->active_procs == 0) continue;
907 +                               /* we should have at least one proc that can do something */
908 +                               if (host->active_procs == 0) continue;
909  
910 -                       if (used == -1 || host->load < used) {
911 -                               used = host->load;
912 +                               if (used == -1 || host->load < used) {
913 +                                       used = host->load;
914  
915 -                               ndx = k;
916 +                                       ndx = k;
917 +                               }
918                         }
919                 }
920  
921 @@ -3005,6 +3028,7 @@
922                         return HANDLER_FINISHED;
923                 }
924  
925 +               hctx->ext->last_used_ndx = ndx;
926                 host = hctx->ext->hosts[ndx];
927  
928                 /*
929 Index: src/server.c
930 ===================================================================
931 --- src/server.c        (.../tags/lighttpd-1.4.13)      (revision 1706)
932 +++ src/server.c        (.../branches/lighttpd-1.4.x)   (revision 1706)
933 @@ -163,6 +163,7 @@
934  #undef CLEAN
935  
936         for (i = 0; i < FILE_CACHE_MAX; i++) {
937 +               srv->mtime_cache[i].mtime = (time_t)-1;
938                 srv->mtime_cache[i].str = buffer_init();
939         }
940  
941 @@ -1231,6 +1232,19 @@
942                                                 srv_socket->fd = -1;
943  
944                                                 /* network_close() will cleanup after us */
945 +
946 +                                               if (srv->srvconf.pid_file->used &&
947 +                                                   srv->srvconf.changeroot->used == 0) {
948 +                                                       if (0 != unlink(srv->srvconf.pid_file->ptr)) {
949 +                                                               if (errno != EACCES && errno != EPERM) {
950 +                                                                       log_error_write(srv, __FILE__, __LINE__, "sbds",
951 +                                                                                       "unlink failed for:",
952 +                                                                                       srv->srvconf.pid_file,
953 +                                                                                       errno,
954 +                                                                                       strerror(errno));
955 +                                                               }
956 +                                                       }
957 +                                               }
958                                         }
959                                 }
960  
961 @@ -1335,7 +1349,8 @@
962         }
963  
964         if (srv->srvconf.pid_file->used &&
965 -           srv->srvconf.changeroot->used == 0) {
966 +           srv->srvconf.changeroot->used == 0 &&
967 +           0 == graceful_shutdown) {
968                 if (0 != unlink(srv->srvconf.pid_file->ptr)) {
969                         if (errno != EACCES && errno != EPERM) {
970                                 log_error_write(srv, __FILE__, __LINE__, "sbds",
971 Index: doc/extforward.txt
972 ===================================================================
973 --- doc/extforward.txt  (.../tags/lighttpd-1.4.13)      (revision 0)
974 +++ doc/extforward.txt  (.../branches/lighttpd-1.4.x)   (revision 1706)
975 @@ -0,0 +1,96 @@
976 +==============
977 +mod_extforward
978 +==============
979 +
980 +.. contents::
981 +
982 +Overview
983 +========
984 +
985 +Comman Kang <comman.kang at gmail.com> sent me: ::
986 +
987 +  Hello jan.
988 +
989 +       I've made something rough but similar to mod_extract_forwarded for
990 +  Apache.  This module will extract the client's "real" ip from
991 +  X-Forwarded-For header which is added by squid or other proxies. It might be
992 +  useful for servers behind reverse proxy servers.
993 +
994 +       However, this module is causing segfault with mod_ssl or
995 +  $HTTP{''socket"} directive,  crashing in config_check_cond while patching
996 +  connection ,  I do not understand architecture of the lighttpd well, does it
997 +  need to call patch_connection in either handle_request_done and
998 +  connection_reset ?
999 +
1000 +Lionel Elie Mamane <lionel@mamane.lu> improved the patch: ::
1001 +
1002 +    I've taken lighttpd-1.4.10-mod_extforward.c from the wiki and I've
1003 +  extended it. Here is the result.
1004 +
1005 +  Major changes:
1006 +
1007 +   - IPv6 support
1008 +
1009 +   - Fixed at least one segfault with SERVER['socket']
1010 +
1011 +   - Arrange things so that a url.access-deny under scope of a
1012 +     HTTP['remoteip'] condition works well :)
1013 +
1014 +  I've commented the code in some places, mostly where I wasn't sure
1015 +  what was going on, or I didn't see what the original author meant to
1016 +  do.
1017 +
1018 +Options
1019 +=======
1020 +
1021 +extforward.forwarder
1022 +  Sets trust level of proxy IP's.
1023 +
1024 +  Default: empty
1025 +
1026 +  Example: ::
1027 +    
1028 +    extforward.forwarder = ("10.0.0.232" => "trust")
1029 +
1030 +  will translate ip addresses coming from 10.0.0.232 to real ip addresses extracted from X-Forwarded-For: HTTP request header.
1031 +
1032 +Note
1033 +=======
1034 +
1035 +The effect of this module is variable on $HTTP["remotip"] directives and other module's remote ip dependent actions.
1036 +Things done by modules before we change the remoteip or after we reset it will match on the proxy's IP.
1037 +Things done in between these two moments will match on the real client's IP.
1038 +The moment things are done by a module depends on in which hook it does things and within the same hook
1039 +on whether they are before/after us in the module loading order
1040 +(order in the server.modules directive in the config file).
1041 +
1042 +Tested behaviours:
1043 +
1044 +  mod_access: Will match on the real client.
1045 +
1046 +  mod_accesslog:
1047 +   In order to see the "real" ip address in access log ,
1048 +   you'll have to load mod_extforward after mod_accesslog.
1049 +   like this: ::
1050 +
1051 +    server.modules  = (
1052 +       .....
1053 +       mod_accesslog,
1054 +       mod_extforward
1055 +    )
1056 +
1057 +Samples
1058 +=======
1059 +
1060 +Trust proxy 10.0.0.232 and 10.0.0.232 ::
1061 +
1062 +  extforward.forwarder = (
1063 +     "10.0.0.232" => "trust",
1064 +     "10.0.0.233" => "trust",
1065 +  )
1066 +
1067 +Trust all proxies  (NOT RECOMMENDED!) ::
1068 +
1069 +  extforward.forwarder = ( "all" => "trust")
1070 +
1071 +Note that "all" has precedence over specific entries, so "all except" setups will not work.
1072 Index: doc/Makefile.am
1073 ===================================================================
1074 --- doc/Makefile.am     (.../tags/lighttpd-1.4.13)      (revision 1706)
1075 +++ doc/Makefile.am     (.../branches/lighttpd-1.4.x)   (revision 1706)
1076 @@ -6,6 +6,7 @@
1077  cgi.txt \
1078  compress.txt \
1079  configuration.txt \
1080 +extforward.txt \
1081  fastcgi-state.txt \
1082  fastcgi.txt \
1083  features.txt \
1084 @@ -43,6 +44,7 @@
1085          cgi.html \
1086          compress.html \
1087          configuration.html \
1088 +        extforward.html \
1089          fastcgi-state.html \
1090          fastcgi.html \
1091          features.html \
1092 Index: NEWS
1093 ===================================================================
1094 --- NEWS        (.../tags/lighttpd-1.4.13)      (revision 1706)
1095 +++ NEWS        (.../branches/lighttpd-1.4.x)   (revision 1706)
1096 @@ -3,6 +3,9 @@
1097  NEWS
1098  ====
1099  
1100 +- 1.4.14 - ???
1101 +  * added mod_extforward module [1665]
1102 +
1103  - 1.4.13 - 2006-10-09
1104  
1105    * added initgroups in spawn-fcgi (#871)
1106
1107 Property changes on: .
1108 ___________________________________________________________________
1109 Name: svk:merge
1110    + a98e19e4-a712-0410-8832-6551a15ffc53:/local/branches/lighttpd-1.4.x:1557
1111
This page took 0.173087 seconds and 4 git commands to generate.