~ps10gel/ubuntu/xenial/trafficserver/6.2.0

« back to all changes in this revision

Viewing changes to test/plugin/redirect-1-neg/redirect-1-neg.c

  • Committer: Bazaar Package Importer
  • Author(s): Arno Toell
  • Date: 2011-01-13 11:49:18 UTC
  • Revision ID: james.westby@ubuntu.com-20110113114918-vu422h8dknrgkj15
Tags: upstream-2.1.5-unstable
ImportĀ upstreamĀ versionĀ 2.1.5-unstable

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/** @file
 
2
 
 
3
  A brief file description
 
4
 
 
5
  @section license License
 
6
 
 
7
  Licensed to the Apache Software Foundation (ASF) under one
 
8
  or more contributor license agreements.  See the NOTICE file
 
9
  distributed with this work for additional information
 
10
  regarding copyright ownership.  The ASF licenses this file
 
11
  to you under the Apache License, Version 2.0 (the
 
12
  "License"); you may not use this file except in compliance
 
13
  with the License.  You may obtain a copy of the License at
 
14
 
 
15
      http://www.apache.org/licenses/LICENSE-2.0
 
16
 
 
17
  Unless required by applicable law or agreed to in writing, software
 
18
  distributed under the License is distributed on an "AS IS" BASIS,
 
19
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
20
  See the License for the specific language governing permissions and
 
21
  limitations under the License.
 
22
 */
 
23
 
 
24
/*
 
25
 *   redirect-1.c:
 
26
 *      an example program which redirects clients based on the source IP
 
27
 *
 
28
 *
 
29
 *      Usage:
 
30
 *      (NT): Redirect.dll block_ip url_redirect
 
31
 *      (Solaris): redirect-1.so block_ip url_redirect
 
32
 *
 
33
 *
 
34
 */
 
35
 
 
36
#include <string.h>
 
37
 
 
38
#if !defined (_WIN32)
 
39
#  include <unistd.h>
 
40
#  include <netinet/in.h>
 
41
#  include <arpa/inet.h>
 
42
#else
 
43
#  include <windows.h>
 
44
#endif
 
45
 
 
46
#include "ts.h"
 
47
 
 
48
#if !defined (_WIN32)
 
49
static in_addr_t ip_deny;
 
50
#else
 
51
static unsigned int ip_deny;
 
52
#endif
 
53
 
 
54
/*
 
55
 * uncoupled statistics variables:
 
56
 */
 
57
static TSStat method_count_redirected_connect;
 
58
static TSStat method_count_redirected_delete;
 
59
static TSStat method_count_redirected_get;
 
60
static TSStat method_count_redirected_head;
 
61
static TSStat method_count_redirected_icp_query;
 
62
static TSStat method_count_redirected_options;
 
63
static TSStat method_count_redirected_post;
 
64
static TSStat method_count_redirected_purge;
 
65
static TSStat method_count_redirected_put;
 
66
static TSStat method_count_redirected_trace;
 
67
static TSStat method_count_redirected_unknown;
 
68
 
 
69
 
 
70
/*
 
71
 *      coupled statistics variables:
 
72
 *              coupled stat category for the following stats
 
73
 *              is request_outcomes. The relationship among the stats is:
 
74
 *              requests_all = requests_redirects + requests_unchanged
 
75
 */
 
76
static TSCoupledStat request_outcomes;
 
77
static TSStat requests_all;
 
78
static TSStat requests_redirects;
 
79
static TSStat requests_unchanged;
 
80
 
 
81
 
 
82
void update_redirected_method_stats(TSMBuffer bufp, TSMLoc hdr_loc);
 
83
 
 
84
static char *url_redirect;
 
85
static char *uri_redirect;
 
86
static char *block_ip;
 
87
 
 
88
#define PLUGIN_NAME "redirect-1-neg"
 
89
#define LOG_SET_FUNCTION_NAME(NAME) const char * FUNCTION_NAME = NAME
 
90
 
 
91
#define LOG_ERROR_NEG(API_NAME) { \
 
92
    TSDebug(PLUGIN_NAME, "%s: %s %s %s File %s, line number %d",PLUGIN_NAME, API_NAME, "NEGAPIFAIL", \
 
93
             FUNCTION_NAME, __FILE__, __LINE__); \
 
