Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals

manager.c

Go to the documentation of this file.
00001 /* 00002 * Asterisk -- A telephony toolkit for Linux. 00003 * 00004 * Channel Management and more 00005 * 00006 * Copyright (C) 1999, Mark Spencer 00007 * 00008 * Mark Spencer <markster@linux-support.net> 00009 * 00010 * This program is free software, distributed under the terms of 00011 * the GNU General Public License 00012 */ 00013 00014 #include <stdio.h> 00015 #include <stdlib.h> 00016 #include <pthread.h> 00017 #include <string.h> 00018 #include <sys/time.h> 00019 #include <sys/types.h> 00020 #include <netdb.h> 00021 #include <sys/socket.h> 00022 #include <netinet/in.h> 00023 #include <netinet/tcp.h> 00024 #include <arpa/inet.h> 00025 #include <signal.h> 00026 #include <errno.h> 00027 #include <unistd.h> 00028 #include <sys/poll.h> 00029 #include <asterisk/channel.h> 00030 #include <asterisk/file.h> 00031 #include <asterisk/manager.h> 00032 #include <asterisk/config.h> 00033 #include <asterisk/lock.h> 00034 #include <asterisk/logger.h> 00035 #include <asterisk/options.h> 00036 #include <asterisk/cli.h> 00037 #include <asterisk/app.h> 00038 #include <asterisk/pbx.h> 00039 #include <asterisk/md5.h> 00040 #include <asterisk/acl.h> 00041 #include <asterisk/utils.h> 00042 00043 struct fast_originate_helper 00044 { 00045 char tech[256]; 00046 char data[256]; 00047 int timeout; 00048 char app[256]; 00049 char appdata[256]; 00050 char callerid[256]; 00051 char variable[256]; 00052 char account[256]; 00053 char context[256]; 00054 char exten[256]; 00055 int priority; 00056 }; 00057 00058 static int enabled = 0; 00059 static int portno = DEFAULT_MANAGER_PORT; 00060 static int asock = -1; 00061 static pthread_t t; 00062 AST_MUTEX_DEFINE_STATIC(sessionlock); 00063 static int block_sockets = 0; 00064 00065 static struct permalias { 00066 int num; 00067 char *label; 00068 } perms[] = { 00069 { EVENT_FLAG_SYSTEM, "system" }, 00070 { EVENT_FLAG_CALL, "call" }, 00071 { EVENT_FLAG_LOG, "log" }, 00072 { EVENT_FLAG_VERBOSE, "verbose" }, 00073 { EVENT_FLAG_COMMAND, "command" }, 00074 { EVENT_FLAG_AGENT, "agent" }, 00075 { EVENT_FLAG_USER, "user" }, 00076 { -1, "all" }, 00077 }; 00078 00079 static struct mansession *sessions = NULL; 00080 static struct manager_action *first_action = NULL; 00081 AST_MUTEX_DEFINE_STATIC(actionlock); 00082 00083 int ast_carefulwrite(int fd, char *s, int len, int timeoutms) 00084 { 00085 /* Try to write string, but wait no more than ms milliseconds 00086 before timing out */ 00087 int res=0; 00088 struct pollfd fds[1]; 00089 while(len) { 00090 res = write(fd, s, len); 00091 if ((res < 0) && (errno != EAGAIN)) { 00092 return -1; 00093 } 00094 if (res < 0) res = 0; 00095 len -= res; 00096 s += res; 00097 fds[0].fd = fd; 00098 fds[0].events = POLLOUT; 00099 /* Wait until writable again */ 00100 res = poll(fds, 1, timeoutms); 00101 if (res < 1) 00102 return -1; 00103 } 00104 return res; 00105 } 00106 00107 static char *complete_show_mancmd(char *line, char *word, int pos, int state) 00108 { 00109 struct manager_action *cur = first_action; 00110 int which = 0; 00111 00112 ast_mutex_lock(&actionlock); 00113 while (cur) { /* Walk the list of actions */ 00114 if (!strncasecmp(word, cur->action, strlen(word))) { 00115 if (++which > state) { 00116 char *ret = strdup(cur->action); 00117 ast_mutex_unlock(&actionlock); 00118 return ret; 00119 } 00120 } 00121 cur = cur->next; 00122 } 00123 ast_mutex_unlock(&actionlock); 00124 return NULL; 00125 } 00126 00127 static int handle_showmancmd(int fd, int argc, char *argv[]) 00128 { 00129 struct manager_action *cur = first_action; 00130 int num; 00131 00132 if (argc != 4) 00133 return RESULT_SHOWUSAGE; 00134 ast_mutex_lock(&actionlock); 00135 while (cur) { /* Walk the list of actions */ 00136 for (num = 3; num < argc; num++) { 00137 if (!strcasecmp(cur->action, argv[num])) { 00138 ast_cli(fd, "Action: %s\nSynopsis: %s\n%s\n", cur->action, cur->synopsis, cur->description ? cur->description : ""); 00139 } 00140 } 00141 cur = cur->next; 00142 } 00143 00144 ast_mutex_unlock(&actionlock); 00145 return RESULT_SUCCESS; 00146 } 00147 00148 static int handle_showmancmds(int fd, int argc, char *argv[]) 00149 { 00150 struct manager_action *cur = first_action; 00151 char *format = " %-15.15s %-45.45s\n"; 00152 00153 ast_mutex_lock(&actionlock); 00154 ast_cli(fd, format, "Action", "Synopsis"); 00155 while (cur) { /* Walk the list of actions */ 00156 ast_cli(fd, format, cur->action, cur->synopsis); 00157 cur = cur->next; 00158 } 00159 00160 ast_mutex_unlock(&actionlock); 00161 return RESULT_SUCCESS; 00162 } 00163 00164 static int handle_showmanconn(int fd, int argc, char *argv[]) 00165 { 00166 struct mansession *s; 00167 char *format = " %-15.15s %-15.15s\n"; 00168 ast_mutex_lock(&sessionlock); 00169 s = sessions; 00170 ast_cli(fd, format, "Username", "IP Address"); 00171 while (s) { 00172 ast_cli(fd, format,s->username, inet_ntoa(s->sin.sin_addr)); 00173 s = s->next; 00174 } 00175 00176 ast_mutex_unlock(&sessionlock); 00177 return RESULT_SUCCESS; 00178 } 00179 00180 static char showmancmd_help[] = 00181 "Usage: show manager command <actionname>\n" 00182 " Shows the detailed description for a specific manager command.\n"; 00183 00184 static char showmancmds_help[] = 00185 "Usage: show manager commands\n" 00186 " Prints a listing of all the available manager commands.\n"; 00187 00188 static char showmanconn_help[] = 00189 "Usage: show manager connected\n" 00190 " Prints a listing of the users that are connected to the\n" 00191 "manager interface.\n"; 00192 00193 static struct ast_cli_entry show_mancmd_cli = 00194 { { "show", "manager", "command", NULL }, 00195 handle_showmancmd, "Show manager command", showmancmd_help, complete_show_mancmd }; 00196 00197 static struct ast_cli_entry show_mancmds_cli = 00198 { { "show", "manager", "commands", NULL }, 00199 handle_showmancmds, "Show manager commands", showmancmds_help }; 00200 00201 static struct ast_cli_entry show_manconn_cli = 00202 { { "show", "manager", "connected", NULL }, 00203 handle_showmanconn, "Show connected manager users", showmanconn_help }; 00204 00205 static void destroy_session(struct mansession *s) 00206 { 00207 struct mansession *cur, *prev = NULL; 00208 ast_mutex_lock(&sessionlock); 00209 cur = sessions; 00210 while(cur) { 00211 if (cur == s) 00212 break; 00213 prev = cur; 00214 cur = cur->next; 00215 } 00216 if (cur) { 00217 if (prev) 00218 prev->next = cur->next; 00219 else 00220 sessions = cur->next; 00221 if (s->fd > -1) 00222 close(s->fd); 00223 free(s); 00224 } else 00225 ast_log(LOG_WARNING, "Trying to delete non-existant session %p?\n", s); 00226 ast_mutex_unlock(&sessionlock); 00227 00228 } 00229 00230 char *astman_get_header(struct message *m, char *var) 00231 { 00232 char cmp[80]; 00233 int x; 00234 snprintf(cmp, sizeof(cmp), "%s: ", var); 00235 for (x=0;x<m->hdrcount;x++) 00236 if (!strncasecmp(cmp, m->headers[x], strlen(cmp))) 00237 return m->headers[x] + strlen(cmp); 00238 return ""; 00239 } 00240 00241 void astman_send_error(struct mansession *s, struct message *m, char *error) 00242 { 00243 char *id = astman_get_header(m,"ActionID"); 00244 ast_mutex_lock(&s->lock); 00245 ast_cli(s->fd, "Response: Error\r\n"); 00246 if (id && !ast_strlen_zero(id)) 00247 ast_cli(s->fd, "ActionID: %s\r\n",id); 00248 ast_cli(s->fd, "Message: %s\r\n\r\n", error); 00249 ast_mutex_unlock(&s->lock); 00250 } 00251 00252 void astman_send_response(struct mansession *s, struct message *m, char *resp, char *msg) 00253 { 00254 char *id = astman_get_header(m,"ActionID"); 00255 ast_mutex_lock(&s->lock); 00256 ast_cli(s->fd, "Response: %s\r\n", resp); 00257 if (id && !ast_strlen_zero(id)) 00258 ast_cli(s->fd, "ActionID: %s\r\n",id); 00259 if (msg) 00260 ast_cli(s->fd, "Message: %s\r\n\r\n", msg); 00261 else 00262 ast_cli(s->fd, "\r\n"); 00263 ast_mutex_unlock(&s->lock); 00264 } 00265 00266 void astman_send_ack(struct mansession *s, struct message *m, char *msg) 00267 { 00268 astman_send_response(s, m, "Success", msg); 00269 } 00270 00271 static int get_perm(char *instr) 00272 { 00273 char tmp[256]; 00274 char *c; 00275 int x; 00276 int ret = 0; 00277 char *stringp=NULL; 00278 if (!instr) 00279 return 0; 00280 strncpy(tmp, instr, sizeof(tmp) - 1); 00281 stringp=tmp; 00282 c = strsep(&stringp, ","); 00283 while(c) { 00284 for (x=0;x<sizeof(perms) / sizeof(perms[0]);x++) { 00285 if (!strcasecmp(perms[x].label, c)) 00286 ret |= perms[x].num; 00287 } 00288 c = strsep(&stringp, ","); 00289 } 00290 return ret; 00291 } 00292 00293 static int set_eventmask(struct mansession *s, char *eventmask) 00294 { 00295 if (!eventmask) 00296 return -1; 00297 if (!strcasecmp(eventmask, "on") || ast_true(eventmask)) { 00298 ast_mutex_lock(&s->lock); 00299 s->send_events = 1; 00300 ast_mutex_unlock(&s->lock); 00301 return 1; 00302 } else if (!strcasecmp(eventmask, "off") || ast_false(eventmask)) { 00303 ast_mutex_lock(&s->lock); 00304 s->send_events = 0; 00305 ast_mutex_unlock(&s->lock); 00306 return 0; 00307 } 00308 return -1; 00309 } 00310 00311 static int authenticate(struct mansession *s, struct message *m) 00312 { 00313 struct ast_config *cfg; 00314 char *cat; 00315 char *user = astman_get_header(m, "Username"); 00316 char *pass = astman_get_header(m, "Secret"); 00317 char *authtype = astman_get_header(m, "AuthType"); 00318 char *key = astman_get_header(m, "Key"); 00319 char *events = astman_get_header(m, "Events"); 00320 00321 cfg = ast_load("manager.conf"); 00322 if (!cfg) 00323 return -1; 00324 cat = ast_category_browse(cfg, NULL); 00325 while(cat) { 00326 if (strcasecmp(cat, "general")) { 00327 /* This is a user */ 00328 if (!strcasecmp(cat, user)) { 00329 struct ast_variable *v; 00330 struct ast_ha *ha = NULL; 00331 char *password = NULL; 00332 v = ast_variable_browse(cfg, cat); 00333 while (v) { 00334 if (!strcasecmp(v->name, "secret")) { 00335 password = v->value; 00336 } else if (!strcasecmp(v->name, "permit") || 00337 !strcasecmp(v->name, "deny")) { 00338 ha = ast_append_ha(v->name, v->value, ha); 00339 } 00340 v = v->next; 00341 } 00342 if (ha && !ast_apply_ha(ha, &(s->sin))) { 00343 ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", inet_ntoa(s->sin.sin_addr), user); 00344 ast_free_ha(ha); 00345 ast_destroy(cfg); 00346 return -1; 00347 } else if (ha) 00348 ast_free_ha(ha); 00349 if (!strcasecmp(authtype, "MD5")) { 00350 if (key && !ast_strlen_zero(key) && s->challenge) { 00351 int x; 00352 int len=0; 00353 char md5key[256] = ""; 00354 struct MD5Context md5; 00355 unsigned char digest[16]; 00356 MD5Init(&md5); 00357 MD5Update(&md5, s->challenge, strlen(s->challenge)); 00358 MD5Update(&md5, password, strlen(password)); 00359 MD5Final(digest, &md5); 00360 for (x=0;x<16;x++) 00361 len += sprintf(md5key + len, "%2.2x", digest[x]); 00362 if (!strcmp(md5key, key)) 00363 break; 00364 else { 00365 ast_destroy(cfg); 00366 return -1; 00367 } 00368 } 00369 } else if (password && !strcasecmp(password, pass)) { 00370 break; 00371 } else { 00372 ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", inet_ntoa(s->sin.sin_addr), user); 00373 ast_destroy(cfg); 00374 return -1; 00375 } 00376 } 00377 } 00378 cat = ast_category_browse(cfg, cat); 00379 } 00380 if (cat) { 00381 strncpy(s->username, cat, sizeof(s->username) - 1); 00382 s->readperm = get_perm(ast_variable_retrieve(cfg, cat, "read")); 00383 s->writeperm = get_perm(ast_variable_retrieve(cfg, cat, "write")); 00384 ast_destroy(cfg); 00385 if (events) 00386 set_eventmask(s, events); 00387 return 0; 00388 } 00389 ast_log(LOG_NOTICE, "%s tried to authenticate with non-existant user '%s'\n", inet_ntoa(s->sin.sin_addr), user); 00390 ast_destroy(cfg); 00391 return -1; 00392 } 00393 00394 static char mandescr_ping[] = 00395 "Description: A 'Ping' action will ellicit a 'Pong' response. Used to keep the " 00396 " manager connection open.\n" 00397 "Variables: NONE\n"; 00398 00399 static int action_ping(struct mansession *s, struct message *m) 00400 { 00401 astman_send_response(s, m, "Pong", NULL); 00402 return 0; 00403 } 00404 00405 static char mandescr_listcommands[] = 00406 "Description: Returns the action name and synopsis for every\n" 00407 " action that is available to the user\n" 00408 "Variables: NONE\n"; 00409 00410 static int action_listcommands(struct mansession *s, struct message *m) 00411 { 00412 struct manager_action *cur = first_action; 00413 char idText[256] = ""; 00414 char *id = astman_get_header(m,"ActionID"); 00415 00416 if (id && !ast_strlen_zero(id)) 00417 snprintf(idText,256,"ActionID: %s\r\n",id); 00418 ast_cli(s->fd, "Response: Success\r\n%s", idText); 00419 ast_mutex_lock(&actionlock); 00420 while (cur) { /* Walk the list of actions */ 00421 if ((s->writeperm & cur->authority) == cur->authority) 00422 ast_cli(s->fd, "%s: %s\r\n", cur->action, cur->synopsis); 00423 cur = cur->next; 00424 } 00425 ast_mutex_unlock(&actionlock); 00426 ast_cli(s->fd, "\r\n"); 00427 00428 return 0; 00429 } 00430 00431 static int action_events(struct mansession *s, struct message *m) 00432 { 00433 char *mask = astman_get_header(m, "EventMask"); 00434 int res; 00435 00436 res = set_eventmask(s, mask); 00437 if (res > 0) 00438 astman_send_response(s, m, "Events On", NULL); 00439 else if (res == 0) 00440 astman_send_response(s, m, "Events Off", NULL); 00441 else 00442 astman_send_response(s, m, "EventMask parse error", NULL); 00443 return 0; 00444 } 00445 00446 static int action_logoff(struct mansession *s, struct message *m) 00447 { 00448 astman_send_response(s, m, "Goodbye", "Thanks for all the fish."); 00449 return -1; 00450 } 00451 00452 static int action_hangup(struct mansession *s, struct message *m) 00453 { 00454 struct ast_channel *c = NULL; 00455 char *name = astman_get_header(m, "Channel"); 00456 if (ast_strlen_zero(name)) { 00457 astman_send_error(s, m, "No channel specified"); 00458 return 0; 00459 } 00460 c = ast_channel_walk_locked(NULL); 00461 while(c) { 00462 if (!strcasecmp(c->name, name)) { 00463 break; 00464 } 00465 ast_mutex_unlock(&c->lock); 00466 c = ast_channel_walk_locked(c); 00467 } 00468 if (!c) { 00469 astman_send_error(s, m, "No such channel"); 00470 return 0; 00471 } 00472 ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT); 00473 ast_mutex_unlock(&c->lock); 00474 astman_send_ack(s, m, "Channel Hungup"); 00475 return 0; 00476 } 00477 00478 static int action_setvar(struct mansession *s, struct message *m) 00479 { 00480 struct ast_channel *c = NULL; 00481 char *name = astman_get_header(m, "Channel"); 00482 char *varname = astman_get_header(m, "Variable"); 00483 char *varval = astman_get_header(m, "Value"); 00484 00485 if (!strlen(name)) { 00486 astman_send_error(s, m, "No channel specified"); 00487 return 0; 00488 } 00489 if (!strlen(varname)) { 00490 astman_send_error(s, m, "No variable specified"); 00491 return 0; 00492 } 00493 00494 c = ast_channel_walk_locked(NULL); 00495 while(c) { 00496 if (!strcasecmp(c->name, name)) { 00497 break; 00498 } 00499 ast_mutex_unlock(&c->lock); 00500 c = ast_channel_walk_locked(c); 00501 } 00502 if (!c) { 00503 astman_send_error(s, m, "No such channel"); 00504 return 0; 00505 } 00506 00507 pbx_builtin_setvar_helper(c,varname,varval); 00508 00509 ast_mutex_unlock(&c->lock); 00510 astman_send_ack(s, m, "Variable Set"); 00511 return 0; 00512 } 00513 00514 static int action_getvar(struct mansession *s, struct message *m) 00515 { 00516 struct ast_channel *c = NULL; 00517 char *name = astman_get_header(m, "Channel"); 00518 char *varname = astman_get_header(m, "Variable"); 00519 char *varval; 00520 00521 if (!strlen(name)) { 00522 astman_send_error(s, m, "No channel specified"); 00523 return 0; 00524 } 00525 if (!strlen(varname)) { 00526 astman_send_error(s, m, "No variable specified"); 00527 return 0; 00528 } 00529 00530 c = ast_channel_walk_locked(NULL); 00531 while(c) { 00532 if (!strcasecmp(c->name, name)) { 00533 break; 00534 } 00535 ast_mutex_unlock(&c->lock); 00536 c = ast_channel_walk_locked(c); 00537 } 00538 if (!c) { 00539 astman_send_error(s, m, "No such channel"); 00540 return 0; 00541 } 00542 00543 varval=pbx_builtin_getvar_helper(c,varname); 00544 00545 ast_mutex_unlock(&c->lock); 00546 ast_cli(s->fd, "Response: Success\r\n" 00547 "%s: %s",varname,varval); 00548 00549 return 0; 00550 } 00551 00552 00553 static int action_status(struct mansession *s, struct message *m) 00554 { 00555 char *id = astman_get_header(m,"ActionID"); 00556 char idText[256] = ""; 00557 struct ast_channel *c; 00558 char bridge[256]; 00559 astman_send_ack(s, m, "Channel status will follow"); 00560 c = ast_channel_walk_locked(NULL); 00561 if (id && !ast_strlen_zero(id)) 00562 snprintf(idText,256,"ActionID: %s\r\n",id); 00563 while(c) { 00564 if (c->bridge) 00565 snprintf(bridge, sizeof(bridge), "Link: %s\r\n", c->bridge->name); 00566 else 00567 strcpy(bridge, ""); 00568 if (c->pbx) { 00569 ast_cli(s->fd, 00570 "Event: Status\r\n" 00571 "Channel: %s\r\n" 00572 "CallerID: %s\r\n" 00573 "State: %s\r\n" 00574 "Context: %s\r\n" 00575 "Extension: %s\r\n" 00576 "Priority: %d\r\n" 00577 "%s" 00578 "Uniqueid: %s\r\n" 00579 "%s" 00580 "\r\n", 00581 c->name, c->callerid ? c->callerid : "<unknown>", 00582 ast_state2str(c->_state), c->context, 00583 c->exten, c->priority, bridge, c->uniqueid, idText); 00584 } else { 00585 ast_cli(s->fd, 00586 "Event: Status\r\n" 00587 "Channel: %s\r\n" 00588 "CallerID: %s\r\n" 00589 "State: %s\r\n" 00590 "%s" 00591 "Uniqueid: %s\r\n" 00592 "%s" 00593 "\r\n", 00594 c->name, c->callerid ? c->callerid : "<unknown>", 00595 ast_state2str(c->_state), bridge, c->uniqueid, idText); 00596 } 00597 ast_mutex_unlock(&c->lock); 00598 c = ast_channel_walk_locked(c); 00599 } 00600 ast_cli(s->fd, 00601 "Event: StatusComplete\r\n" 00602 "%s" 00603 "\r\n",idText); 00604 return 0; 00605 } 00606 00607 static int action_redirect(struct mansession *s, struct message *m) 00608 { 00609 char *name = astman_get_header(m, "Channel"); 00610 char *name2 = astman_get_header(m, "ExtraChannel"); 00611 char *exten = astman_get_header(m, "Exten"); 00612 char *context = astman_get_header(m, "Context"); 00613 char *priority = astman_get_header(m, "Priority"); 00614 struct ast_channel *chan, *chan2 = NULL; 00615 int pi = 0; 00616 int res; 00617 if (!name || ast_strlen_zero(name)) { 00618 astman_send_error(s, m, "Channel not specified"); 00619 return 0; 00620 } 00621 if (!ast_strlen_zero(priority) && (sscanf(priority, "%d", &pi) != 1)) { 00622 astman_send_error(s, m, "Invalid priority\n"); 00623 return 0; 00624 } 00625 chan = ast_get_channel_by_name_locked(name); 00626 if (!chan) { 00627 astman_send_error(s, m, "Channel not existant"); 00628 return 0; 00629 } 00630 if (!ast_strlen_zero(name2)) 00631 chan2 = ast_get_channel_by_name_locked(name2); 00632 res = ast_async_goto(chan, context, exten, pi); 00633 if (!res) { 00634 if (!ast_strlen_zero(name2)) { 00635 if (chan2) 00636 res = ast_async_goto(chan2, context, exten, pi); 00637 else 00638 res = -1; 00639 if (!res) 00640 astman_send_ack(s, m, "Dual Redirect successful"); 00641 else 00642 astman_send_error(s, m, "Secondary redirect failed"); 00643 } else 00644 astman_send_ack(s, m, "Redirect successful"); 00645 } else 00646 astman_send_error(s, m, "Redirect failed"); 00647 if (chan) 00648 ast_mutex_unlock(&chan->lock); 00649 if (chan2) 00650 ast_mutex_unlock(&chan2->lock); 00651 return 0; 00652 } 00653 00654 static int action_command(struct mansession *s, struct message *m) 00655 { 00656 char *cmd = astman_get_header(m, "Command"); 00657 char *id = astman_get_header(m, "ActionID"); 00658 ast_mutex_lock(&s->lock); 00659 s->blocking = 1; 00660 ast_mutex_unlock(&s->lock); 00661 ast_cli(s->fd, "Response: Follows\r\n"); 00662 if (id && !ast_strlen_zero(id)) 00663 ast_cli(s->fd, "ActionID: %s\r\n", id); 00664 /* FIXME: Wedge a ActionID response in here, waiting for later changes */ 00665 ast_cli_command(s->fd, cmd); 00666 ast_cli(s->fd, "--END COMMAND--\r\n\r\n"); 00667 ast_mutex_lock(&s->lock); 00668 s->blocking = 0; 00669 ast_mutex_unlock(&s->lock); 00670 return 0; 00671 } 00672 00673 static void *fast_originate(void *data) 00674 { 00675 struct fast_originate_helper *in = data; 00676 int res; 00677 int reason = 0; 00678 if (!ast_strlen_zero(in->app)) { 00679 res = ast_pbx_outgoing_app(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->app, in->appdata, &reason, 1, !ast_strlen_zero(in->callerid) ? in->callerid : NULL, in->variable, in->account); 00680 } else { 00681 res = ast_pbx_outgoing_exten(in->tech, AST_FORMAT_SLINEAR, in->data, in->timeout, in->context, in->exten, in->priority, &reason, 1, !ast_strlen_zero(in->callerid) ? in->callerid : NULL, in->variable, in->account); 00682 } 00683 free(in); 00684 return NULL; 00685 } 00686 00687 static char mandescr_originate[] = 00688 "Description: Generates an outgoing call to a Extension/Context/Priority or\n" 00689 " Application/Data\n" 00690 "Variables: (Names marked with * are required)\n" 00691 " *Channel: Channel name to call\n" 00692 " Exten: Extension to use (requires 'Context' and 'Priority')\n" 00693 " Context: Context to use (requires 'Exten' and 'Priority')\n" 00694 " Priority: Priority to use (requires 'Exten' and 'Context')\n" 00695 " Application: Application to use\n" 00696 " Data: Data to use (requires 'Application')\n" 00697 " Timeout: How long to wait for call to be answered (in ms)\n" 00698 " CallerID: Caller ID to be set on the outgoing channel\n" 00699 " Variable: Channel variable to set (VAR1=value1|VAR2=value2)\n" 00700 " Account: Account code\n" 00701 " Async: Set to 'true' for fast origination\n"; 00702 00703 static int action_originate(struct mansession *s, struct message *m) 00704 { 00705 char *name = astman_get_header(m, "Channel"); 00706 char *exten = astman_get_header(m, "Exten"); 00707 char *context = astman_get_header(m, "Context"); 00708 char *priority = astman_get_header(m, "Priority"); 00709 char *timeout = astman_get_header(m, "Timeout"); 00710 char *callerid = astman_get_header(m, "CallerID"); 00711 char *variable = astman_get_header(m, "Variable"); 00712 char *account = astman_get_header(m, "Account"); 00713 char *app = astman_get_header(m, "Application"); 00714 char *appdata = astman_get_header(m, "Data"); 00715 char *async = astman_get_header(m, "Async"); 00716 char *tech, *data; 00717 int pi = 0; 00718 int res; 00719 int to = 30000; 00720 int reason = 0; 00721 char tmp[256]; 00722 pthread_t th; 00723 pthread_attr_t attr; 00724 if (!name) { 00725 astman_send_error(s, m, "Channel not specified"); 00726 return 0; 00727 } 00728 if (!ast_strlen_zero(priority) && (sscanf(priority, "%d", &pi) != 1)) { 00729 astman_send_error(s, m, "Invalid priority\n"); 00730 return 0; 00731 } 00732 if (!ast_strlen_zero(timeout) && (sscanf(timeout, "%d", &to) != 1)) { 00733 astman_send_error(s, m, "Invalid timeout\n"); 00734 return 0; 00735 } 00736 strncpy(tmp, name, sizeof(tmp) - 1); 00737 tech = tmp; 00738 data = strchr(tmp, '/'); 00739 if (!data) { 00740 astman_send_error(s, m, "Invalid channel\n"); 00741 return 0; 00742 } 00743 *data = '\0'; 00744 data++; 00745 if (ast_true(async)) 00746 { 00747 struct fast_originate_helper *fast = malloc(sizeof(struct fast_originate_helper)); 00748 if (!fast) 00749 { 00750 res = -1; 00751 } 00752 else 00753 { 00754 memset(fast, 0, sizeof(struct fast_originate_helper)); 00755 strncpy(fast->tech, tech, sizeof(fast->tech) - 1); 00756 strncpy(fast->data, data, sizeof(fast->data) - 1); 00757 strncpy(fast->app, app, sizeof(fast->app) - 1); 00758 strncpy(fast->appdata, appdata, sizeof(fast->appdata) - 1); 00759 strncpy(fast->callerid, callerid, sizeof(fast->callerid) - 1); 00760 strncpy(fast->variable, variable, sizeof(fast->variable) - 1); 00761 strncpy(fast->account, account, sizeof(fast->account) - 1); 00762 strncpy(fast->context, context, sizeof(fast->context) - 1); 00763 strncpy(fast->exten, exten, sizeof(fast->exten) - 1); 00764 fast->timeout = to; 00765 fast->priority = pi; 00766 pthread_attr_init(&attr); 00767 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 00768 if (pthread_create(&th, &attr, fast_originate, fast)) 00769 { 00770 res = -1; 00771 } 00772 else 00773 { 00774 res = 0; 00775 } 00776 } 00777 } else if (!ast_strlen_zero(app)) { 00778 res = ast_pbx_outgoing_app(tech, AST_FORMAT_SLINEAR, data, to, app, appdata, &reason, 0, !ast_strlen_zero(callerid) ? callerid : NULL, variable, account); 00779 } else { 00780 if (exten && context && pi) 00781 res = ast_pbx_outgoing_exten(tech, AST_FORMAT_SLINEAR, data, to, context, exten, pi, &reason, 0, !ast_strlen_zero(callerid) ? callerid : NULL, variable, account); 00782 else { 00783 astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'"); 00784 return 0; 00785 } 00786 } 00787 if (!res) 00788 astman_send_ack(s, m, "Originate successfully queued"); 00789 else 00790 astman_send_error(s, m, "Originate failed"); 00791 return 0; 00792 } 00793 00794 static int action_mailboxstatus(struct mansession *s, struct message *m) 00795 { 00796 char *mailbox = astman_get_header(m, "Mailbox"); 00797 char *id = astman_get_header(m,"ActionID"); 00798 char idText[256] = ""; 00799 if (!mailbox || ast_strlen_zero(mailbox)) { 00800 astman_send_error(s, m, "Mailbox not specified"); 00801 return 0; 00802 } 00803 if (id && !ast_strlen_zero(id)) 00804 snprintf(idText,256,"ActionID: %s\r\n",id); 00805 ast_cli(s->fd, "Response: Success\r\n" 00806 "%s" 00807 "Message: Mailbox Status\r\n" 00808 "Mailbox: %s\r\n" 00809 "Waiting: %d\r\n\r\n", idText, mailbox, ast_app_has_voicemail(mailbox)); 00810 return 0; 00811 } 00812 00813 static int action_mailboxcount(struct mansession *s, struct message *m) 00814 { 00815 char *mailbox = astman_get_header(m, "Mailbox"); 00816 char *id = astman_get_header(m,"ActionID"); 00817 char idText[256] = ""; 00818 int newmsgs = 0, oldmsgs = 0; 00819 if (!mailbox || ast_strlen_zero(mailbox)) { 00820 astman_send_error(s, m, "Mailbox not specified"); 00821 return 0; 00822 } 00823 ast_app_messagecount(mailbox, &newmsgs, &oldmsgs); 00824 if (id && !ast_strlen_zero(id)) { 00825 snprintf(idText,256,"ActionID: %s\r\n",id); 00826 } 00827 ast_cli(s->fd, "Response: Success\r\n" 00828 "%s" 00829 "Message: Mailbox Message Count\r\n" 00830 "Mailbox: %s\r\n" 00831 "NewMessages: %d\r\n" 00832 "OldMessages: %d\r\n" 00833 "\r\n", 00834 idText,mailbox, newmsgs, oldmsgs); 00835 return 0; 00836 } 00837 00838 static int action_extensionstate(struct mansession *s, struct message *m) 00839 { 00840 char *exten = astman_get_header(m, "Exten"); 00841 char *context = astman_get_header(m, "Context"); 00842 char *id = astman_get_header(m,"ActionID"); 00843 char idText[256] = ""; 00844 char hint[256] = ""; 00845 int status; 00846 if (!exten || ast_strlen_zero(exten)) { 00847 astman_send_error(s, m, "Extension not specified"); 00848 return 0; 00849 } 00850 if (!context || ast_strlen_zero(context)) 00851 context = "default"; 00852 status = ast_extension_state(NULL, context, exten); 00853 ast_get_hint(hint, sizeof(hint) - 1, NULL, context, exten); 00854 if (id && !ast_strlen_zero(id)) { 00855 snprintf(idText,256,"ActionID: %s\r\n",id); 00856 } 00857 ast_cli(s->fd, "Response: Success\r\n" 00858 "%s" 00859 "Message: Extension Status\r\n" 00860 "Exten: %s\r\n" 00861 "Context: %s\r\n" 00862 "Hint: %s\r\n" 00863 "Status: %d\r\n\r\n", 00864 idText,exten, context, hint, status); 00865 return 0; 00866 } 00867 00868 static int action_timeout(struct mansession *s, struct message *m) 00869 { 00870 struct ast_channel *c = NULL; 00871 char *name = astman_get_header(m, "Channel"); 00872 int timeout = atoi(astman_get_header(m, "Timeout")); 00873 if (ast_strlen_zero(name)) { 00874 astman_send_error(s, m, "No channel specified"); 00875 return 0; 00876 } 00877 if (!timeout) { 00878 astman_send_error(s, m, "No timeout specified"); 00879 return 0; 00880 } 00881 c = ast_channel_walk_locked(NULL); 00882 while(c) { 00883 if (!strcasecmp(c->name, name)) { 00884 break; 00885 } 00886 ast_mutex_unlock(&c->lock); 00887 c = ast_channel_walk_locked(c); 00888 } 00889 if (!c) { 00890 astman_send_error(s, m, "No such channel"); 00891 return 0; 00892 } 00893 ast_channel_setwhentohangup(c, timeout); 00894 ast_mutex_unlock(&c->lock); 00895 astman_send_ack(s, m, "Timeout Set"); 00896 return 0; 00897 } 00898 00899 static int process_message(struct mansession *s, struct message *m) 00900 { 00901 char action[80]; 00902 struct manager_action *tmp = first_action; 00903 char *id = astman_get_header(m,"ActionID"); 00904 char idText[256] = ""; 00905 00906 strncpy(action, astman_get_header(m, "Action"), sizeof(action)); 00907 ast_log( LOG_DEBUG, "Manager received command '%s'\n", action ); 00908 00909 if (ast_strlen_zero(action)) { 00910 astman_send_error(s, m, "Missing action in request"); 00911 return 0; 00912 } 00913 if (id && !ast_strlen_zero(id)) { 00914 snprintf(idText,256,"ActionID: %s\r\n",id); 00915 } 00916 if (!s->authenticated) { 00917 if (!strcasecmp(action, "Challenge")) { 00918 char *authtype; 00919 authtype = astman_get_header(m, "AuthType"); 00920 if (!strcasecmp(authtype, "MD5")) { 00921 if (!s->challenge || ast_strlen_zero(s->challenge)) { 00922 ast_mutex_lock(&s->lock); 00923 snprintf(s->challenge, sizeof(s->challenge), "%d", rand()); 00924 ast_mutex_unlock(&s->lock); 00925 } 00926 ast_cli(s->fd, "Response: Success\r\n" 00927 "%s" 00928 "Challenge: %s\r\n\r\n", 00929 idText,s->challenge); 00930 return 0; 00931 } else { 00932 astman_send_error(s, m, "Must specify AuthType"); 00933 return 0; 00934 } 00935 } else if (!strcasecmp(action, "Login")) { 00936 if (authenticate(s, m)) { 00937 sleep(1); 00938 astman_send_error(s, m, "Authentication failed"); 00939 return -1; 00940 } else { 00941 s->authenticated = 1; 00942 if (option_verbose > 1) 00943 ast_verbose(VERBOSE_PREFIX_2 "Manager '%s' logged on from %s\n", s->username, inet_ntoa(s->sin.sin_addr)); 00944 ast_log(LOG_EVENT, "Manager '%s' logged on from %s\n", s->username, inet_ntoa(s->sin.sin_addr)); 00945 astman_send_ack(s, m, "Authentication accepted"); 00946 } 00947 } else if (!strcasecmp(action, "Logoff")) { 00948 astman_send_ack(s, m, "See ya"); 00949 return -1; 00950 } else 00951 astman_send_error(s, m, "Authentication Required"); 00952 } else { 00953 while( tmp ) { 00954 if (!strcasecmp(action, tmp->action)) { 00955 if ((s->writeperm & tmp->authority) == tmp->authority) { 00956 if (tmp->func(s, m)) 00957 return -1; 00958 } else { 00959 astman_send_error(s, m, "Permission denied"); 00960 } 00961 return 0; 00962 } 00963 tmp = tmp->next; 00964 } 00965 astman_send_error(s, m, "Invalid/unknown command"); 00966 } 00967 return 0; 00968 } 00969 00970 static int get_input(struct mansession *s, char *output) 00971 { 00972 /* output must have at least sizeof(s->inbuf) space */ 00973 int res; 00974 int x; 00975 struct pollfd fds[1]; 00976 for (x=1;x<s->inlen;x++) { 00977 if ((s->inbuf[x] == '\n') && (s->inbuf[x-1] == '\r')) { 00978 /* Copy output data up to and including \r\n */ 00979 memcpy(output, s->inbuf, x + 1); 00980 /* Add trailing \0 */ 00981 output[x+1] = '\0'; 00982 /* Move remaining data back to the front */ 00983 memmove(s->inbuf, s->inbuf + x + 1, s->inlen - x); 00984 s->inlen -= (x + 1); 00985 return 1; 00986 } 00987 } 00988 if (s->inlen >= sizeof(s->inbuf) - 1) { 00989 ast_log(LOG_WARNING, "Dumping long line with no return from %s: %s\n", inet_ntoa(s->sin.sin_addr), s->inbuf); 00990 s->inlen = 0; 00991 } 00992 fds[0].fd = s->fd; 00993 fds[0].events = POLLIN; 00994 res = poll(fds, 1, -1); 00995 if (res < 0) { 00996 ast_log(LOG_WARNING, "Select returned error: %s\n", strerror(errno)); 00997 } else if (res > 0) { 00998 ast_mutex_lock(&s->lock); 00999 res = read(s->fd, s->inbuf + s->inlen, sizeof(s->inbuf) - 1 - s->inlen); 01000 ast_mutex_unlock(&s->lock); 01001 if (res < 1) 01002 return -1; 01003 } 01004 s->inlen += res; 01005 s->inbuf[s->inlen] = '\0'; 01006 return 0; 01007 } 01008 01009 static void *session_do(void *data) 01010 { 01011 struct mansession *s = data; 01012 struct message m; 01013 int res; 01014 01015 ast_mutex_lock(&s->lock); 01016 ast_cli(s->fd, "Asterisk Call Manager/1.0\r\n"); 01017 ast_mutex_unlock(&s->lock); 01018 memset(&m, 0, sizeof(&m)); 01019 for (;;) { 01020 res = get_input(s, m.headers[m.hdrcount]); 01021 if (res > 0) { 01022 /* Strip trailing \r\n */ 01023 if (strlen(m.headers[m.hdrcount]) < 2) 01024 continue; 01025 m.headers[m.hdrcount][strlen(m.headers[m.hdrcount]) - 2] = '\0'; 01026 if (ast_strlen_zero(m.headers[m.hdrcount])) { 01027 if (process_message(s, &m)) 01028 break; 01029 memset(&m, 0, sizeof(&m)); 01030 } else if (m.hdrcount < MAX_HEADERS - 1) 01031 m.hdrcount++; 01032 } else if (res < 0) 01033 break; 01034 } 01035 if (s->authenticated) { 01036 if (option_verbose > 1) 01037 ast_verbose(VERBOSE_PREFIX_2 "Manager '%s' logged off from %s\n", s->username, inet_ntoa(s->sin.sin_addr)); 01038 ast_log(LOG_EVENT, "Manager '%s' logged off from %s\n", s->username, inet_ntoa(s->sin.sin_addr)); 01039 } else { 01040 if (option_verbose > 1) 01041 ast_verbose(VERBOSE_PREFIX_2 "Connect attempt from '%s' unable to authenticate\n", inet_ntoa(s->sin.sin_addr)); 01042 ast_log(LOG_EVENT, "Failed attempt from %s\n", inet_ntoa(s->sin.sin_addr)); 01043 } 01044 destroy_session(s); 01045 return NULL; 01046 } 01047 01048 static void *accept_thread(void *ignore) 01049 { 01050 int as; 01051 struct sockaddr_in sin; 01052 int sinlen; 01053 struct mansession *s; 01054 struct protoent *p; 01055 int arg = 1; 01056 int flags; 01057 pthread_attr_t attr; 01058 01059 pthread_attr_init(&attr); 01060 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 01061 01062 for (;;) { 01063 sinlen = sizeof(sin); 01064 as = accept(asock, (struct sockaddr *)&sin, &sinlen); 01065 if (as < 0) { 01066 ast_log(LOG_NOTICE, "Accept returned -1: %s\n", strerror(errno)); 01067 continue; 01068 } 01069 p = getprotobyname("tcp"); 01070 if( p ) { 01071 if( setsockopt(as, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) { 01072 ast_log(LOG_WARNING, "Failed to set manager tcp connection to TCP_NODELAY mode: %s\n", strerror(errno)); 01073 } 01074 } 01075 s = malloc(sizeof(struct mansession)); 01076 if (!s) { 01077 ast_log(LOG_WARNING, "Failed to allocate management session: %s\n", strerror(errno)); 01078 continue; 01079 } 01080 memset(s, 0, sizeof(struct mansession)); 01081 memcpy(&s->sin, &sin, sizeof(sin)); 01082 01083 if(! block_sockets) { 01084 /* For safety, make sure socket is non-blocking */ 01085 flags = fcntl(as, F_GETFL); 01086 fcntl(as, F_SETFL, flags | O_NONBLOCK); 01087 } 01088 ast_mutex_init(&s->lock); 01089 s->fd = as; 01090 s->send_events = 1; 01091 ast_mutex_lock(&sessionlock); 01092 s->next = sessions; 01093 sessions = s; 01094 ast_mutex_unlock(&sessionlock); 01095 if (pthread_create(&t, &attr, session_do, s)) 01096 destroy_session(s); 01097 } 01098 pthread_attr_destroy(&attr); 01099 return NULL; 01100 } 01101 01102 int manager_event(int category, char *event, char *fmt, ...) 01103 { 01104 struct mansession *s; 01105 char tmp[4096]; 01106 va_list ap; 01107 01108 ast_mutex_lock(&sessionlock); 01109 s = sessions; 01110 while(s) { 01111 if (((s->readperm & category) == category) && s->send_events) { 01112 ast_mutex_lock(&s->lock); 01113 if (!s->blocking) { 01114 ast_cli(s->fd, "Event: %s\r\n", event); 01115 va_start(ap, fmt); 01116 vsnprintf(tmp, sizeof(tmp), fmt, ap); 01117 va_end(ap); 01118 ast_carefulwrite(s->fd,tmp,strlen(tmp),100); 01119 ast_cli(s->fd, "\r\n"); 01120 } 01121 ast_mutex_unlock(&s->lock); 01122 } 01123 s = s->next; 01124 } 01125 ast_mutex_unlock(&sessionlock); 01126 return 0; 01127 } 01128 01129 int ast_manager_unregister( char *action ) { 01130 struct manager_action *cur = first_action, *prev = first_action; 01131 01132 ast_mutex_lock(&actionlock); 01133 while( cur ) { 01134 if (!strcasecmp(action, cur->action)) { 01135 prev->next = cur->next; 01136 free(cur); 01137 if (option_verbose > 1) 01138 ast_verbose(VERBOSE_PREFIX_2 "Manager unregistered action %s\n", action); 01139 ast_mutex_unlock(&actionlock); 01140 return 0; 01141 } 01142 prev = cur; 01143 cur = cur->next; 01144 } 01145 ast_mutex_unlock(&actionlock); 01146 return 0; 01147 } 01148 01149 static int manager_state_cb(char *context, char *exten, int state, void *data) 01150 { 01151 /* Notify managers of change */ 01152 manager_event(EVENT_FLAG_CALL, "ExtensionStatus", "Exten: %s\r\nContext: %s\r\nStatus: %d\r\n", exten, context, state); 01153 return 0; 01154 } 01155 01156 static int ast_manager_register_struct(struct manager_action *act) 01157 { 01158 struct manager_action *cur = first_action, *prev = NULL; 01159 int ret; 01160 01161 ast_mutex_lock(&actionlock); 01162 while(cur) { /* Walk the list of actions */ 01163 ret = strcasecmp(cur->action, act->action); 01164 if (ret == 0) { 01165 ast_log(LOG_WARNING, "Manager: Action '%s' already registered\n", act->action); 01166 ast_mutex_unlock(&actionlock); 01167 return -1; 01168 } else if (ret > 0) { 01169 /* Insert these alphabetically */ 01170 if (prev) { 01171 act->next = prev->next; 01172 prev->next = act; 01173 } else { 01174 act->next = first_action; 01175 first_action = act; 01176 } 01177 break; 01178 } 01179 prev = cur; 01180 cur = cur->next; 01181 } 01182 01183 if (!cur) { 01184 if (prev) 01185 prev->next = act; 01186 else 01187 first_action = act; 01188 act->next = NULL; 01189 } 01190 01191 if (option_verbose > 1) 01192 ast_verbose(VERBOSE_PREFIX_2 "Manager registered action %s\n", act->action); 01193 ast_mutex_unlock(&actionlock); 01194 return 0; 01195 } 01196 01197 int ast_manager_register2(char *action, int auth, int (*func)(struct mansession *s, struct message *m), char *synopsis, char *description) 01198 { 01199 struct manager_action *cur; 01200 01201 cur = malloc(sizeof(struct manager_action)); 01202 if (!cur) { 01203 ast_log(LOG_WARNING, "Manager: out of memory trying to register action\n"); 01204 ast_mutex_unlock(&actionlock); 01205 return -1; 01206 } 01207 cur->action = action; 01208 cur->authority = auth; 01209 cur->func = func; 01210 cur->synopsis = synopsis; 01211 cur->description = description; 01212 cur->next = NULL; 01213 01214 ast_manager_register_struct(cur); 01215 01216 return 0; 01217 } 01218 01219 static int registered = 0; 01220 01221 int init_manager(void) 01222 { 01223 struct ast_config *cfg; 01224 char *val; 01225 int oldportno = portno; 01226 static struct sockaddr_in ba; 01227 int x = 1; 01228 if (!registered) { 01229 /* Register default actions */ 01230 ast_manager_register2("Ping", 0, action_ping, "Ping", mandescr_ping); 01231 ast_manager_register( "Events", 0, action_events, "Contol Event Flow" ); 01232 ast_manager_register( "Logoff", 0, action_logoff, "Logoff Manager" ); 01233 ast_manager_register( "Hangup", EVENT_FLAG_CALL, action_hangup, "Hangup Channel" ); 01234 ast_manager_register( "Status", EVENT_FLAG_CALL, action_status, "Status" ); 01235 ast_manager_register( "Setvar", EVENT_FLAG_CALL, action_setvar, "Set Channel Variable" ); 01236 ast_manager_register( "Getvar", EVENT_FLAG_CALL, action_getvar, "Gets a Channel Variable" ); 01237 ast_manager_register( "Redirect", EVENT_FLAG_CALL, action_redirect, "Redirect" ); 01238 ast_manager_register2("Originate", EVENT_FLAG_CALL, action_originate, "Originate Call", mandescr_originate); 01239 ast_manager_register( "MailboxStatus", EVENT_FLAG_CALL, action_mailboxstatus, "Check Mailbox" ); 01240 ast_manager_register( "Command", EVENT_FLAG_COMMAND, action_command, "Execute Command" ); 01241 ast_manager_register( "ExtensionState", EVENT_FLAG_CALL, action_extensionstate, "Check Extension Status" ); 01242 ast_manager_register( "AbsoluteTimeout", EVENT_FLAG_CALL, action_timeout, "Set Absolute Timeout" ); 01243 ast_manager_register( "MailboxCount", EVENT_FLAG_CALL, action_mailboxcount, "Check Mailbox Message Count" ); 01244 ast_manager_register2("ListCommands", 0, action_listcommands, "List available manager commands", mandescr_listcommands); 01245 01246 ast_cli_register(&show_mancmd_cli); 01247 ast_cli_register(&show_mancmds_cli); 01248 ast_cli_register(&show_manconn_cli); 01249 ast_extension_state_add(NULL, NULL, manager_state_cb, NULL); 01250 registered = 1; 01251 } 01252 portno = DEFAULT_MANAGER_PORT; 01253 cfg = ast_load("manager.conf"); 01254 if (!cfg) { 01255 ast_log(LOG_NOTICE, "Unable to open management configuration manager.conf. Call management disabled.\n"); 01256 return 0; 01257 } 01258 memset(&ba, 0, sizeof(ba)); 01259 val = ast_variable_retrieve(cfg, "general", "enabled"); 01260 if (val) 01261 enabled = ast_true(val); 01262 01263 val = ast_variable_retrieve(cfg, "general", "block-sockets"); 01264 if(val) 01265 block_sockets = ast_true(val); 01266 01267 if ((val = ast_variable_retrieve(cfg, "general", "port"))) { 01268 if (sscanf(val, "%d", &portno) != 1) { 01269 ast_log(LOG_WARNING, "Invalid port number '%s'\n", val); 01270 portno = DEFAULT_MANAGER_PORT; 01271 } 01272 } else if ((val = ast_variable_retrieve(cfg, "general", "portno"))) { 01273 if (sscanf(val, "%d", &portno) != 1) { 01274 ast_log(LOG_WARNING, "Invalid port number '%s'\n", val); 01275 portno = DEFAULT_MANAGER_PORT; 01276 } 01277 ast_log(LOG_NOTICE, "Use of portno in manager.conf deprecated. Please use 'port=%s' instead.\n", val); 01278 } 01279 01280 ba.sin_family = AF_INET; 01281 ba.sin_port = htons(portno); 01282 memset(&ba.sin_addr, 0, sizeof(ba.sin_addr)); 01283 01284 if ((val = ast_variable_retrieve(cfg, "general", "bindaddr"))) { 01285 if (!inet_aton(val, &ba.sin_addr)) { 01286 ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val); 01287 memset(&ba.sin_addr, 0, sizeof(ba.sin_addr)); 01288 } 01289 } 01290 01291 if ((asock > -1) && ((portno != oldportno) || !enabled)) { 01292 #if 0 01293 /* Can't be done yet */ 01294 close(asock); 01295 asock = -1; 01296 #else 01297 ast_log(LOG_WARNING, "Unable to change management port / enabled\n"); 01298 #endif 01299 } 01300 ast_destroy(cfg); 01301 01302 /* If not enabled, do nothing */ 01303 if (!enabled) { 01304 return 0; 01305 } 01306 if (asock < 0) { 01307 asock = socket(AF_INET, SOCK_STREAM, 0); 01308 if (asock < 0) { 01309 ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno)); 01310 return -1; 01311 } 01312 setsockopt(asock, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x)); 01313 if (bind(asock, (struct sockaddr *)&ba, sizeof(ba))) { 01314 ast_log(LOG_WARNING, "Unable to bind socket: %s\n", strerror(errno)); 01315 close(asock); 01316 asock = -1; 01317 return -1; 01318 } 01319 if (listen(asock, 2)) { 01320 ast_log(LOG_WARNING, "Unable to listen on socket: %s\n", strerror(errno)); 01321 close(asock); 01322 asock = -1; 01323 return -1; 01324 } 01325 if (option_verbose) 01326 ast_verbose("Asterisk Management interface listening on port %d\n", portno); 01327 pthread_create(&t, NULL, accept_thread, NULL); 01328 } 01329 return 0; 01330 } 01331 01332 int reload_manager(void) 01333 { 01334 manager_event(EVENT_FLAG_SYSTEM, "Reload", "Message: Reload Requested\r\n"); 01335 return init_manager(); 01336 }

Generated on Sat Jun 12 16:40:58 2004 for Asterisk by doxygen 1.3.7