~ps10gel/ubuntu/xenial/trafficserver/6.2.0

« back to all changes in this revision

Viewing changes to test/plugin/INKHttpHooksTrans/INKHttpTxnIPAddress.cc

  • 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
#include "ts.h"
 
26
#include "ink_assert.h"
 
27
#include <netdb.h>
 
28
#include <netinet/in.h>
 
29
#include <sys/socket.h>
 
30
#include <string.h>
 
31
#include <stdio.h>
 
32
#include <stdlib.h>
 
33
 
 
34
 
 
35
/* cvrt unsigned int address to dotted decimal address
 
36
 * delete on the otherside, otherwise: don't care
 
37
*/
 
38
char *
 
39
uint2ddip(unsigned int addr)
 
40
{
 
41
  char *ptr = (char *) TSmalloc(64);
 
42
  if (!ptr)
 
43
    return NULL;
 
44
 
 
45
  unsigned int address = addr;
 
46
  unsigned char *ip = (unsigned char *) &address;
 
47
 
 
48
  sprintf(ptr, "%d.%d.%d.%d", (unsigned int) ip[0], (unsigned int) ip[1], (unsigned int) ip[2], (unsigned int) ip[3]);
 
49
 
 
50
  return ptr;
 
51
}
 
52
 
 
53
 
 
54
/* Set in TSPluginInit */
 
55
typedef struct parentProxyInfo
 
56
{
 
57
  char parentProxyp[BUFSIZ];
 
58
  int parentPort;
 
59
} parentProxyInfo_t;
 
60
 
 
61
static int
 
62
handle_SEND_REQUEST(TSCont contp, TSEvent event, void *eData)
 
63
{
 
64
  TSHttpTxn txnp = (TSHttpTxn *) eData;
 
65
  unsigned int nextHopIP = 0;
 
66
  int err = 0;
 
67
  char *ipAddrp = NULL;
 
68
 
 
69
  /* Origin Server (destination) or Parent IP
 
70
   * TODO use return addr with an actual network library routine (gethostbyaddr) to validate addr
 
71
   * TODO tests with an actual parent proxy
 
72
   */
 
73
  nextHopIP = TSHttpTxnNextHopIPGet(txnp);
 
74
  if (!nextHopIP) {
 
75
    TSDebug("TSHttpTxnIPAddress", "TSHttpTxnNextHopIPGet failed");
 
76
    return ++err;
 
77
  }
 
78
  ipAddrp = uint2ddip(nextHopIP);
 
79
  TSDebug("TSHttpTxnIPAddress", "TSHttpTxnNextHopIPGet passed for %s", ipAddrp ? ipAddrp : "NULL ptr!");
 
80
  TSfree(ipAddrp);
 
81
  /* TODO validate this IP address, not just an integer value
 
82
   * see below
 
83
   */
 
84
  return err;
 
85
}
 
86
 
 
87
 
 
88
/* Test:
 
89
* TSHttpTxnClientReqGet
 
90
* TSHttpTxnServerIPGet (specific)
 
91
* TSHttpHdrUrlGet
 
92
* TSUrlHostGet
 
93
* Test is to use the address returend by TSHttpTxnServerIPGet
 
94
* with a standard network interface api and compare that
 
95
* host with the hostname found in the request URL.
 
96
*/
 
97
static int
 
98
handle_OS_DNS(TSCont contp, TSEvent event, void *eData)
 