94
}
 
95
 
 
96
static void
 
97
handle_client_lookup(TSHttpTxn txnp, TSCont contp)
 
98
{
 
99
  TSMBuffer bufp;
 
100
  TSMLoc hdr_loc, url_loc;
 
101
  int host_length;
 
102
 
 
103
#if !defined (_WIN32)
 
104
  in_addr_t clientip;
 
105
#else
 
106
  unsigned int clientip;
 
107
#endif
 
108
 
 
109
  const char *host;
 
110
  char *clientstring;
 
111
  struct in_addr tempstruct;
 
112
 
 
113
  /*
 
114
   * Here we declare local coupled statistics variables:
 
115
   */
 
116
  TSCoupledStat local_request_outcomes;
 
117
  TSStat local_requests_all;
 
118
  TSStat local_requests_redirects;
 
119
  TSStat local_requests_unchanged;
 
120
 
 
121
  LOG_SET_FUNCTION_NAME("handle_client_lookup");
 
122
 
 
123
  /*
 
124
   *  Create local copy of the global coupled stat category:
 
125
   */
 
126
  local_request_outcomes = TSStatCoupledLocalCopyCreate("local_request_outcomes", request_outcomes);
 
127
 
 
128
 
 
129
  /*
 
130
   * Create the local copies of the global coupled stats:
 
131
   */
 
132
  local_requests_all = TSStatCoupledLocalAdd(local_request_outcomes, "requests.all.local", TSSTAT_TYPE_FLOAT);
 
133
  local_requests_redirects = TSStatCoupledLocalAdd(local_request_outcomes,
 
134
                                                    "requests.redirects.local", TSSTAT_TYPE_INT64);
 
135
  local_requests_unchanged = TSStatCoupledLocalAdd(local_request_outcomes,
 
136
                                                    "requests.unchanged.local", TSSTAT_TYPE_INT64);
 
137
 
 
138
 
 
139
  /*
 
140
   *   Increment the count of total requests:
 
141
   *     (it is more natural to treat the number of requests as an
 
142
   *      integer, but we declare this a FLOAT in order to demonstrate
 
143
   *      how to increment coupled FLOAT stats)
 
144
   */
 
145
  TSStatFloatAddTo(local_requests_all, 1.0);
 
146
 
 
147
  /* negative test */
 
148
#ifdef DEBUG
 
149
  if (TSStatCoupledLocalCopyCreate(NULL, request_outcomes) != TS_ERROR_PTR) {
 
150
    LOG_ERROR_NEG("TSStatCoupledLocalCopyCreate");
 
151
  }
 
152
  if (TSStatCoupledLocalCopyCreate("my_local_copy", NULL) != TS_ERROR_PTR) {
 
153
    LOG_ERROR_NEG("TSStatCoupledLocalCopyCreate");
 
154
  }
 
155
 
 
156
  if (TSStatCoupledLocalAdd(NULL, "requests.negtest", TSSTAT_TYPE_INT64) != TS_ERROR_PTR) {
 
157
    LOG_ERROR_NEG("TSStatCoupledLocalAdd");
 
158
  }
 
159
  if (TSStatCoupledLocalAdd(local_request_outcomes, NULL, TSSTAT_TYPE_INT64) != TS_ERROR_PTR) {
 
160
    LOG_ERROR_NEG("TSStatCoupledLocalAdd");
 
161
  }
 
162
 
 
163
  if (TSStatFloatAddTo(NULL, 1.0) != TS_ERROR) {
 
164
    LOG_ERROR_NEG("TSStatFloatAddTo");
 
165
  }
 
166
 
 
167
  if (TSHttpTxnClientIPGet(NULL) != 0) {
 
168
    LOG_ERROR_NEG("TSHttpTxnClientIPGet");
 
169
  }
 
170
#endif
 
171
 
 
172
#if !defined (_WIN32)
 
173
  clientip = (in_addr_t) TSHttpTxnClientIPGet(txnp);
 
174
#else
 
175
  clientip = TSHttpTxnClientIPGet(txnp);
 
176
#endif
 
177
 
 
178
  tempstruct.s_addr = clientip;
 
179
  clientstring = inet_ntoa(tempstruct);
 
180
  TSDebug("redirect", "clientip is %s and block_ip is %s", clientstring, block_ip);
 
181
 
 
182
  if (!TSHttpTxnClientReqGet(txnp, &bufp, &hdr_loc)) {
 
183
    TSError("couldn't retrieve client request header\n");
 
184
    goto done;
 
185
  }
 
186
 
 
187
  url_loc = TSHttpHdrUrlGet(bufp, hdr_loc);
 
188
  if (!url_loc) {
 
189
    TSError("couldn't retrieve request url\n");
 
190
    TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
 
191
    goto done;
 
192
  }
 
193
 
 
194
  host = TSUrlHostGet(bufp, url_loc, &host_length);
 
195
  if (!host) {
 
196
    TSError("couldn't retrieve request hostname\n");
 
197
    TSHandleMLocRelease(bufp, hdr_loc, url_loc);
 
198
    TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
 
199
    goto done;
 
200
  }
 
201
 
 
202
  /*
 
203
   *   Check to see if the client is already headed to the redirect site.
 
204
   */
 
205
  if (strncmp(host, url_redirect, host_length) == 0) {
 
206
    TSHandleMLocRelease(bufp, hdr_loc, url_loc);
 
207
    TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
 
208
    goto done;
 
209
  }
 
210
 
 
211
  if (ip_deny == clientip) {
 
212
 
 
213
    TSHttpTxnHookAdd(txnp, TS_HTTP_SEND_RESPONSE_HDR_HOOK, contp);
 
214
 
 
215
    update_redirected_method_stats(bufp, hdr_loc);
 
216
 
 
217
    TSHandleMLocRelease(bufp, hdr_loc, url_loc);
 
218
    TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
 
219
 
 
220
    /*
 
221
     *   Increment the local redirect stat and do global update:
 
222
     */
 
223
    TSStatIncrement(local_requests_redirects);
 
224
    TSStatsCoupledUpdate(local_request_outcomes);
 
225
    TSStatCoupledLocalCopyDestroy(local_request_outcomes);
 
226
 
 
227
    TSHttpTxnReenable(txnp, TS_EVENT_HTTP_ERROR);
 
228
    return;
 
229
  }
 
230
 
 
231
done:
 
232
  /*
 
233
   * Increment the local number unchanged stat and do global update:
 
234
   */
 
235
  TSStatIncrement(local_requests_unchanged);
 
236
  TSStatsCoupledUpdate(local_request_outcomes);
 
237
  TSStatCoupledLocalCopyDestroy(local_request_outcomes);
 
238
 
 
239
  /* negative test */
 
240
#ifdef DEBUG
 
241
  if (TSStatsCoupledUpdate(NULL) != TS_ERROR) {
 
242
    LOG_ERROR_NEG("TSStatsCoupledUpdate");
 
243
  }
 
244
  if (TSStatCoupledLocalCopyDestroy(NULL) != TS_ERROR) {
 
245
    LOG_ERROR_NEG("TSStatCoupledLocalCopyDestroy");
 
246
  }
 
247
#endif
 
248
 
 
249
  TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
 
250
}
 
