Asterisk - The Open Source Telephony Project  GIT-master-44aef04
astman.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*
20  *
21  * ASTerisk MANager
22  *
23  */
24 
25 /*** MODULEINFO
26  <support_level>extended</support_level>
27  ***/
28 
29 #define ASTMM_LIBC ASTMM_IGNORE
30 #include "asterisk.h"
31 
32 #include <newt.h>
33 #include <stdio.h>
34 #include <sys/time.h>
35 #include <netdb.h>
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
38 #include <sys/socket.h>
39 #include <sys/select.h>
40 #include <fcntl.h>
41 #include <string.h>
42 #include <errno.h>
43 #include <unistd.h>
44 #include <stdlib.h>
45 
46 #include "asterisk/md5.h"
47 #include "asterisk/linkedlists.h"
48 
49 #define ARRAY_LEN(a) (sizeof(a) / sizeof(a[0]))
50 
51 #undef gethostbyname
52 
53 #define MAX_HEADERS 80
54 #define MAX_LEN 256
55 
56 /*
57  * 2005.05.27 - different versions of newt define the type of the buffer
58  * for the 5th argument to newtEntry() as char ** or const char ** . To
59  * let the code compile cleanly with -Werror, we cast it to void * through
60  * _NEWT_CAST.
61  */
62 #define _NEWT_CAST (void *)
63 
64 #define DEFAULT_MANAGER_PORT 5038
65 
66 struct message {
67  unsigned int hdrcount;
69 };
70 
71 static struct ast_mansession {
72  struct sockaddr_in sin;
73  int fd;
74  char inbuf[MAX_LEN];
75  int inlen;
76 } session;
77 
78 struct ast_chan {
79  char name[80];
80  char exten[20];
81  char context[20];
82  char priority[20];
83  char callerid[40];
84  char state[10];
86 };
87 
89 
90 /* dummy functions to be compatible with the Asterisk core for md5.c */
91 int ast_add_profile(const char *, uint64_t scale);
92 int ast_add_profile(const char *s, uint64_t scale)
93 {
94  return -1;
95 }
96 
97 int64_t ast_profile(int, int64_t);
98 int64_t ast_profile(int key, int64_t val)
99 {
100  return 0;
101 }
102 int64_t ast_mark(int, int start1_stop0);
103 int64_t ast_mark(int key, int start1_stop0)
104 {
105  return 0;
106 }
107 
108 /* end of dummy functions */
109 
110 static struct ast_chan *find_chan(char *name)
111 {
112  struct ast_chan *chan;
113  AST_LIST_TRAVERSE(&chans, chan, list) {
114  if (!strcmp(name, chan->name))
115  return chan;
116  }
117  chan = malloc(sizeof(struct ast_chan));
118  if (chan) {
119  memset(chan, 0, sizeof(struct ast_chan));
120  strncpy(chan->name, name, sizeof(chan->name) - 1);
122  }
123  return chan;
124 }
125 
126 static void del_chan(char *name)
127 {
128  struct ast_chan *chan;
129 
131  if (!strcmp(name, chan->name)) {
133  free(chan);
134  return;
135  }
136  }
138 }
139 
140 
141 static void __attribute__((format(printf, 2, 3))) fdprintf(int fd, char *fmt, ...)
142 {
143  char stuff[4096];
144  va_list ap;
145 
146  va_start(ap, fmt);
147  vsnprintf(stuff, sizeof(stuff), fmt, ap);
148  va_end(ap);
149  if (write(fd, stuff, strlen(stuff)) < 0) {
150  fprintf(stderr, "write() failed: %s\n", strerror(errno));
151  }
152 }
153 
154 static char *get_header(struct message *m, char *var)
155 {
156  char cmp[80];
157  int x;
158  snprintf(cmp, sizeof(cmp), "%s: ", var);
159  for (x=0;x<m->hdrcount;x++)
160  if (!strncasecmp(cmp, m->headers[x], strlen(cmp)))
161  return m->headers[x] + strlen(cmp);
162  return "";
163 }
164 
165 static int event_newstate(struct ast_mansession *s, struct message *m)
166 {
167  struct ast_chan *chan;
168  chan = find_chan(get_header(m, "Channel"));
169  strncpy(chan->state, get_header(m, "State"), sizeof(chan->state) - 1);
170  return 0;
171 }
172 
173 static int event_newexten(struct ast_mansession *s, struct message *m)
174 {
175  struct ast_chan *chan;
176  chan = find_chan(get_header(m, "Channel"));
177  strncpy(chan->exten, get_header(m, "Extension"), sizeof(chan->exten) - 1);
178  strncpy(chan->context, get_header(m, "Context"), sizeof(chan->context) - 1);
179  strncpy(chan->priority, get_header(m, "Priority"), sizeof(chan->priority) - 1);
180  return 0;
181 }
182 
183 static int event_newchannel(struct ast_mansession *s, struct message *m)
184 {
185  struct ast_chan *chan;
186  chan = find_chan(get_header(m, "Channel"));
187  strncpy(chan->state, get_header(m, "State"), sizeof(chan->state) - 1);
188  strncpy(chan->callerid, get_header(m, "Callerid"), sizeof(chan->callerid) - 1);
189  return 0;
190 }
191 
192 static int event_status(struct ast_mansession *s, struct message *m)
193 {
194  struct ast_chan *chan;
195  chan = find_chan(get_header(m, "Channel"));
196  strncpy(chan->state, get_header(m, "State"), sizeof(chan->state) - 1);
197  strncpy(chan->callerid, get_header(m, "Callerid"), sizeof(chan->callerid) - 1);
198  strncpy(chan->exten, get_header(m, "Extension"), sizeof(chan->exten) - 1);
199  strncpy(chan->context, get_header(m, "Context"), sizeof(chan->context) - 1);
200  strncpy(chan->priority, get_header(m, "Priority"), sizeof(chan->priority) - 1);
201  return 0;
202 }
203 
204 static int event_hangup(struct ast_mansession *s, struct message *m)
205 {
206  del_chan(get_header(m, "Channel"));
207  return 0;
208 }
209 
210 static int event_ignore(struct ast_mansession *s, struct message *m)
211 {
212  return 0;
213 }
214 
215 static int event_rename(struct ast_mansession *s, struct message *m)
216 {
217  struct ast_chan *chan;
218  chan = find_chan(get_header(m, "Oldname"));
219  strncpy(chan->name, get_header(m, "Newname"), sizeof(chan->name) - 1);
220  return 0;
221 }
222 static struct event {
223  char *event;
224  int (*func)(struct ast_mansession *s, struct message *m);
225 } events[] = {
226  { "Newstate", event_newstate },
227  { "Newchannel", event_newchannel },
228  { "Newexten", event_newexten },
229  { "Hangup", event_hangup },
230  { "Rename", event_rename },
231  { "Status", event_status },
232  { "Link", event_ignore },
233  { "Unlink", event_ignore },
234  { "StatusComplete", event_ignore },
235  { "Dial", event_ignore },
236  { "PeerStatus", event_ignore },
237  { "MessageWaiting", event_ignore },
238  { "Newcallerid", event_ignore },
239  { "AGIExec", event_ignore},
240  { "VarSet", event_ignore},
241  { "MeetmeTalking", event_ignore},
242  { "MeetmeJoin", event_ignore},
243  { "MeetmeLeave", event_ignore},
244  { "MeetmeEnd", event_ignore},
245  { "MeetmeMute", event_ignore},
246  { "Masquerade", event_ignore},
247 };
248 
249 static int process_message(struct ast_mansession *s, struct message *m)
250 {
251  int x;
252  char event[80] = "";
253  strncpy(event, get_header(m, "Event"), sizeof(event) - 1);
254  if (!strlen(event)) {
255  fprintf(stderr, "Missing event in request");
256  return 0;
257  }
258  for (x = 0; x < ARRAY_LEN(events); x++) {
259  if (!strcasecmp(event, events[x].event)) {
260  if (events[x].func(s, m))
261  return -1;
262  break;
263  }
264  }
265  if (x >= ARRAY_LEN(events))
266  fprintf(stderr, "Ignoring unknown event '%s'", event);
267 #if 0
268  for (x=0;x<m->hdrcount;x++) {
269  printf("Header: %s\n", m->headers[x]);
270  }
271 #endif
272  return 0;
273 }
274 
275 static void rebuild_channels(newtComponent c)
276 {
277  void *prev = NULL;
278  struct ast_chan *chan;
279  char tmpn[sizeof(chan->name) + sizeof(chan->callerid) + 3 - 1];
280  char tmp[256];
281  int x=0;
282  prev = newtListboxGetCurrent(c);
283  newtListboxClear(c);
284  AST_LIST_TRAVERSE(&chans, chan, list) {
285  snprintf(tmpn, sizeof(tmpn), "%s (%s)", chan->name, chan->callerid);
286  if (strlen(chan->exten))
287  snprintf(tmp, sizeof(tmp), "%-30s %8s -> %s@%s:%s",
288  tmpn, chan->state,
289  chan->exten, chan->context, chan->priority);
290  else
291  snprintf(tmp, sizeof(tmp), "%-30s %8s",
292  tmpn, chan->state);
293  newtListboxAppendEntry(c, tmp, chan);
294  x++;
295  }
296  if (!x)
297  newtListboxAppendEntry(c, " << No Active Channels >> ", NULL);
298  newtListboxSetCurrentByKey(c, prev);
299 }
300 
301 static int has_input(struct ast_mansession *s)
302 {
303  int x;
304  for (x=1;x<s->inlen;x++)
305  if ((s->inbuf[x] == '\n') && (s->inbuf[x-1] == '\r'))
306  return 1;
307  return 0;
308 }
309 
310 static int get_input(struct ast_mansession *s, char *output)
311 {
312  /* output must have at least sizeof(s->inbuf) space */
313  int res;
314  int x;
315  struct timeval tv = {0, 0};
316  fd_set fds;
317  for (x=1;x<s->inlen;x++) {
318  if ((s->inbuf[x] == '\n') && (s->inbuf[x-1] == '\r')) {
319  /* Copy output data up to and including \r\n */
320  memcpy(output, s->inbuf, x + 1);
321  /* Add trailing \0 */
322  output[x+1] = '\0';
323  /* Move remaining data back to the front */
324  memmove(s->inbuf, s->inbuf + x + 1, s->inlen - x);
325  s->inlen -= (x + 1);
326  return 1;
327  }
328  }
329  if (s->inlen >= sizeof(s->inbuf) - 1) {
330  fprintf(stderr, "Dumping long line with no return from %s: %s\n", inet_ntoa(s->sin.sin_addr), s->inbuf);
331  s->inlen = 0;
332  }
333  FD_ZERO(&fds);
334  FD_SET(s->fd, &fds);
335  res = select(s->fd + 1, &fds, NULL, NULL, &tv);
336  if (res < 0) {
337  fprintf(stderr, "Select returned error: %s\n", strerror(errno));
338  } else if (res > 0) {
339  res = read(s->fd, s->inbuf + s->inlen, sizeof(s->inbuf) - 1 - s->inlen);
340  if (res < 1)
341  return -1;
342  s->inlen += res;
343  s->inbuf[s->inlen] = '\0';
344  } else {
345  return 2;
346  }
347  return 0;
348 }
349 
350 static int input_check(struct ast_mansession *s, struct message **mout)
351 {
352  static struct message m;
353  int res;
354 
355  if (mout)
356  *mout = NULL;
357 
358  for(;;) {
359  res = get_input(s, m.headers[m.hdrcount]);
360  if (res == 1) {
361 #if 0
362  fprintf(stderr, "Got header: %s", m.headers[m.hdrcount]);
363  fgetc(stdin);
364 #endif
365  /* Strip trailing \r\n */
366  if (strlen(m.headers[m.hdrcount]) < 2)
367  continue;
368  m.headers[m.hdrcount][strlen(m.headers[m.hdrcount]) - 2] = '\0';
369  if (!strlen(m.headers[m.hdrcount])) {
370  if (mout && strlen(get_header(&m, "Response"))) {
371  *mout = &m;
372  return 0;
373  }
374  if (process_message(s, &m))
375  break;
376  memset(&m, 0, sizeof(m));
377  } else if (m.hdrcount < MAX_HEADERS - 1)
378  m.hdrcount++;
379  } else if (res < 0) {
380  return -1;
381  } else if (res == 2)
382  return 0;
383  }
384  return -1;
385 }
386 
387 static struct message *wait_for_response(int timeout)
388 {
389  struct message *m;
390  struct timeval tv;
391  int res;
392  fd_set fds;
393  for (;;) {
394  tv.tv_sec = timeout / 1000;
395  tv.tv_usec = (timeout % 1000) * 1000;
396  FD_SET(session.fd, &fds);
397  res = select(session.fd + 1, &fds, NULL, NULL, &tv);
398  if (res < 1)
399  break;
400  if (input_check(&session, &m) < 0) {
401  return NULL;
402  }
403  if (m)
404  return m;
405  }
406  return NULL;
407 }
408 
409 
410 static int __attribute__((format(printf, 2, 3))) manager_action(char *action, char *fmt, ...)
411 {
412  struct ast_mansession *s;
413  char tmp[4096];
414  va_list ap;
415  int res;
416 
417  s = &session;
418  fdprintf(s->fd, "Action: %s\r\n", action);
419  va_start(ap, fmt);
420  vsnprintf(tmp, sizeof(tmp), fmt, ap);
421  va_end(ap);
422  if ((res = write(s->fd, tmp, strlen(tmp))) < 0) {
423  fprintf(stderr, "write() failed: %s\n", strerror(errno));
424  }
425  fdprintf(s->fd, "\r\n");
426  return 0;
427 }
428 
429 static int show_message(char *title, char *msg)
430 {
431  newtComponent form;
432  newtComponent label;
433  newtComponent ok;
434  struct newtExitStruct es;
435 
436  newtCenteredWindow(60,7, title);
437 
438  label = newtLabel(4,1,msg);
439  ok = newtButton(27, 3, "OK");
440  form = newtForm(NULL, NULL, 0);
441  newtFormAddComponents(form, label, ok, NULL);
442  newtFormRun(form, &es);
443  newtPopWindow();
444  newtFormDestroy(form);
445  return 0;
446 }
447 
448 static newtComponent showform;
449 static int show_doing(char *title, char *tmp)
450 {
451  struct newtExitStruct es;
452  newtComponent label;
453  showform = newtForm(NULL, NULL, 0);
454  newtCenteredWindow(70,4, title);
455  label = newtLabel(3,1,tmp);
456  newtFormAddComponents(showform,label, NULL);
457  newtFormSetTimer(showform, 200);
458  newtFormRun(showform, &es);
459  return 0;
460 }
461 
462 static int hide_doing(void)
463 {
464  newtPopWindow();
465  newtFormDestroy(showform);
466  return 0;
467 }
468 
469 static void try_status(void)
470 {
471  struct message *m;
472  manager_action("Status", "%s", "");
473  m = wait_for_response(10000);
474  if (!m) {
475  show_message("Status Failed", "Timeout waiting for response");
476  } else if (strcasecmp(get_header(m, "Response"), "Success")) {
477  show_message("Status Failed Failed", get_header(m, "Message"));
478  }
479 }
480 
481 
482 static void try_hangup(newtComponent c)
483 {
484  struct ast_chan *chan;
485  struct message *m;
486 
487  chan = newtListboxGetCurrent(c);
488  if (chan) {
489  manager_action("Hangup", "Channel: %s\r\n", chan->name);
490  m = wait_for_response(10000);
491  if (!m) {
492  show_message("Hangup Failed", "Timeout waiting for response");
493  } else if (strcasecmp(get_header(m, "Response"), "Success")) {
494  show_message("Hangup Failed", get_header(m, "Message"));
495  }
496  }
497 
498 }
499 
500 static int get_user_input(char *msg, char *buf, int buflen)
501 {
502  newtComponent form;
503  newtComponent ok;
504  newtComponent cancel;
505  newtComponent inpfield;
506  const char *input;
507  int res = -1;
508  struct newtExitStruct es;
509 
510  newtCenteredWindow(60,7, msg);
511 
512  inpfield = newtEntry(5, 2, "", 50, _NEWT_CAST &input, 0);
513  ok = newtButton(22, 3, "OK");
514  cancel = newtButton(32, 3, "Cancel");
515  form = newtForm(NULL, NULL, 0);
516  newtFormAddComponents(form, inpfield, ok, cancel, NULL);
517  newtFormRun(form, &es);
518  strncpy(buf, input, buflen - 1);
519  if (es.u.co == ok)
520  res = 0;
521  else
522  res = -1;
523  newtPopWindow();
524  newtFormDestroy(form);
525  return res;
526 }
527 
528 static void try_redirect(newtComponent c)
529 {
530  struct ast_chan *chan;
531  char dest[256];
532  struct message *m;
533  static const char tmp_prefix[] = "Enter new extension for ";
534  char channame[256];
535  char tmp[sizeof(tmp_prefix) + sizeof(channame)];
536  char *context;
537 
538  chan = newtListboxGetCurrent(c);
539  if (chan) {
540  snprintf(channame, sizeof(channame), "%s", chan->name);
541  snprintf(tmp, sizeof(tmp), "%s%s", tmp_prefix, channame);
542  if (get_user_input(tmp, dest, sizeof(dest)))
543  return;
544  if ((context = strchr(dest, '@'))) {
545  *context = '\0';
546  context++;
547  manager_action("Redirect", "Channel: %s\r\nContext: %s\r\nExten: %s\r\nPriority: 1\r\n", chan->name,context,dest);
548  } else {
549  manager_action("Redirect", "Channel: %s\r\nExten: %s\r\nPriority: 1\r\n", chan->name, dest);
550  }
551  m = wait_for_response(10000);
552  if (!m) {
553  show_message("Hangup Failed", "Timeout waiting for response");
554  } else if (strcasecmp(get_header(m, "Response"), "Success")) {
555  show_message("Hangup Failed", get_header(m, "Message"));
556  }
557  }
558 
559 }
560 
561 static int manage_calls(char *host)
562 {
563  newtComponent form;
564  newtComponent quit;
565  newtComponent hangup;
566  newtComponent redirect;
567  newtComponent channels;
568  struct newtExitStruct es;
569  char tmp[80];
570 
571  /* Mark: If there's one thing you learn from this code, it is this...
572  Never, ever fly Air France. Their customer service is absolutely
573  the worst. I've never heard the words "That's not my problem" as
574  many times as I have from their staff -- It should, without doubt
575  be their corporate motto if it isn't already. Don't bother giving
576  them business because you're just a pain in their side and they
577  will be sure to let you know the first time you speak to them.
578 
579  If you ever want to make me happy just tell me that you, too, will
580  never fly Air France again either (in spite of their excellent
581  cuisine).
582 
583  Update by oej: The merger with KLM has transferred this
584  behaviour to KLM as well.
585  Don't bother giving them business either...
586 
587  Only if you want to travel randomly without luggage, you
588  might pick either of them.
589 
590  */
591  snprintf(tmp, sizeof(tmp), "Asterisk Manager at %s", host);
592  newtCenteredWindow(74, 20, tmp);
593  form = newtForm(NULL, NULL, 0);
594  newtFormWatchFd(form, session.fd, NEWT_FD_READ);
595  newtFormSetTimer(form, 100);
596  quit = newtButton(62, 16, "Quit");
597  redirect = newtButton(35, 16, "Redirect");
598  hangup = newtButton(50, 16, "Hangup");
599  channels = newtListbox(1,1,14, NEWT_FLAG_SCROLL);
600  newtFormAddComponents(form, channels, redirect, hangup, quit, NULL);
601  newtListboxSetWidth(channels, 72);
602 
603  show_doing("Getting Status", "Retrieving system status...");
604  try_status();
605  hide_doing();
606 
607  for(;;) {
608  newtFormRun(form, &es);
609  if (has_input(&session) || (es.reason == NEWT_EXIT_FDREADY)) {
610  if (input_check(&session, NULL)) {
611  show_message("Disconnected", "Disconnected from remote host");
612  break;
613  }
614  } else if (es.reason == NEWT_EXIT_COMPONENT) {
615  if (es.u.co == quit)
616  break;
617  if (es.u.co == hangup) {
618  try_hangup(channels);
619  } else if (es.u.co == redirect) {
620  try_redirect(channels);
621  }
622  }
623  rebuild_channels(channels);
624  }
625  newtFormDestroy(form);
626  return 0;
627 }
628 
629 static int manager_login(char *hostname)
630 {
631  newtComponent form;
632  newtComponent cancel;
633  newtComponent login;
634  newtComponent username;
635  newtComponent password;
636  newtComponent label;
637  newtComponent ulabel;
638  newtComponent plabel;
639  const char *user;
640  const char *pass;
641  struct message *m;
642  struct newtExitStruct es;
643  char tmp[55];
644  struct hostent *hp;
645  int res = -1;
646 
647  session.fd = socket(AF_INET, SOCK_STREAM, 0);
648  if (session.fd < 0) {
649  snprintf(tmp, sizeof(tmp), "socket() failed: %s\n", strerror(errno));
650  show_message("Socket failed", tmp);
651  return -1;
652  }
653 
654  snprintf(tmp, sizeof(tmp), "Looking up %s\n", hostname);
655  show_doing("Connecting....", tmp);
656 
657 
658  hp = gethostbyname(hostname);
659  if (!hp) {
660  snprintf(tmp, sizeof(tmp), "No such address: %s\n", hostname);
661  show_message("Host lookup failed", tmp);
662  return -1;
663  }
664  hide_doing();
665  snprintf(tmp, sizeof(tmp), "Connecting to %s", hostname);
666  show_doing("Connecting...", tmp);
667 
668  session.sin.sin_family = AF_INET;
669  session.sin.sin_port = htons(DEFAULT_MANAGER_PORT);
670  memcpy(&session.sin.sin_addr, hp->h_addr, sizeof(session.sin.sin_addr));
671 
672  if (connect(session.fd,(struct sockaddr*)&session.sin, sizeof(session.sin))) {
673  snprintf(tmp, sizeof(tmp), "%s failed: %s\n", hostname, strerror(errno));
674  show_message("Connect Failed", tmp);
675  return -1;
676  }
677 
678  hide_doing();
679 
680  login = newtButton(5, 6, "Login");
681  cancel = newtButton(25, 6, "Cancel");
682  newtCenteredWindow(40, 10, "Asterisk Manager Login");
683  snprintf(tmp, sizeof(tmp), "Host: %s", hostname);
684  label = newtLabel(4,1, tmp);
685 
686  ulabel = newtLabel(4,2,"Username:");
687  plabel = newtLabel(4,3,"Password:");
688 
689  username = newtEntry(14, 2, "", 20, _NEWT_CAST &user, 0);
690  password = newtEntry(14, 3, "", 20, _NEWT_CAST &pass, NEWT_FLAG_HIDDEN);
691 
692  form = newtForm(NULL, NULL, 0);
693  newtFormAddComponents(form, username, password, login, cancel, label, ulabel, plabel,NULL);
694  newtFormRun(form, &es);
695  if (es.reason == NEWT_EXIT_COMPONENT) {
696  if (es.u.co == login) {
697  snprintf(tmp, sizeof(tmp), "Logging in '%s'...", user);
698  show_doing("Logging in", tmp);
699  /* Check to see if the remote host supports MD5 Authentication */
700  manager_action("Challenge", "AuthType: MD5\r\n");
701  m = wait_for_response(10000);
702  if (m && !strcasecmp(get_header(m, "Response"), "Success")) {
703  char *challenge = get_header(m, "Challenge");
704  int x;
705  int len = 0;
706  char md5key[256] = "";
707  struct MD5Context md5;
708  unsigned char digest[16];
709  MD5Init(&md5);
710  MD5Update(&md5, (unsigned char *)challenge, strlen(challenge));
711  MD5Update(&md5, (unsigned char *)pass, strlen(pass));
712  MD5Final(digest, &md5);
713  for (x=0; x<16; x++)
714  len += sprintf(md5key + len, "%02hhx", digest[x]);
715  manager_action("Login",
716  "AuthType: MD5\r\n"
717  "Username: %s\r\n"
718  "Key: %s\r\n",
719  user, md5key);
720  m = wait_for_response(10000);
721  hide_doing();
722  if (!strcasecmp(get_header(m, "Response"), "Success")) {
723  res = 0;
724  } else {
725  show_message("Login Failed", get_header(m, "Message"));
726  }
727  } else {
728  manager_action("Login",
729  "Username: %s\r\n"
730  "Secret: %s\r\n",
731  user, pass);
732  m = wait_for_response(10000);
733  hide_doing();
734  if (m) {
735  if (!strcasecmp(get_header(m, "Response"), "Success")) {
736  res = 0;
737  } else {
738  show_message("Login Failed", get_header(m, "Message"));
739  }
740  }
741  }
742  }
743  }
744  newtFormDestroy(form);
745  return res;
746 }
747 
748 int main(int argc, char *argv[])
749 {
750  if (argc < 2) {
751  fprintf(stderr, "Usage: astman <host>\n");
752  exit(1);
753  }
754  newtInit();
755  newtCls();
756  newtDrawRootText(0, 0, "Asterisk Manager (C)2002, Linux Support Services, Inc.");
757  newtPushHelpLine("Welcome to the Asterisk Manager!");
758  if (manager_login(argv[1])) {
759  newtFinished();
760  exit(1);
761  }
762  manage_calls(argv[1]);
763  newtFinished();
764  return 0;
765 }
static char user[512]
int64_t ast_mark(int, int start1_stop0)
Definition: astman.c:103
static char pass[512]
static newtComponent showform
Definition: astman.c:448
char inbuf[MAX_LEN]
Definition: astman.c:74
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:118
Asterisk main include file. File version handling, generic pbx functions.
#define MAX_HEADERS
Definition: astman.c:53
static int event_hangup(struct ast_mansession *s, struct message *m)
Definition: astman.c:204
#define gethostbyname
Definition: lock.h:637
Definition: ast_expr2.c:325
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static struct message * wait_for_response(int timeout)
Definition: astman.c:387
static char * get_header(struct message *m, char *var)
Definition: astman.c:154
#define DEFAULT_MANAGER_PORT
Definition: astman.c:64
static struct ast_chan * find_chan(char *name)
Definition: astman.c:110
static int timeout
Definition: cdr_mysql.c:86
static int tmp()
Definition: bt_open.c:389
#define var
Definition: ast_expr2f.c:614
void MD5Final(unsigned char digest[16], struct MD5Context *context)
Definition: md5.c:120
Definition: astman.c:222
static struct test_val c
char priority[20]
Definition: astman.c:82
static int hangup(void *data)
Definition: chan_pjsip.c:2483
#define NULL
Definition: resample.c:96
static int inbuf(struct baseio *bio, FILE *fi)
utility used by inchar(), for base_encode()
static int input(yyscan_t yyscanner)
Definition: ast_expr2f.c:1584
static int priority
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:614
static struct ast_str * password
Definition: cdr_mysql.c:77
void MD5Init(struct MD5Context *context)
Definition: md5.c:57
#define FD_ZERO(a)
Definition: select.h:49
#define FD_SET(fd, fds)
Definition: select.h:58
#define inet_ntoa
Definition: network.h:87
static int event_newexten(struct ast_mansession *s, struct message *m)
Definition: astman.c:173
char * malloc()
void free()
static char host[256]
Definition: muted.c:77
static struct event events[]
static void try_hangup(newtComponent c)
Definition: astman.c:482
static struct ast_mansession session
static void try_redirect(newtComponent c)
Definition: astman.c:528
static void del_chan(char *name)
Definition: astman.c:126
static int manage_calls(char *host)
Definition: astman.c:561
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:556
static void challenge(const char *realm, pjsip_tx_data *tdata, const pjsip_rx_data *rdata, int is_stale)
astobj2 callback for adding digest challenges to responses
A set of macros to manage forward-linked lists.
#define MAX_LEN
Definition: astman.c:54
static struct channel_usage channels
char name[80]
Definition: astman.c:79
void MD5Update(struct MD5Context *context, unsigned char const *buf, unsigned len)
Definition: md5.c:72
static void try_status(void)
Definition: astman.c:469
#define AST_LIST_HEAD_NOLOCK_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
Definition: linkedlists.h:345
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:730
char * event
Definition: astman.c:223
static int show_doing(char *title, char *tmp)
Definition: astman.c:449
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int errno
static int show_message(char *title, char *msg)
Definition: astman.c:429
struct sockaddr_in sin
Definition: astman.c:72
static int process_message(struct ast_mansession *s, struct message *m)
Definition: astman.c:249
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:409
struct ast_chan::@504 list
static int event_newstate(struct ast_mansession *s, struct message *m)
Definition: astman.c:165
static const char name[]
Definition: cdr_mysql.c:74
static int get_user_input(char *msg, char *buf, int buflen)
Definition: astman.c:500
char exten[20]
Definition: astman.c:80
static void rebuild_channels(newtComponent c)
Definition: astman.c:275
static int manager_login(char *hostname)
Definition: astman.c:629
Definition: md5.h:26
static int event_status(struct ast_mansession *s, struct message *m)
Definition: astman.c:192
Definition: astman.c:88
char context[20]
Definition: astman.c:81
static int event_newchannel(struct ast_mansession *s, struct message *m)
Definition: astman.c:183
static int hide_doing(void)
Definition: astman.c:462
#define _NEWT_CAST
Definition: astman.c:62
static int event_ignore(struct ast_mansession *s, struct message *m)
Definition: astman.c:210
int ast_add_profile(const char *, uint64_t scale)
support for event profiling
Definition: astman.c:92
static struct ast_str * hostname
Definition: cdr_mysql.c:77
const char * headers[AST_MAX_MANHEADERS]
Definition: manager.h:146
int main(int argc, char *argv[])
Definition: astman.c:748
static void fdprintf(int fd, char *fmt,...)
Definition: astman.c:141
#define ARRAY_LEN(a)
Definition: astman.c:49
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
static int get_input(struct ast_mansession *s, char *output)
Definition: astman.c:310
static int event_rename(struct ast_mansession *s, struct message *m)
Definition: astman.c:215
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:116
static int manager_action(char *action, char *fmt,...)
Definition: astman.c:410
char callerid[40]
Definition: astman.c:83
static int input_check(struct ast_mansession *s, struct message **mout)
Definition: astman.c:350
static struct hostent * hp
Definition: chan_skinny.c:1236
unsigned int hdrcount
Definition: manager.h:145
MD5 digest functions.
int64_t ast_profile(int, int64_t)
Definition: astman.c:98
char state[10]
Definition: astman.c:84
static snd_pcm_format_t format
Definition: chan_alsa.c:102
static int has_input(struct ast_mansession *s)
Definition: astman.c:301