99
{
 
100
  unsigned int os_ip;
 
101
  TSHttpTxn txnp = (TSHttpTxn *) eData;
 
102
  struct in_addr inAddr;
 
103
  struct hostent *hostEntp = NULL;
 
104
  int err = 0;
 
105
  const char *reqURLHost = NULL;
 
106
  int hostLen = 0;
 
107
  char strTokenp = '.';         /* URLs separated by this token */
 
108
  char *domain_os_ip = NULL, *domain_url = NULL;
 
109
  TSMBuffer buf;
 
110
  unsigned int nextHopIP;
 
111
  TSMLoc loc, hdrLoc;
 
112
  char *ptr = NULL;
 
113
 
 
114
  /* See: handle_SEND_REQUEST(): nextHopIP = TSHttpTxnNextHopIPGet(txnp);
 
115
   */
 
116
  os_ip = TSHttpTxnServerIPGet(txnp);
 
117
  if (os_ip) {
 
118
    inAddr.s_addr = os_ip;
 
119
    hostEntp = gethostbyaddr((const char *) &inAddr, sizeof(struct in_addr), AF_INET);
 
120
    if (!hostEntp) {
 
121
      ptr = uint2ddip(os_ip);
 
122
      /* failure */
 
123
      TSDebug("TSHttpTxnIPAddress", "TSHttpTxnServerIPGet: gethostbyaddr failed for %s", ptr ? ptr : "NULL ptr!");
 
124
      TSfree(ptr);
 
125
      return ++err;
 
126
    }
 
127
  } else {
 
128
    /* failure */
 
129
    TSDebug("TSHttpTxnIPAddress", "TSHttpTxnServerIPGet: gethostbyaddr no hostname");
 
130
    ++err;
 
131
  }
 
132
  if (!TSHttpTxnClientReqGet(txnp, &buf, &loc)) {
 
133
    /* failure */
 
134
    TSDebug("TSHttpTxnIPAddress", "TSHttpTxnServerIPGet: TSHttpTxnClientReqGet failed");
 
135
    return ++err;               /* ret here, else TSMHandleRelease */
 
136
  }
 
137
 
 
138
  if ((hdrLoc = TSHttpHdrUrlGet(buf, loc)) == NULL) {
 
139
    /* failure */
 
140
    TSDebug("TSHttpTxnIPAddress", "TSHttpTxnServerIPGet: TSHttpHdrURLGet failed");
 
141
    TSHandleMLocRelease(buf, TS_NULL_MLOC, loc);
 
142
    return ++err;               /* ret here, else TSMHandleRelease */
 
143
  }
 
144
 
 
145
  /* no memory del on reqURLHost */
 
146
  reqURLHost = TSUrlHostGet(buf, hdrLoc, &hostLen);
 
147
  if (!reqURLHost || !hostLen) {
 
148
    /* FAILURE */
 
149
    TSDebug("TSHttpTxnIPAddress", "TSHttpTxnServerIPGet: gethostbyaddr no hostname");
 
150
    TSHandleMLocRelease(buf, TS_NULL_MLOC, loc);
 
151
    return ++err;
 
152
  }
 
153
  /* compare the domains of the hostname
 
154
   * from gethostbyaddr and TSURLHostGet: e.g.:
 
155
   * w1.someGiantSite.com with a request of: www.someGiantSite.com
 
156
   */
 
157
  else {
 
158
    /* compare with domain (!host) from os_ip
 
159
     * Not using hostLen
 
160
     */
 
161
    domain_url = strchr((char *) reqURLHost, (int) strTokenp);
 
162
    domain_os_ip = strchr(hostEntp->h_name, (int) strTokenp);
 
163
 
 
164
    if (!domain_os_ip || !domain_url) {
 
165
      TSDebug("TSHttpTxnIPAddress", "TSHttpTxnServerIPGet: fail: strtok");
 
166
      ++err;
 
167
    }
 
168
    if (strncmp(++domain_os_ip, ++domain_url, BUFSIZ)) {
 
169
      TSDebug("TSHttpTxnIPAddress", "TSHttpTxnServerIPGet: fail: domain names %s != %s", domain_os_ip, domain_url);
 
170
      ++err;
 
171
    }
 
172
  }
 
173
  TSHandleMLocRelease(buf, TS_NULL_MLOC, loc);
 
174
  return err;
 
175
}
 
176
 
 
177
/* Currently not used.  Interfaces like TSHttpTxnNextHopIPGet
 
178
 * should only be called from SEND_REQUEST, inclusive, forward
 
179
*/
 
180
static int
 
181
handle_TXN_START(TSCont contp, TSEvent event, void *eData)
 
182
{
 
183
  return 0;
 
184
}
 
185
 
 
186
static int
 
187
handle_TXN_CLOSE(TSCont contp, TSEvent event, void *eData)
 