251
 
 
252
 
 
253
 
 
254
static void
 
255
handle_response(TSHttpTxn txnp)
 
256
{
 
257
  TSMBuffer bufp;
 
258
  TSMLoc hdr_loc, newfield_loc;
 
259
  TSMLoc url_loc;
 
260
  char *url_str;
 
261
  char *buf;
 
262
  char *errormsg_body = "All requests from this IP address are redirected.\n";
 
263
  char *tmp_body;
 
264
 
 
265
  if (!TSHttpTxnClientRespGet(txnp, &bufp, &hdr_loc)) {
 
266
    TSError("couldn't retrieve client response header\n");
 
267
    goto done;
 
268
  }
 
269
 
 
270
  TSHttpHdrStatusSet(bufp, hdr_loc, TS_HTTP_STATUS_MOVED_PERMANENTLY);
 
271
  TSHttpHdrReasonSet(bufp, hdr_loc,
 
272
                      TSHttpHdrReasonLookup(TS_HTTP_STATUS_MOVED_PERMANENTLY),
 
273
                      strlen(TSHttpHdrReasonLookup(TS_HTTP_STATUS_MOVED_PERMANENTLY)));
 
274
 
 
275
  newfield_loc = TSMimeHdrFieldCreate(bufp, hdr_loc);
 
276
  TSMimeHdrFieldNameSet(bufp, hdr_loc, newfield_loc, TS_MIME_FIELD_LOCATION, TS_MIME_LEN_LOCATION);
 
277
  TSMimeHdrFieldValueStringInsert(bufp, hdr_loc, newfield_loc, uri_redirect, strlen(uri_redirect), -1);
 
278
  TSMimeHdrFieldAppend(bufp, hdr_loc, newfield_loc);
 
279
 
 
280
 
 
281
  /*
 
282
   *  Note that we can't directly use errormsg_body, as TSHttpTxnErrorBodySet()
 
283
   *  will try to free the passed buffer with TSfree().
 
284
   */
 
285
  tmp_body = TSstrdup(errormsg_body);
 
286
  TSHttpTxnErrorBodySet(txnp, tmp_body, strlen(tmp_body), NULL);
 
287
  TSHandleMLocRelease(bufp, hdr_loc, newfield_loc);
 
288
  TSHandleMLocRelease(bufp, TS_NULL_MLOC, hdr_loc);
 
289
 
 
290
 
 
291
done:
 
292
  TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
 
293
}
 
