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 * Filename: InkMgmtAPI.cc
26 * Purpose: This file implements all traffic server management functions.
27 * Created: 9/11/00
28 * Created by: Lan Tran
29 *
30 *
31 ***************************************************************************/
32 #include "tscore/ink_platform.h"
33 #include "tscore/ink_code.h"
34 #include "tscore/ink_memory.h"
35 #include "tscore/ParseRules.h"
36 #include <climits>
37 #include "tscore/I_Layout.h"
38
39 #include "mgmtapi.h"
40 #include "CoreAPI.h"
41 #include "CoreAPIShared.h"
42
43 #include "tscore/TextBuffer.h"
44
45 /***************************************************************************
46 * API Memory Management
47 ***************************************************************************/
48 void *
_TSmalloc(unsigned int size,const char *)49 _TSmalloc(unsigned int size, const char * /* path ATS_UNUSED */)
50 {
51 return ats_malloc(size);
52 }
53
54 void *
_TSrealloc(void * ptr,unsigned int size,const char *)55 _TSrealloc(void *ptr, unsigned int size, const char * /* path ATS_UNUSED */)
56 {
57 return ats_realloc(ptr, size);
58 }
59
60 char *
_TSstrdup(const char * str,int length,const char *)61 _TSstrdup(const char *str, int length, const char * /* path ATS_UNUSED */)
62 {
63 return ats_strndup(str, length);
64 }
65
66 void
_TSfree(void * ptr)67 _TSfree(void *ptr)
68 {
69 ats_free(ptr);
70 }
71
72 /***************************************************************************
73 * API Helper Functions for Data Carrier Structures
74 ***************************************************************************/
75
76 /*--- TSList operations -------------------------------------------------*/
77 tsapi TSList
TSListCreate(void)78 TSListCreate(void)
79 {
80 return (void *)create_queue();
81 }
82
83 /* NOTE: The List must be EMPTY */
84 tsapi void
TSListDestroy(TSList l)85 TSListDestroy(TSList l)
86 {
87 if (!l) {
88 return;
89 }
90
91 delete_queue(static_cast<LLQ *>(l));
92 return;
93 }
94
95 tsapi TSMgmtError
TSListEnqueue(TSList l,void * data)96 TSListEnqueue(TSList l, void *data)
97 {
98 int ret;
99
100 ink_assert(l && data);
101 if (!l || !data) {
102 return TS_ERR_PARAMS;
103 }
104
105 ret = enqueue(static_cast<LLQ *>(l), data); /* returns TRUE=1 or FALSE=0 */
106 if (ret == 0) {
107 return TS_ERR_FAIL;
108 } else {
109 return TS_ERR_OKAY;
110 }
111 }
112
113 tsapi void *
TSListDequeue(TSList l)114 TSListDequeue(TSList l)
115 {
116 ink_assert(l);
117 if (!l || queue_is_empty(static_cast<LLQ *>(l))) {
118 return nullptr;
119 }
120
121 return dequeue(static_cast<LLQ *>(l));
122 }
123
124 tsapi bool
TSListIsEmpty(TSList l)125 TSListIsEmpty(TSList l)
126 {
127 ink_assert(l);
128 if (!l) {
129 return true; // list doesn't exist, so it's empty
130 }
131
132 return queue_is_empty(static_cast<LLQ *>(l));
133 }
134
135 tsapi int
TSListLen(TSList l)136 TSListLen(TSList l)
137 {
138 ink_assert(l);
139 if (!l) {
140 return -1;
141 }
142
143 return queue_len(static_cast<LLQ *>(l));
144 }
145
146 tsapi bool
TSListIsValid(TSList l)147 TSListIsValid(TSList l)
148 {
149 int i, len;
150
151 if (!l) {
152 return false;
153 }
154
155 len = queue_len(static_cast<LLQ *>(l));
156 for (i = 0; i < len; i++) {
157 void *ele = dequeue(static_cast<LLQ *>(l));
158 if (!ele) {
159 return false;
160 }
161 enqueue(static_cast<LLQ *>(l), ele);
162 }
163 return true;
164 }
165
166 /*--- TSStringList operations --------------------------------------*/
167 tsapi TSStringList
TSStringListCreate()168 TSStringListCreate()
169 {
170 return (void *)create_queue(); /* this queue will be a list of char* */
171 }
172
173 /* usually, must be an empty list before destroying*/
174 tsapi void
TSStringListDestroy(TSStringList strl)175 TSStringListDestroy(TSStringList strl)
176 {
177 if (!strl) {
178 return;
179 }
180
181 /* dequeue each element and free it */
182 while (!queue_is_empty(static_cast<LLQ *>(strl))) {
183 char *str = static_cast<char *>(dequeue(static_cast<LLQ *>(strl)));
184 ats_free(str);
185 }
186
187 delete_queue(static_cast<LLQ *>(strl));
188 }
189
190 tsapi TSMgmtError
TSStringListEnqueue(TSStringList strl,char * str)191 TSStringListEnqueue(TSStringList strl, char *str)
192 {
193 int ret;
194
195 ink_assert(strl && str);
196 if (!strl || !str) {
197 return TS_ERR_PARAMS;
198 }
199
200 ret = enqueue(static_cast<LLQ *>(strl), str); /* returns TRUE=1 or FALSE=0 */
201 if (ret == 0) {
202 return TS_ERR_FAIL;
203 } else {
204 return TS_ERR_OKAY;
205 }
206 }
207
208 tsapi char *
TSStringListDequeue(TSStringList strl)209 TSStringListDequeue(TSStringList strl)
210 {
211 ink_assert(strl);
212 if (!strl || queue_is_empty(static_cast<LLQ *>(strl))) {
213 return nullptr;
214 }
215
216 return static_cast<char *>(dequeue(static_cast<LLQ *>(strl)));
217 }
218
219 tsapi bool
TSStringListIsEmpty(TSStringList strl)220 TSStringListIsEmpty(TSStringList strl)
221 {
222 ink_assert(strl);
223 if (!strl) {
224 return true;
225 }
226
227 return queue_is_empty(static_cast<LLQ *>(strl));
228 }
229
230 tsapi int
TSStringListLen(TSStringList strl)231 TSStringListLen(TSStringList strl)
232 {
233 ink_assert(strl);
234 if (!strl) {
235 return -1;
236 }
237
238 return queue_len(static_cast<LLQ *>(strl));
239 }
240
241 // returns false if any element is NULL string
242 tsapi bool
TSStringListIsValid(TSStringList strl)243 TSStringListIsValid(TSStringList strl)
244 {
245 int i, len;
246
247 if (!strl) {
248 return false;
249 }
250
251 len = queue_len(static_cast<LLQ *>(strl));
252 for (i = 0; i < len; i++) {
253 char *str = static_cast<char *>(dequeue(static_cast<LLQ *>(strl)));
254 if (!str) {
255 return false;
256 }
257 enqueue(static_cast<LLQ *>(strl), str);
258 }
259 return true;
260 }
261
262 /*--- TSIntList operations --------------------------------------*/
263 tsapi TSIntList
TSIntListCreate()264 TSIntListCreate()
265 {
266 return (void *)create_queue(); /* this queue will be a list of int* */
267 }
268
269 /* usually, must be an empty list before destroying*/
270 tsapi void
TSIntListDestroy(TSIntList intl)271 TSIntListDestroy(TSIntList intl)
272 {
273 if (!intl) {
274 return;
275 }
276
277 /* dequeue each element and free it */
278 while (!queue_is_empty(static_cast<LLQ *>(intl))) {
279 int *iPtr = static_cast<int *>(dequeue(static_cast<LLQ *>(intl)));
280 ats_free(iPtr);
281 }
282
283 delete_queue(static_cast<LLQ *>(intl));
284 return;
285 }
286
287 tsapi TSMgmtError
TSIntListEnqueue(TSIntList intl,int * elem)288 TSIntListEnqueue(TSIntList intl, int *elem)
289 {
290 int ret;
291
292 ink_assert(intl && elem);
293 if (!intl || !elem) {
294 return TS_ERR_PARAMS;
295 }
296
297 ret = enqueue(static_cast<LLQ *>(intl), elem); /* returns TRUE=1 or FALSE=0 */
298 if (ret == 0) {
299 return TS_ERR_FAIL;
300 } else {
301 return TS_ERR_OKAY;
302 }
303 }
304
305 tsapi int *
TSIntListDequeue(TSIntList intl)306 TSIntListDequeue(TSIntList intl)
307 {
308 ink_assert(intl);
309 if (!intl || queue_is_empty(static_cast<LLQ *>(intl))) {
310 return nullptr;
311 }
312
313 return static_cast<int *>(dequeue(static_cast<LLQ *>(intl)));
314 }
315
316 tsapi bool
TSIntListIsEmpty(TSIntList intl)317 TSIntListIsEmpty(TSIntList intl)
318 {
319 ink_assert(intl);
320 if (!intl) {
321 return true;
322 }
323
324 return queue_is_empty(static_cast<LLQ *>(intl));
325 }
326
327 tsapi int
TSIntListLen(TSIntList intl)328 TSIntListLen(TSIntList intl)
329 {
330 ink_assert(intl);
331 if (!intl) {
332 return -1;
333 }
334
335 return queue_len(static_cast<LLQ *>(intl));
336 }
337
338 tsapi bool
TSIntListIsValid(TSIntList intl,int min,int max)339 TSIntListIsValid(TSIntList intl, int min, int max)
340 {
341 if (!intl) {
342 return false;
343 }
344
345 for (unsigned long i = 0; i < queue_len(static_cast<LLQ *>(intl)); i++) {
346 int *item = static_cast<int *>(dequeue(static_cast<LLQ *>(intl)));
347 if (*item < min) {
348 return false;
349 }
350 if (*item > max) {
351 return false;
352 }
353 enqueue(static_cast<LLQ *>(intl), item);
354 }
355 return true;
356 }
357
358 /*--- allocate/deallocate operations --------------------------------------*/
359 tsapi TSMgmtEvent *
TSEventCreate(void)360 TSEventCreate(void)
361 {
362 TSMgmtEvent *event = static_cast<TSMgmtEvent *>(ats_malloc(sizeof(TSMgmtEvent)));
363
364 event->id = -1;
365 event->name = nullptr;
366 event->description = nullptr;
367 event->priority = TS_EVENT_PRIORITY_UNDEFINED;
368
369 return event;
370 }
371
372 tsapi void
TSEventDestroy(TSMgmtEvent * event)373 TSEventDestroy(TSMgmtEvent *event)
374 {
375 if (event) {
376 ats_free(event->name);
377 ats_free(event->description);
378 ats_free(event);
379 }
380 return;
381 }
382
383 tsapi TSRecordEle *
TSRecordEleCreate(void)384 TSRecordEleCreate(void)
385 {
386 TSRecordEle *ele = static_cast<TSRecordEle *>(ats_malloc(sizeof(TSRecordEle)));
387
388 ele->rec_name = nullptr;
389 ele->rec_type = TS_REC_UNDEFINED;
390
391 return ele;
392 }
393
394 tsapi void
TSRecordEleDestroy(TSRecordEle * ele)395 TSRecordEleDestroy(TSRecordEle *ele)
396 {
397 if (ele) {
398 ats_free(ele->rec_name);
399 if (ele->rec_type == TS_REC_STRING && ele->valueT.string_val) {
400 ats_free(ele->valueT.string_val);
401 }
402 ats_free(ele);
403 }
404 return;
405 }
406
407 /***************************************************************************
408 * API Core
409 ***************************************************************************/
410
411 /*--- host status operations ----------------------------------------------- */
412 tsapi TSMgmtError
TSHostStatusSetUp(const char * host_name,int down_time,const char * reason)413 TSHostStatusSetUp(const char *host_name, int down_time, const char *reason)
414 {
415 return HostStatusSetUp(host_name, down_time, reason);
416 }
417
418 tsapi TSMgmtError
TSHostStatusSetDown(const char * host_name,int down_time,const char * reason)419 TSHostStatusSetDown(const char *host_name, int down_time, const char *reason)
420 {
421 return HostStatusSetDown(host_name, down_time, reason);
422 }
423
424 /*--- statistics operations ----------------------------------------------- */
425 tsapi TSMgmtError
TSStatsReset(const char * name)426 TSStatsReset(const char *name)
427 {
428 return StatsReset(name);
429 }
430
431 /*--- variable operations ------------------------------------------------- */
432 /* Call the CfgFileIO variable operations */
433
434 tsapi TSMgmtError
TSRecordGet(const char * rec_name,TSRecordEle * rec_val)435 TSRecordGet(const char *rec_name, TSRecordEle *rec_val)
436 {
437 return MgmtRecordGet(rec_name, rec_val);
438 }
439
440 TSMgmtError
TSRecordGetInt(const char * rec_name,TSInt * int_val)441 TSRecordGetInt(const char *rec_name, TSInt *int_val)
442 {
443 TSMgmtError ret = TS_ERR_OKAY;
444
445 TSRecordEle *ele = TSRecordEleCreate();
446 ret = MgmtRecordGet(rec_name, ele);
447 if (ret != TS_ERR_OKAY) {
448 goto END;
449 }
450
451 *int_val = ele->valueT.int_val;
452
453 END:
454 TSRecordEleDestroy(ele);
455 return ret;
456 }
457
458 TSMgmtError
TSRecordGetCounter(const char * rec_name,TSCounter * counter_val)459 TSRecordGetCounter(const char *rec_name, TSCounter *counter_val)
460 {
461 TSMgmtError ret;
462
463 TSRecordEle *ele = TSRecordEleCreate();
464 ret = MgmtRecordGet(rec_name, ele);
465 if (ret != TS_ERR_OKAY) {
466 goto END;
467 }
468 *counter_val = ele->valueT.counter_val;
469
470 END:
471 TSRecordEleDestroy(ele);
472 return ret;
473 }
474
475 TSMgmtError
TSRecordGetFloat(const char * rec_name,TSFloat * float_val)476 TSRecordGetFloat(const char *rec_name, TSFloat *float_val)
477 {
478 TSMgmtError ret;
479
480 TSRecordEle *ele = TSRecordEleCreate();
481 ret = MgmtRecordGet(rec_name, ele);
482 if (ret != TS_ERR_OKAY) {
483 goto END;
484 }
485 *float_val = ele->valueT.float_val;
486
487 END:
488 TSRecordEleDestroy(ele);
489 return ret;
490 }
491
492 TSMgmtError
TSRecordGetString(const char * rec_name,TSString * string_val)493 TSRecordGetString(const char *rec_name, TSString *string_val)
494 {
495 TSMgmtError ret;
496
497 TSRecordEle *ele = TSRecordEleCreate();
498 ret = MgmtRecordGet(rec_name, ele);
499 if (ret != TS_ERR_OKAY) {
500 goto END;
501 }
502
503 *string_val = ats_strdup(ele->valueT.string_val);
504
505 END:
506 TSRecordEleDestroy(ele);
507 return ret;
508 }
509
510 /*-------------------------------------------------------------------------
511 * TSRecordGetMlt
512 *-------------------------------------------------------------------------
513 * Purpose: Retrieves list of record values specified in the rec_names list
514 * Input: rec_names - list of record names to retrieve
515 * rec_vals - queue of TSRecordEle* that corresponds to rec_names
516 * Output: If at any point, while retrieving one of the records there's a
517 * a failure then the entire process is aborted, all the allocated
518 * TSRecordEle's are deallocated and TS_ERR_FAIL is returned.
519 * Note: rec_names is not freed; if function is successful, the rec_names
520 * list is unchanged!
521 *
522 * IS THIS FUNCTION AN ATOMIC TRANSACTION? Technically, all the variables
523 * requested should refer to the same config file. But a lock is only
524 * put on each variable it is looked up. Need to be able to lock
525 * a file while retrieving all the requested records!
526 */
527
528 tsapi TSMgmtError
TSRecordGetMlt(TSStringList rec_names,TSList rec_vals)529 TSRecordGetMlt(TSStringList rec_names, TSList rec_vals)
530 {
531 int num_recs, i, j;
532 TSMgmtError ret;
533
534 if (!rec_names || !rec_vals) {
535 return TS_ERR_PARAMS;
536 }
537
538 num_recs = queue_len(static_cast<LLQ *>(rec_names));
539 for (i = 0; i < num_recs; i++) {
540 char *rec_name = static_cast<char *>(dequeue(static_cast<LLQ *>(rec_names))); // remove name from list
541 if (!rec_name) {
542 return TS_ERR_PARAMS; // NULL is invalid record name
543 }
544
545 TSRecordEle *ele = TSRecordEleCreate();
546
547 ret = MgmtRecordGet(rec_name, ele);
548 enqueue(static_cast<LLQ *>(rec_names), rec_name); // return name to list
549
550 if (ret != TS_ERR_OKAY) { // RecordGet failed
551 // need to free all the ele's allocated by MgmtRecordGet so far
552 TSRecordEleDestroy(ele);
553 for (j = 0; j < i; j++) {
554 ele = static_cast<TSRecordEle *>(dequeue(static_cast<LLQ *>(rec_vals)));
555 if (ele) {
556 TSRecordEleDestroy(ele);
557 }
558 }
559 return ret;
560 }
561 enqueue(static_cast<LLQ *>(rec_vals), ele); // all is good; add ele to end of list
562 }
563
564 return TS_ERR_OKAY;
565 }
566
567 tsapi TSMgmtError
TSRecordGetMatchMlt(const char * regex,TSList rec_vals)568 TSRecordGetMatchMlt(const char *regex, TSList rec_vals)
569 {
570 if (!regex || !rec_vals) {
571 return TS_ERR_PARAMS;
572 }
573
574 return MgmtRecordGetMatching(regex, rec_vals);
575 }
576
577 tsapi TSMgmtError
TSRecordSet(const char * rec_name,const char * val,TSActionNeedT * action_need)578 TSRecordSet(const char *rec_name, const char *val, TSActionNeedT *action_need)
579 {
580 return MgmtRecordSet(rec_name, val, action_need);
581 }
582
583 tsapi TSMgmtError
TSRecordSetInt(const char * rec_name,TSInt int_val,TSActionNeedT * action_need)584 TSRecordSetInt(const char *rec_name, TSInt int_val, TSActionNeedT *action_need)
585 {
586 return MgmtRecordSetInt(rec_name, int_val, action_need);
587 }
588
589 tsapi TSMgmtError
TSRecordSetCounter(const char * rec_name,TSCounter counter_val,TSActionNeedT * action_need)590 TSRecordSetCounter(const char *rec_name, TSCounter counter_val, TSActionNeedT *action_need)
591 {
592 return MgmtRecordSetCounter(rec_name, counter_val, action_need);
593 }
594
595 tsapi TSMgmtError
TSRecordSetFloat(const char * rec_name,TSFloat float_val,TSActionNeedT * action_need)596 TSRecordSetFloat(const char *rec_name, TSFloat float_val, TSActionNeedT *action_need)
597 {
598 return MgmtRecordSetFloat(rec_name, float_val, action_need);
599 }
600
601 tsapi TSMgmtError
TSRecordSetString(const char * rec_name,const char * str_val,TSActionNeedT * action_need)602 TSRecordSetString(const char *rec_name, const char *str_val, TSActionNeedT *action_need)
603 {
604 return MgmtRecordSetString(rec_name, str_val, action_need);
605 }
606
607 /*-------------------------------------------------------------------------
608 * TSRecordSetMlt
609 *-------------------------------------------------------------------------
610 * Basically iterates through each RecordEle in rec_list and calls the
611 * appropriate "MgmtRecordSetxx" function for that record
612 * Input: rec_list - queue of TSRecordEle*; each TSRecordEle* must have
613 * a valid record name (remains unchanged on return)
614 * Output: if there is an error during the setting of one of the variables then
615 * will continue to try to set the other variables. Error response will
616 * indicate though that not all set operations were successful.
617 * TS_ERR_OKAY is returned if all the records are set successfully
618 * Note: Determining the action needed is more complex b/c need to keep
619 * track of which record change is the most drastic out of the group of
620 * records; action_need will be set to the most severe action needed of
621 * all the "Set" calls
622 */
623 tsapi TSMgmtError
TSRecordSetMlt(TSList rec_list,TSActionNeedT * action_need)624 TSRecordSetMlt(TSList rec_list, TSActionNeedT *action_need)
625 {
626 int num_recs, ret, i;
627 TSMgmtError status = TS_ERR_OKAY;
628 TSActionNeedT top_action_req = TS_ACTION_UNDEFINED;
629
630 if (!rec_list || !action_need) {
631 return TS_ERR_PARAMS;
632 }
633
634 num_recs = queue_len(static_cast<LLQ *>(rec_list));
635
636 for (i = 0; i < num_recs; i++) {
637 TSRecordEle *ele = static_cast<TSRecordEle *>(dequeue(static_cast<LLQ *>(rec_list)));
638 if (ele) {
639 switch (ele->rec_type) {
640 case TS_REC_INT:
641 ret = MgmtRecordSetInt(ele->rec_name, ele->valueT.int_val, action_need);
642 break;
643 case TS_REC_COUNTER:
644 ret = MgmtRecordSetCounter(ele->rec_name, ele->valueT.counter_val, action_need);
645 break;
646 case TS_REC_FLOAT:
647 ret = MgmtRecordSetFloat(ele->rec_name, ele->valueT.float_val, action_need);
648 break;
649 case TS_REC_STRING:
650 ret = MgmtRecordSetString(ele->rec_name, ele->valueT.string_val, action_need);
651 break;
652 default:
653 ret = TS_ERR_FAIL;
654 break;
655 }; /* end of switch (ele->rec_type) */
656 if (ret != TS_ERR_OKAY) {
657 status = TS_ERR_FAIL;
658 }
659
660 // keep track of most severe action; reset if needed
661 // the TSActionNeedT should be listed such that most severe actions have
662 // a lower number (so most severe action == 0)
663 if (*action_need < top_action_req) { // a more severe action
664 top_action_req = *action_need;
665 }
666 }
667 enqueue(static_cast<LLQ *>(rec_list), ele);
668 }
669
670 // set the action_need to be the most sever action needed of all the "set" calls
671 *action_need = top_action_req;
672
673 return status;
674 }
675
676 /*--- api initialization and shutdown -------------------------------------*/
677 tsapi TSMgmtError
TSInit(const char * socket_path,TSInitOptionT options)678 TSInit(const char *socket_path, TSInitOptionT options)
679 {
680 return Init(socket_path, options);
681 }
682
683 tsapi TSMgmtError
TSTerminate()684 TSTerminate()
685 {
686 return Terminate();
687 }
688
689 /*--- plugin initialization -----------------------------------------------*/
690 inkexp extern void
TSPluginInit(int,const char * [])691 TSPluginInit(int /* argc ATS_UNUSED */, const char * /* argv ATS_UNUSED */[])
692 {
693 }
694
695 /*--- network operations --------------------------------------------------*/
696 tsapi TSMgmtError
TSConnect(TSIpAddr,int)697 TSConnect(TSIpAddr /* ip_addr ATS_UNUSED */, int /* port ATS_UNUSED */)
698 {
699 return TS_ERR_OKAY;
700 }
701 tsapi TSMgmtError
TSDisconnectCbRegister(TSDisconnectFunc *,void *)702 TSDisconnectCbRegister(TSDisconnectFunc * /* func ATS_UNUSED */, void * /* data ATS_UNUSED */)
703 {
704 return TS_ERR_OKAY;
705 }
706 tsapi TSMgmtError
TSDisconnectRetrySet(int,int)707 TSDisconnectRetrySet(int /* retries ATS_UNUSED */, int /* retry_sleep_msec ATS_UNUSED */)
708 {
709 return TS_ERR_OKAY;
710 }
711 tsapi TSMgmtError
TSDisconnect()712 TSDisconnect()
713 {
714 return TS_ERR_OKAY;
715 }
716
717 /*--- control operations --------------------------------------------------*/
718 /* NOTE: these operations are wrappers that make direct calls to the CoreAPI */
719
720 /* TSProxyStateGet: get the proxy state (on/off)
721 * Input: <none>
722 * Output: proxy state (on/off)
723 */
724 tsapi TSProxyStateT
TSProxyStateGet()725 TSProxyStateGet()
726 {
727 return ProxyStateGet();
728 }
729
730 /* TSProxyStateSet: set the proxy state (on/off)
731 * Input: proxy_state - set to on/off
732 * clear - start TS with cache clearing option,
733 * when stopping TS should always be TS_CACHE_CLEAR_NONE
734 * Output: TSMgmtError
735 */
736 tsapi TSMgmtError
TSProxyStateSet(TSProxyStateT proxy_state,unsigned clear)737 TSProxyStateSet(TSProxyStateT proxy_state, unsigned clear)
738 {
739 unsigned mask = TS_CACHE_CLEAR_NONE | TS_CACHE_CLEAR_CACHE | TS_CACHE_CLEAR_HOSTDB;
740
741 if (clear & ~mask) {
742 return TS_ERR_PARAMS;
743 }
744
745 return ProxyStateSet(proxy_state, static_cast<TSCacheClearT>(clear));
746 }
747
748 tsapi TSMgmtError
TSProxyBacktraceGet(unsigned options,TSString * trace)749 TSProxyBacktraceGet(unsigned options, TSString *trace)
750 {
751 if (options != 0) {
752 return TS_ERR_PARAMS;
753 }
754
755 if (trace == nullptr) {
756 return TS_ERR_PARAMS;
757 }
758
759 return ServerBacktrace(options, trace);
760 }
761
762 /* TSReconfigure: tell traffic_server to re-read its configuration files
763 * Input: <none>
764 * Output: TSMgmtError
765 */
766 tsapi TSMgmtError
TSReconfigure()767 TSReconfigure()
768 {
769 return Reconfigure();
770 }
771
772 /* TSRestart: restarts Traffic Server
773 * Input: options - bitmask of TSRestartOptionT
774 * Output: TSMgmtError
775 */
776 tsapi TSMgmtError
TSRestart(unsigned options)777 TSRestart(unsigned options)
778 {
779 return Restart(options);
780 }
781
782 /* TSActionDo: based on TSActionNeedT, will take appropriate action
783 * Input: action - action that needs to be taken
784 * Output: TSMgmtError
785 */
786 tsapi TSMgmtError
TSActionDo(TSActionNeedT action)787 TSActionDo(TSActionNeedT action)
788 {
789 TSMgmtError ret;
790
791 switch (action) {
792 case TS_ACTION_RESTART:
793 ret = Restart(true); // cluster wide by default?
794 break;
795 case TS_ACTION_RECONFIGURE:
796 ret = Reconfigure();
797 break;
798 case TS_ACTION_DYNAMIC:
799 /* do nothing - change takes effect immediately */
800 return TS_ERR_OKAY;
801 case TS_ACTION_SHUTDOWN:
802 default:
803 return TS_ERR_FAIL;
804 }
805
806 return ret;
807 }
808
809 /* TSBouncer: restarts the traffic_server process(es)
810 * Input: options - bitmask of TSRestartOptionT
811 * Output: TSMgmtError
812 */
813 tsapi TSMgmtError
TSBounce(unsigned options)814 TSBounce(unsigned options)
815 {
816 return Bounce(options);
817 }
818
819 tsapi TSMgmtError
TSStop(unsigned options)820 TSStop(unsigned options)
821 {
822 return Stop(options);
823 }
824
825 tsapi TSMgmtError
TSDrain(unsigned options)826 TSDrain(unsigned options)
827 {
828 return Drain(options);
829 }
830
831 tsapi TSMgmtError
TSStorageDeviceCmdOffline(const char * dev)832 TSStorageDeviceCmdOffline(const char *dev)
833 {
834 return StorageDeviceCmdOffline(dev);
835 }
836
837 tsapi TSMgmtError
TSLifecycleMessage(const char * tag,void const * data,size_t data_size)838 TSLifecycleMessage(const char *tag, void const *data, size_t data_size)
839 {
840 return LifecycleMessage(tag, data, data_size);
841 }
842
843 /* NOTE: user must deallocate the memory for the string returned */
844 char *
TSGetErrorMessage(TSMgmtError err_id)845 TSGetErrorMessage(TSMgmtError err_id)
846 {
847 char msg[1024]; // need to define a MAX_ERR_MSG_SIZE???
848 char *err_msg = nullptr;
849
850 switch (err_id) {
851 case TS_ERR_OKAY:
852 snprintf(msg, sizeof(msg), "[%d] Everything's looking good.", err_id);
853 break;
854 case TS_ERR_READ_FILE: /* Error occur in reading file */
855 snprintf(msg, sizeof(msg), "[%d] Unable to find/open file for reading.", err_id);
856 break;
857 case TS_ERR_WRITE_FILE: /* Error occur in writing file */
858 snprintf(msg, sizeof(msg), "[%d] Unable to find/open file for writing.", err_id);
859 break;
860 case TS_ERR_PARSE_CONFIG_RULE: /* Error in parsing configuration file */
861 snprintf(msg, sizeof(msg), "[%d] Error parsing configuration file.", err_id);
862 break;
863 case TS_ERR_INVALID_CONFIG_RULE: /* Invalid Configuration Rule */
864 snprintf(msg, sizeof(msg), "[%d] Invalid configuration rule reached.", err_id);
865 break;
866 case TS_ERR_NET_ESTABLISH:
867 snprintf(msg, sizeof(msg), "[%d] Error establishing socket connection.", err_id);
868 break;
869 case TS_ERR_NET_READ: /* Error reading from socket */
870 snprintf(msg, sizeof(msg), "[%d] Error reading from socket.", err_id);
871 break;
872 case TS_ERR_NET_WRITE: /* Error writing to socket */
873 snprintf(msg, sizeof(msg), "[%d] Error writing to socket.", err_id);
874 break;
875 case TS_ERR_NET_EOF: /* Hit socket EOF */
876 snprintf(msg, sizeof(msg), "[%d] Reached socket EOF.", err_id);
877 break;
878 case TS_ERR_NET_TIMEOUT: /* Timed out waiting for socket read */
879 snprintf(msg, sizeof(msg), "[%d] Timed out waiting for socket read.", err_id);
880 break;
881 case TS_ERR_SYS_CALL: /* Error in sys/utility call, eg.malloc */
882 snprintf(msg, sizeof(msg), "[%d] Error in basic system/utility call.", err_id);
883 break;
884 case TS_ERR_PARAMS: /* Invalid parameters for a fn */
885 snprintf(msg, sizeof(msg), "[%d] Invalid parameters passed into function call.", err_id);
886 break;
887 case TS_ERR_FAIL:
888 snprintf(msg, sizeof(msg), "[%d] Generic Fail message (ie. CoreAPI call).", err_id);
889 break;
890 case TS_ERR_NOT_SUPPORTED:
891 snprintf(msg, sizeof(msg), "[%d] Operation not supported on this platform.", err_id);
892 break;
893 case TS_ERR_PERMISSION_DENIED:
894 snprintf(msg, sizeof(msg), "[%d] Operation not permitted.", err_id);
895 break;
896
897 default:
898 snprintf(msg, sizeof(msg), "[%d] Invalid error type.", err_id);
899 break;
900 }
901
902 err_msg = ats_strdup(msg);
903 return err_msg;
904 }
905
906 /* ReadFromUrl: reads a remotely located config file into a buffer
907 * Input: url - remote location of the file
908 * header - a buffer is allocated on the header char* pointer
909 * headerSize - the size of the header buffer is returned
910 * body - a buffer is allocated on the body char* pointer
911 * bodySize - the size of the body buffer is returned
912 * Output: TSMgmtError - TS_ERR_OKAY if succeed, TS_ERR_FAIL otherwise
913 * Obsolete: tsapi TSMgmtError TSReadFromUrl (char *url, char **text, int *size);
914 * NOTE: The URL can be expressed in the following forms:
915 * - http://www.example.com:80/products/network/index.html
916 * - http://www.example.com/products/network/index.html
917 * - http://www.example.com/products/network/
918 * - http://www.example.com/
919 * - http://www.example.com
920 * - www.example.com
921 * NOTE: header and headerSize can be NULL
922 */
923 tsapi TSMgmtError
TSReadFromUrl(char * url,char ** header,int * headerSize,char ** body,int * bodySize)924 TSReadFromUrl(char *url, char **header, int *headerSize, char **body, int *bodySize)
925 {
926 // return ReadFromUrl(url, header, headerSize, body, bodySize);
927 return TSReadFromUrlEx(url, header, headerSize, body, bodySize, URL_TIMEOUT);
928 }
929
930 tsapi TSMgmtError
TSReadFromUrlEx(const char * url,char ** header,int * headerSize,char ** body,int * bodySize,int timeout)931 TSReadFromUrlEx(const char *url, char **header, int *headerSize, char **body, int *bodySize, int timeout)
932 {
933 int hFD = -1;
934 char *httpHost = nullptr;
935 char *httpPath = nullptr;
936 int httpPort = HTTP_PORT;
937 int bufsize = URL_BUFSIZE;
938 char buffer[URL_BUFSIZE];
939 char request[BUFSIZE];
940 char *hdr_temp;
941 char *bdy_temp;
942 TSMgmtError status = TS_ERR_OKAY;
943
944 // Sanity check
945 if (!url) {
946 return TS_ERR_FAIL;
947 }
948 if (timeout < 0) {
949 timeout = URL_TIMEOUT;
950 }
951 // Chop the protocol part, if it exists
952 const char *doubleSlash = strstr(url, "//");
953 if (doubleSlash) {
954 url = doubleSlash + 2; // advance two positions to get rid of leading '//'
955 }
956 // the path starts after the first occurrence of '/'
957 const char *tempPath = strstr(url, "/");
958 char *host_and_port;
959 if (tempPath) {
960 host_and_port = ats_strndup(url, strlen(url) - strlen(tempPath));
961 tempPath += 1; // advance one position to get rid of leading '/'
962 httpPath = ats_strdup(tempPath);
963 } else {
964 host_and_port = ats_strdup(url);
965 httpPath = ats_strdup("");
966 }
967
968 // the port proceed by a ":", if it exists
969 char *colon = strstr(host_and_port, ":");
970 if (colon) {
971 httpHost = ats_strndup(host_and_port, strlen(host_and_port) - strlen(colon));
972 colon += 1; // advance one position to get rid of leading ':'
973 httpPort = ink_atoi(colon);
974 if (httpPort <= 0) {
975 httpPort = HTTP_PORT;
976 }
977 } else {
978 httpHost = ats_strdup(host_and_port);
979 }
980 ats_free(host_and_port);
981
982 hFD = connectDirect(httpHost, httpPort, timeout);
983 if (hFD == -1) {
984 status = TS_ERR_NET_ESTABLISH;
985 goto END;
986 }
987
988 /* sending the HTTP request via the established socket */
989 snprintf(request, BUFSIZE, "http://%s:%d/%s", httpHost, httpPort, httpPath);
990 if ((status = sendHTTPRequest(hFD, request, static_cast<uint64_t>(timeout))) != TS_ERR_OKAY) {
991 goto END;
992 }
993
994 memset(buffer, 0, bufsize); /* empty the buffer */
995 if ((status = readHTTPResponse(hFD, buffer, bufsize, static_cast<uint64_t>(timeout))) != TS_ERR_OKAY) {
996 goto END;
997 }
998
999 if ((status = parseHTTPResponse(buffer, &hdr_temp, headerSize, &bdy_temp, bodySize)) != TS_ERR_OKAY) {
1000 goto END;
1001 }
1002
1003 if (header && headerSize) {
1004 *header = ats_strndup(hdr_temp, *headerSize);
1005 }
1006 *body = ats_strndup(bdy_temp, *bodySize);
1007
1008 END:
1009 ats_free(httpHost);
1010 ats_free(httpPath);
1011
1012 return status;
1013 }
1014
1015 /*--- cache inspector operations -------------------------------------------*/
1016
1017 tsapi TSMgmtError
TSLookupFromCacheUrl(TSString url,TSString * info)1018 TSLookupFromCacheUrl(TSString url, TSString *info)
1019 {
1020 TSMgmtError err = TS_ERR_OKAY;
1021 int fd;
1022 char request[BUFSIZE];
1023 char response[URL_BUFSIZE];
1024 char *header;
1025 char *body;
1026 int hdr_size;
1027 int bdy_size;
1028 int timeout = URL_TIMEOUT;
1029 TSInt ts_port = 8080;
1030
1031 if ((err = TSRecordGetInt("proxy.config.http.server_port", &ts_port)) != TS_ERR_OKAY) {
1032 goto END;
1033 }
1034
1035 if ((fd = connectDirect("localhost", ts_port, timeout)) < 0) {
1036 err = TS_ERR_FAIL;
1037 goto END;
1038 }
1039 snprintf(request, BUFSIZE, "http://{cache}/lookup_url?url=%s", url);
1040 if ((err = sendHTTPRequest(fd, request, static_cast<uint64_t>(timeout))) != TS_ERR_OKAY) {
1041 goto END;
1042 }
1043
1044 memset(response, 0, URL_BUFSIZE);
1045 if ((err = readHTTPResponse(fd, response, URL_BUFSIZE, static_cast<uint64_t>(timeout))) != TS_ERR_OKAY) {
1046 goto END;
1047 }
1048
1049 if ((err = parseHTTPResponse(response, &header, &hdr_size, &body, &bdy_size)) != TS_ERR_OKAY) {
1050 goto END;
1051 }
1052
1053 *info = ats_strndup(body, bdy_size);
1054
1055 END:
1056 return err;
1057 }
1058
1059 tsapi TSMgmtError
TSLookupFromCacheUrlRegex(TSString url_regex,TSString * list)1060 TSLookupFromCacheUrlRegex(TSString url_regex, TSString *list)
1061 {
1062 TSMgmtError err = TS_ERR_OKAY;
1063 int fd = -1;
1064 char request[BUFSIZE];
1065 char response[URL_BUFSIZE];
1066 char *header;
1067 char *body;
1068 int hdr_size;
1069 int bdy_size;
1070 int timeout = -1;
1071 TSInt ts_port = 8080;
1072
1073 if ((err = TSRecordGetInt("proxy.config.http.server_port", &ts_port)) != TS_ERR_OKAY) {
1074 goto END;
1075 }
1076
1077 if ((fd = connectDirect("localhost", ts_port, timeout)) < 0) {
1078 err = TS_ERR_FAIL;
1079 goto END;
1080 }
1081 snprintf(request, BUFSIZE, "http://{cache}/lookup_regex?url=%s", url_regex);
1082 if ((err = sendHTTPRequest(fd, request, static_cast<uint64_t>(timeout))) != TS_ERR_OKAY) {
1083 goto END;
1084 }
1085
1086 memset(response, 0, URL_BUFSIZE);
1087 if ((err = readHTTPResponse(fd, response, URL_BUFSIZE, static_cast<uint64_t>(timeout))) != TS_ERR_OKAY) {
1088 goto END;
1089 }
1090
1091 if ((err = parseHTTPResponse(response, &header, &hdr_size, &body, &bdy_size)) != TS_ERR_OKAY) {
1092 goto END;
1093 }
1094
1095 *list = ats_strndup(body, bdy_size);
1096 END:
1097 return err;
1098 }
1099
1100 tsapi TSMgmtError
TSDeleteFromCacheUrl(TSString url,TSString * info)1101 TSDeleteFromCacheUrl(TSString url, TSString *info)
1102 {
1103 TSMgmtError err = TS_ERR_OKAY;
1104 int fd = -1;
1105 char request[BUFSIZE];
1106 char response[URL_BUFSIZE];
1107 char *header;
1108 char *body;
1109 int hdr_size;
1110 int bdy_size;
1111 int timeout = URL_TIMEOUT;
1112 TSInt ts_port = 8080;
1113
1114 if ((err = TSRecordGetInt("proxy.config.http.server_port", &ts_port)) != TS_ERR_OKAY) {
1115 goto END;
1116 }
1117
1118 if ((fd = connectDirect("localhost", ts_port, timeout)) < 0) {
1119 err = TS_ERR_FAIL;
1120 goto END;
1121 }
1122 snprintf(request, BUFSIZE, "http://{cache}/delete_url?url=%s", url);
1123 if ((err = sendHTTPRequest(fd, request, static_cast<uint64_t>(timeout))) != TS_ERR_OKAY) {
1124 goto END;
1125 }
1126
1127 memset(response, 0, URL_BUFSIZE);
1128 if ((err = readHTTPResponse(fd, response, URL_BUFSIZE, static_cast<uint64_t>(timeout))) != TS_ERR_OKAY) {
1129 goto END;
1130 }
1131
1132 if ((err = parseHTTPResponse(response, &header, &hdr_size, &body, &bdy_size)) != TS_ERR_OKAY) {
1133 goto END;
1134 }
1135
1136 *info = ats_strndup(body, bdy_size);
1137
1138 END:
1139 return err;
1140 }
1141
1142 tsapi TSMgmtError
TSDeleteFromCacheUrlRegex(TSString url_regex,TSString * list)1143 TSDeleteFromCacheUrlRegex(TSString url_regex, TSString *list)
1144 {
1145 TSMgmtError err = TS_ERR_OKAY;
1146 int fd = -1;
1147 char request[BUFSIZE];
1148 char response[URL_BUFSIZE];
1149 char *header;
1150 char *body;
1151 int hdr_size;
1152 int bdy_size;
1153 int timeout = -1;
1154 TSInt ts_port = 8080;
1155
1156 if ((err = TSRecordGetInt("proxy.config.http.server_port", &ts_port)) != TS_ERR_OKAY) {
1157 goto END;
1158 }
1159
1160 if ((fd = connectDirect("localhost", ts_port, timeout)) < 0) {
1161 err = TS_ERR_FAIL;
1162 goto END;
1163 }
1164 snprintf(request, BUFSIZE, "http://{cache}/delete_regex?url=%s", url_regex);
1165 if ((err = sendHTTPRequest(fd, request, static_cast<uint64_t>(timeout))) != TS_ERR_OKAY) {
1166 goto END;
1167 }
1168
1169 memset(response, 0, URL_BUFSIZE);
1170 if ((err = readHTTPResponse(fd, response, URL_BUFSIZE, static_cast<uint64_t>(timeout))) != TS_ERR_OKAY) {
1171 goto END;
1172 }
1173
1174 if ((err = parseHTTPResponse(response, &header, &hdr_size, &body, &bdy_size)) != TS_ERR_OKAY) {
1175 goto END;
1176 }
1177
1178 *list = ats_strndup(body, bdy_size);
1179 END:
1180 return err;
1181 }
1182
1183 tsapi TSMgmtError
TSInvalidateFromCacheUrlRegex(TSString url_regex,TSString * list)1184 TSInvalidateFromCacheUrlRegex(TSString url_regex, TSString *list)
1185 {
1186 TSMgmtError err = TS_ERR_OKAY;
1187 int fd = -1;
1188 char request[BUFSIZE];
1189 char response[URL_BUFSIZE];
1190 char *header;
1191 char *body;
1192 int hdr_size;
1193 int bdy_size;
1194 int timeout = -1;
1195 TSInt ts_port = 8080;
1196
1197 if ((err = TSRecordGetInt("proxy.config.http.server_port", &ts_port)) != TS_ERR_OKAY) {
1198 goto END;
1199 }
1200
1201 if ((fd = connectDirect("localhost", ts_port, timeout)) < 0) {
1202 err = TS_ERR_FAIL;
1203 goto END;
1204 }
1205 snprintf(request, BUFSIZE, "http://{cache}/invalidate_regex?url=%s", url_regex);
1206 if ((err = sendHTTPRequest(fd, request, static_cast<uint64_t>(timeout))) != TS_ERR_OKAY) {
1207 goto END;
1208 }
1209
1210 memset(response, 0, URL_BUFSIZE);
1211 if ((err = readHTTPResponse(fd, response, URL_BUFSIZE, static_cast<uint64_t>(timeout))) != TS_ERR_OKAY) {
1212 goto END;
1213 }
1214
1215 if ((err = parseHTTPResponse(response, &header, &hdr_size, &body, &bdy_size)) != TS_ERR_OKAY) {
1216 goto END;
1217 }
1218
1219 *list = ats_strndup(body, bdy_size);
1220 END:
1221 return err;
1222 }
1223
1224 /*--- events --------------------------------------------------------------*/
1225 tsapi TSMgmtError
TSEventSignal(char * event_name,...)1226 TSEventSignal(char *event_name, ...)
1227 {
1228 va_list ap;
1229 TSMgmtError ret;
1230
1231 va_start(ap, event_name); // initialize the argument pointer ap
1232 ret = EventSignal(event_name, ap);
1233 va_end(ap);
1234 return ret;
1235 }
1236
1237 tsapi TSMgmtError
TSEventResolve(const char * event_name)1238 TSEventResolve(const char *event_name)
1239 {
1240 return EventResolve(event_name);
1241 }
1242
1243 tsapi TSMgmtError
TSActiveEventGetMlt(TSList active_events)1244 TSActiveEventGetMlt(TSList active_events)
1245 {
1246 return ActiveEventGetMlt(static_cast<LLQ *>(active_events));
1247 }
1248
1249 tsapi TSMgmtError
TSEventIsActive(char * event_name,bool * is_current)1250 TSEventIsActive(char *event_name, bool *is_current)
1251 {
1252 return EventIsActive(event_name, is_current);
1253 }
1254
1255 tsapi TSMgmtError
TSEventSignalCbRegister(char * event_name,TSEventSignalFunc func,void * data)1256 TSEventSignalCbRegister(char *event_name, TSEventSignalFunc func, void *data)
1257 {
1258 return EventSignalCbRegister(event_name, func, data);
1259 }
1260
1261 tsapi TSMgmtError
TSEventSignalCbUnregister(char * event_name,TSEventSignalFunc func)1262 TSEventSignalCbUnregister(char *event_name, TSEventSignalFunc func)
1263 {
1264 return EventSignalCbUnregister(event_name, func);
1265 }
1266
1267 TSConfigRecordDescription *
TSConfigRecordDescriptionCreate(void)1268 TSConfigRecordDescriptionCreate(void)
1269 {
1270 TSConfigRecordDescription *val = static_cast<TSConfigRecordDescription *>(ats_malloc(sizeof(TSConfigRecordDescription)));
1271
1272 ink_zero(*val);
1273 val->rec_type = TS_REC_UNDEFINED;
1274
1275 return val;
1276 }
1277
1278 void
TSConfigRecordDescriptionDestroy(TSConfigRecordDescription * val)1279 TSConfigRecordDescriptionDestroy(TSConfigRecordDescription *val)
1280 {
1281 TSConfigRecordDescriptionFree(val);
1282 ats_free(val);
1283 }
1284
1285 void
TSConfigRecordDescriptionFree(TSConfigRecordDescription * val)1286 TSConfigRecordDescriptionFree(TSConfigRecordDescription *val)
1287 {
1288 if (val) {
1289 ats_free(val->rec_name);
1290 ats_free(val->rec_checkexpr);
1291
1292 if (val->rec_type == TS_REC_STRING) {
1293 ats_free(val->rec_value.string_val);
1294 }
1295
1296 ink_zero(*val);
1297 val->rec_type = TS_REC_UNDEFINED;
1298 }
1299 }
1300
1301 TSMgmtError
TSConfigRecordDescribe(const char * rec_name,unsigned flags,TSConfigRecordDescription * val)1302 TSConfigRecordDescribe(const char *rec_name, unsigned flags, TSConfigRecordDescription *val)
1303 {
1304 if (!rec_name || !val) {
1305 return TS_ERR_PARAMS;
1306 }
1307
1308 TSConfigRecordDescriptionFree(val);
1309 return MgmtConfigRecordDescribe(rec_name, flags, val);
1310 }
1311
1312 TSMgmtError
TSConfigRecordDescribeMatchMlt(const char * rec_regex,unsigned flags,TSList rec_vals)1313 TSConfigRecordDescribeMatchMlt(const char *rec_regex, unsigned flags, TSList rec_vals)
1314 {
1315 if (!rec_regex || !rec_vals) {
1316 return TS_ERR_PARAMS;
1317 }
1318
1319 return MgmtConfigRecordDescribeMatching(rec_regex, flags, rec_vals);
1320 }
1321