188
{
 
189
  TSMBuffer respBuf;
 
190
  TSMLoc respBufLoc;
 
191
  TSHttpTxn txnp = (TSHttpTxn) eData;
 
192
  char *hostNamep = NULL;
 
193
  void *dataPtr = NULL;
 
194
  int err = 0, re = 0;
 
195
  char **hostname = NULL;
 
196
  int hostPort = 0;
 
197
  unsigned int os_addr = 0;
 
198
  unsigned int clientIP, nextHopIP;
 
199
  int incomingPort;
 
200
  char *ipAddrp = NULL;
 
201
 
 
202
  incomingPort = TSHttpTxnClientIncomingPortGet(txnp);
 
203
  if (!incomingPort) {
 
204
    TSDebug("TSHttpTxnIPAddress", "TSHttpTxnClientIncomingPortGet failed");
 
205
    ++err;                      /* failure */
 
206
  }
 
207
  /* TODO validate this port, not just an integer value
 
208
   * see below
 
209
   */
 
210
 
 
211
  /* Client IP for a transaction (not incoming) */
 
212
  clientIP = TSHttpTxnClientIPGet(txnp);
 
213
  if (!clientIP) {
 
214
    TSDebug("TSHttpTxnIPAddress", "TSHttpTxnClientIPGet failed");
 
215
    err++;
 
216
  }
 
217
  /* TODO validate this IP address, not just an integer value
 
218
   * see below
 
219
   */
 
220
 
 
221
  /* See: handle_SEND_REQUEST(): nextHopIP = TSHttpTxnNextHopIPGet(txnp);
 
222
   *
 
223
   * If origin server was contacted, its adress
 
224
   * will be returned. Need a cach hit true/false interface ?
 
225
   *
 
226
   * Origin Server (destination) or Parent IP
 
227
   * TODO tests with an actual parent proxy
 
228
   */
 
229
  nextHopIP = TSHttpTxnNextHopIPGet(txnp);
 
230
  if (!nextHopIP) {
 
231
    /* It is the responsibility of the plug-in to store hit/miss
 
232
     * details and resolve this as TSHttpTxnNextHopIPGet failure
 
233
     * or cache miss (no o.s. contected).
 
234
     */
 
235
    TSDebug("TSHttpTxnIPAddress", "TSHttpTxnNextHopIPGet failed for or cache miss");
 
236
    err++;
 
237
  }
 
238
  /* TODO validate this IP address, not just an integer value
 
239
   * see below
 
240
   */
 
241
 
 
242
        /***********************************************************
 
243
         * Failure in the following tests will cause remaining tests
 
244
         * to not execute.
 
245
        */
 
246
  os_addr = TSHttpTxnServerIPGet(txnp);
 
247
  if (!os_addr) {
 
248
    TSDebug("TSHttpTxnIPAddress", "TSHttpTxnServerIPGet failed");
 
249
    return ++err;               /* failure */
 
250
  }
 
251
 
 
252
  hostname = (char **) TSmalloc(BUFSIZ);
 
253
  /* if parent proxy is not set: re is -1
 
254
   */
 
255
  TSHttpTxnParentProxyGet(txnp, hostname, &hostPort);
 
256
  /* TODO value of hostname when parent not set?  */
 
257
  if (hostPort == (-1) || *hostname == NULL) {
 
258
    TSDebug("TSHttpTxnIPAddress", "TSHttpTxnParentProxyGet failed");
 
259
    /* return ++err;    failure */
 
260
    /* Allow other test to continue */
 
261
  }
 
262
 
 
263
  /*
 
264
   * Get the parent/port that were set at plug-in init
 
265
   */
 
266
  dataPtr = TSContDataGet(contp);
 
267
  if (!dataPtr) {
 
268
    TSDebug("TSHttpTxnIPAddress", "TSContDataGet returned NULL pointer, cannot test TSHttpTxnParentProxySet");
 
269
    return ++err;
 
270
  }
 
271
 
 
272
  TSDebug("TSHttpTxnIPAddress",
 
273
           "Setting parent proxy to %s:%d",
 
274
           ((parentProxyInfo_t *) dataPtr)->parentProxyp, ((parentProxyInfo_t *) dataPtr)->parentPort);
 
275
 
 
276
  /* TODO how do we check return value? */
 
277
  TSHttpTxnParentProxySet(txnp,
 
278
                           ((parentProxyInfo_t *) dataPtr)->parentProxyp, ((parentProxyInfo_t *) dataPtr)->parentPort);
 
279
 
 
280
  /* parent proxy was set
 
281
   */
 
282
  TSHttpTxnParentProxyGet(txnp, hostname, &hostPort);
 
283
  if (hostPort == (-1) || *hostname == NULL) {
 
284
    TSDebug("TSHttpTxnIPAddress", "TSHttpTxnParentProxyGet failed");
 
285
    /* return ++err;    failure */
 
286
    /* Allow other test to continue */
 
287
  }
 
288
 
 
289
  /* Compare */
 
290
  if ((strncmp(*hostname,
 
291
               ((parentProxyInfo_t *) dataPtr)->parentProxyp, BUFSIZ)) ||
 
292
      ((parentProxyInfo_t *) dataPtr)->parentPort != hostPort) {
 
293
    TSDebug("TSHttpTxnIPAddress", "TSHttpTxnParentProxySet/Get failed");
 
294
    ++err;
 
295
  }
 
296
 
 
297
  TSfree(hostname);
 
298
  TSfree(hostname);
 
299
  return err;
 
300
}
 