294
 
 
295
 
 
296
 
 
297
static int
 
298
redirect_plugin(TSCont contp, TSEvent event, void *edata)
 
299
{
 
300
 
 
301
  TSHttpTxn txnp = (TSHttpTxn) edata;
 
302
 
 
303
  switch (event) {
 
304
  case TS_EVENT_HTTP_READ_REQUEST_HDR:
 
305
 
 
306
    handle_client_lookup(txnp, contp);
 
307
    return 0;
 
308
 
 
309
  case TS_EVENT_HTTP_SEND_RESPONSE_HDR:
 
310
 
 
311
    handle_response(txnp);
 
312
    return 0;
 
313
 
 
314
  default:
 
315
    break;
 
316
  }
 
317
 
 
318
  return 0;
 
319
}
 
320
 
 
321
 
 
322
 
 
323
/*
 
324
 *  Global statistics functions:
 
325
 */
 
326
 
 
327
void
 
328
init_stats(void)
 
329
{
 
330
  LOG_SET_FUNCTION_NAME("init_stats");
 
331
 
 
332
  /* noncoupled: */
 
333
  method_count_redirected_connect = TSStatCreate("method.count.redirected.connect", TSSTAT_TYPE_INT64);
 
334
  method_count_redirected_delete = TSStatCreate("method.count.redirected.delete", TSSTAT_TYPE_INT64);
 
335
  method_count_redirected_get = TSStatCreate("method.count.redirected.get", TSSTAT_TYPE_INT64);
 
336
  method_count_redirected_head = TSStatCreate("method.count.redirected.head", TSSTAT_TYPE_FLOAT);
 
337
  method_count_redirected_icp_query = TSStatCreate("method.count.redirected.icp_query", TSSTAT_TYPE_FLOAT);
 
338
  method_count_redirected_options = TSStatCreate("method.count.redirected.options", TSSTAT_TYPE_INT64);
 
339
  method_count_redirected_post = TSStatCreate("method.count.redirected.post", TSSTAT_TYPE_INT64);
 
340
  method_count_redirected_purge = TSStatCreate("method.count.redirected.purge", TSSTAT_TYPE_INT64);
 
341
  method_count_redirected_put = TSStatCreate("method.count.redirected.put", TSSTAT_TYPE_INT64);
 
342
  method_count_redirected_trace = TSStatCreate("method.count.redirected.trace", TSSTAT_TYPE_INT64);
 
343
  method_count_redirected_unknown = TSStatCreate("method.count.redirected.unknown", TSSTAT_TYPE_INT64);
 
344
 
 
345
  /* coupled: */
 
346
  request_outcomes = TSStatCoupledGlobalCategoryCreate("request_outcomes");
 
347
  requests_all = TSStatCoupledGlobalAdd(request_outcomes, "requests.all", TSSTAT_TYPE_FLOAT);
 
348
  requests_redirects = TSStatCoupledGlobalAdd(request_outcomes, "requests.redirects", TSSTAT_TYPE_INT64);
 
349
  requests_unchanged = TSStatCoupledGlobalAdd(request_outcomes, "requests.unchanged", TSSTAT_TYPE_INT64);
 
350
 
 
351
  /* negative test */
 
352
#ifdef DEBUG
 
353
  if (TSStatCoupledGlobalCategoryCreate(NULL) != TS_ERROR_PTR) {
 
354
    LOG_ERROR_NEG("TSStatCoupledGlobalCategoryCreate");
 
355
  }
 
356
 
 
357
  if (TSStatCoupledGlobalAdd(NULL, "requests.mytest", TSSTAT_TYPE_INT64) != TS_ERROR_PTR) {
 
358
    LOG_ERROR_NEG("TSStatCoupledGlobalAdd");
 
359
  }
 
360
  if (TSStatCoupledGlobalAdd(request_outcomes, NULL, TSSTAT_TYPE_INT64) != TS_ERROR_PTR) {
 
361
    LOG_ERROR_NEG("TSStatCoupledGlobalAdd");
 
362
  }
 
363
#endif
 
364
}
 
365
 
 
366
/*
 
367
 *      This function is only called for redirected requests.  It illustrates
 
368
 *      several different ways of updating INT64 stats.  Some may consider
 
369
 *      the particular use of TSDecrementStat() shown below somewhat contrived.
 
370
 */
 
371
void
 
372
update_redirected_method_stats(TSMBuffer bufp, TSMLoc hdr_loc)
 
373
{
 
374
  const char *txn_method;
 
375
  int length;
 
376
  TS64 tempint;
 
377
 
 
378
  LOG_SET_FUNCTION_NAME("update_redirected_method_stats");
 
379
 
 
380
  txn_method = TSHttpHdrMethodGet(bufp, hdr_loc, &length);
 
381
 
 
382
  if (NULL != txn_method) {
 
383
    if (0 == strncmp(txn_method, TS_HTTP_METHOD_CONNECT, length))
 
384
      TSStatIncrement(method_count_redirected_connect);
 
385
    else if (0 == strncmp(txn_method, TS_HTTP_METHOD_DELETE, length))
 
386
      TSStatIncrement(method_count_redirected_delete);
 
387
    else if (0 == strncmp(txn_method, TS_HTTP_METHOD_GET, length))
 
388
      TSStatIncrement(method_count_redirected_get);
 
389
 
 
390
    else if (0 == strncmp(txn_method, TS_HTTP_METHOD_HEAD, length))
 
391
      TSStatFloatAddTo(method_count_redirected_head, 1);
 
392
    else if (0 == strncmp(txn_method, TS_HTTP_METHOD_ICP_QUERY, length))
 
393
      TSStatFloatAddTo(method_count_redirected_icp_query, 1);
 
394
 
 
395
    else if (0 == strncmp(txn_method, TS_HTTP_METHOD_OPTIONS, length)) {
 
396
      TSStatIntGet(method_count_redirected_options, tempint);
 
397
      tempint++;
 
398
      TSStatIntSet(method_count_redirected_options, tempint);
 
399
    } else if (0 == strncmp(txn_method, TS_HTTP_METHOD_POST, length)) {
 
400
      TSStatDecrement(method_count_redirected_post);
 
401
      TSStatIncrement(method_count_redirected_post);
 
402
      TSStatIncrement(method_count_redirected_post);
 
403
    }
 
404
 
 
405
    else if (0 == strncmp(txn_method, TS_HTTP_METHOD_PURGE, length))
 
406
      TSStatIncrement(method_count_redirected_purge);
 
407
    else if (0 == strncmp(txn_method, TS_HTTP_METHOD_PUT, length))
 
408
      TSStatIncrement(method_count_redirected_put);
 
409
    else if (0 == strncmp(txn_method, TS_HTTP_METHOD_TRACE, length))
 
410
      TSStatIncrement(method_count_redirected_trace);
 
411
    else
 
412
      TSStatIncrement(method_count_redirected_unknown);
 
413
  }
 
414
 
 
415
  /* negative test */
 
416
#ifdef DEBUG
 
417
  if (TSStatIntSet(NULL, 0) != TS_ERROR) {
 
418
    LOG_ERROR_NEG("TSStatIntSet");
 
419
  }
 
420
 
 
421
  if (TSStatDecrement(NULL) != TS_ERROR) {
 
422
    LOG_ERROR_NEG("TSStatDecrement");
 
423
  }
 
424
#endif
 
425
 
 
426
}
 