301
 
 
302
static int
 
303
TSHttpTransaction(TSCont contp, TSEvent event, void *eData)
 
304
{
 
305
  TSHttpSsn ssnp = (TSHttpSsn) eData;
 
306
  TSHttpTxn txnp = (TSHttpTxn) eData;
 
307
  int err = 0;
 
308
  unsigned int nextHopIP = 0;
 
309
 
 
310
  switch (event) {
 
311
 
 
312
  case TS_EVENT_HTTP_SSN_START:
 
313
    TSHttpSsnHookAdd(ssnp, TS_HTTP_TXN_START_HOOK, contp);
 
314
    TSHttpSsnHookAdd(ssnp, TS_HTTP_TXN_CLOSE_HOOK, contp);
 
315
    TSHttpSsnHookAdd(ssnp, TS_HTTP_SEND_REQUEST_HDR_HOOK, contp);
 
316
    TSHttpSsnHookAdd(ssnp, TS_HTTP_OS_DNS_HOOK, contp);
 
317
 
 
318
    TSHttpSsnReenable(ssnp, TS_EVENT_HTTP_CONTINUE);
 
319
    break;
 
320
 
 
321
  case TS_EVENT_HTTP_OS_DNS:
 
322
    handle_OS_DNS(contp, event, eData);
 
323
    TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
 
324
    break;
 
325
 
 
326
  case TS_EVENT_HTTP_TXN_START:
 
327
    handle_TXN_START(contp, event, eData);
 
328
    TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
 
329
    break;
 
330
 
 
331
  case TS_EVENT_HTTP_TXN_CLOSE:
 
332
    handle_TXN_CLOSE(contp, event, eData);
 
333
    TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
 
334
    break;
 
335
 
 
336
  case TS_EVENT_HTTP_SEND_REQUEST_HDR:
 
337
    handle_SEND_REQUEST(contp, event, eData);
 
338
    TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
 
339
    break;
 
340
 
 
341
  default:
 
342
    break;
 
343
  }
 
344
  return err;
 
345
}
 
346
 
 
347
void
 
348
TSPluginInit(int argc, const char *argv[])
 
349
{
 
350
  int err = 0;
 
351
  int length = 0, argCnt = 0;
 
352
  ink_assert(argc == 3);
 
353
 
 
354
  /* Passed in as args to the plug-in  and  does not get deleted
 
355
   */
 
356
  parentProxyInfo_t *parentInfop = (parentProxyInfo_t *) TSmalloc(sizeof(parentProxyInfo_t));
 
357
 
 
358
  if (!parentInfop) {
 
359
    TSDebug("TSHttpTxnIPAddress", "TSmalloc(parentProxyInfo_t = [%d]) failed", sizeof(parentProxyInfo_t));
 
360
    TSDebug("TSHttpTxnIPAddress", "TSHttpTxnIPAddress failed and did not run");
 
361
    return;
 
362
  }
 
363
  strncpy(parentInfop->parentProxyp, argv[++argCnt], strlen(argv[argCnt]));
 
364
  parentInfop->parentPort = atoi(argv[++argCnt]);
 
365
 
 
366
  TSCont contp = TSContCreate(TSHttpTransaction, NULL);
 
367
  TSContDataSet(contp, (void *) parentInfop);  /* Used in txn */
 
368
 
 
369
  /* Never: TSfree(parentInfop);
 
370
   * if you expect to use TSContDataGet
 
371
   * not a leak since TS keeps a reference to this heap
 
372
   * space
 
373
   * Here's a leak (bad stuff man!):
 
374
   *
 
375
   *       ptr = TSmalloc() ;
 
376
   *       Init(ptr);
 
377
   *       TSConDataSet(contp, ptr);
 
378
   *
 
379
   * at some other event at a later time
 
380
   *
 
381
   *        retreivePtr = TSContDataGet(contp);
 
382
   *        newPtr = Modify(retrievePtr);
 
383
   *        TSConDataSet(contp, newPtr);
 
384
   *        TSfree(retrievedPtr);                if not freed, leak
 
385
   */
 
386
 
 
387
  TSHttpHookAdd(TS_HTTP_SSN_START_HOOK, contp);
 
388
}