427
 
 
428
int
 
429
check_ts_version()
 
430
{
 
431
 
 
432
  const char *ts_version = TSTrafficServerVersionGet();
 
433
  int result = 0;
 
434
 
 
435
  if (ts_version) {
 
436
    int major_ts_version = 0;
 
437
    int minor_ts_version = 0;
 
438
    int patch_ts_version = 0;
 
439
 
 
440
    if (sscanf(ts_version, "%d.%d.%d", &major_ts_version, &minor_ts_version, &patch_ts_version) != 3) {
 
441
      return 0;
 
442
    }
 
443
 
 
444
    /* Since this is an TS-SDK 2.0 plugin, we need at
 
445
       least Traffic Server 2.0 to run */
 
446
    if (major_ts_version >= 2) {
 
447
      result = 1;
 
448
    }
 
449
  }
 
450
 
 
451
  return result;
 
452
}
 
453
 
 
454
void
 
455
TSPluginInit(int argc, const char *argv[])
 
456
{
 
457
  const char prefix[] = "http://";
 
458
  int uri_len;
 
459
  TSPluginRegistrationInfo info;
 
460
 
 
461
  info.plugin_name = "redirect-1";
 
462
  info.vendor_name = "MyCompany";
 
463
  info.support_email = "ts-api-support@MyCompany.com";
 
464
 
 
465
  if (!TSPluginRegister(TS_SDK_VERSION_3_0, &info)) {
 
466
    TSError("Plugin registration failed.\n");
 
467
  }
 
468
 
 
469
  if (!check_ts_version()) {
 
470
    TSError("Plugin requires Traffic Server 3.0 or later\n");
 
471
    return;
 
472
  }
 
473
 
 
474
  if (argc == 3) {
 
475
    block_ip = TSstrdup(argv[1]);
 
476
 
 
477
    /*
 
478
     *   The Location header must contain an absolute URI:
 
479
     */
 
480
 
 
481
    url_redirect = TSstrdup(argv[2]);
 
482
    uri_len = strlen(prefix) + strlen(url_redirect) + 1;
 
483
    uri_redirect = TSmalloc(uri_len);
 
484
    strcpy(uri_redirect, prefix);
 
485
    strcat(uri_redirect, url_redirect);
 
486
 
 
487
  } else {
 
488
    TSError("Incorrect syntax in plugin.conf:  correct usage is" "redirect-1.so ip_deny url_redirect");
 
489
    return;
 
490
  }
 
491
 
 
492
  ip_deny = inet_addr(block_ip);
 
493
 
 
494
  TSHttpHookAdd(TS_HTTP_READ_REQUEST_HDR_HOOK, TSContCreate(redirect_plugin, NULL));
 
495
 
 
496
  TSDebug("redirect_init", "block_ip is %s, url_redirect is %s, and uri_redirect is %s",
 
497
           block_ip, url_redirect, uri_redirect);
 
498
  TSDebug("redirect_init", "ip_deny is %ld\n", ip_deny);
 
499
 
 
500
  TSDebug("redirect_init", "initializing stats...");
 
501
  init_stats();
 
502
 
 
503
 
 
504
  /*
 
505
   *  Demonstrate another tracing function.  This can be used to
 
506
   *  enable debug calculations and other work that should only
 
507
   *  be done in debug mode.
 
508
   */
 
509
 
 
510
  if (TSIsDebugTagSet("redirect_demo"))
 
511
    TSDebug("redirect_init", "The redirect_demo tag is set");
 
512
  else
 
513
    TSDebug("redirect_init", "The redirect_demo tag is not set");
 
514
}