Fri Feb 21 07:00:01 CET 2003
[asterisk/asterisk.git] / manager.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Channel Management and more
5  * 
6  * Copyright (C) 1999, Mark Spencer
7  *
8  * Mark Spencer <markster@linux-support.net>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <pthread.h>
17 #include <string.h>
18 #include <sys/time.h>
19 #include <sys/socket.h>
20 #include <netinet/in.h>
21 #include <arpa/inet.h>
22 #include <signal.h>
23 #include <errno.h>
24 #include <unistd.h>
25 #include <asterisk/channel.h>
26 #include <asterisk/file.h>
27 #include <asterisk/manager.h>
28 #include <asterisk/config.h>
29 #include <asterisk/lock.h>
30 #include <asterisk/logger.h>
31 #include <asterisk/options.h>
32 #include <asterisk/cli.h>
33 #include <asterisk/pbx.h>
34
35 static int enabled = 0;
36 static int portno = DEFAULT_MANAGER_PORT;
37 static int asock = -1;
38 static pthread_t t;
39 static pthread_mutex_t sessionlock = AST_MUTEX_INITIALIZER;
40
41 static struct permalias {
42         int num;
43         char *label;
44 } perms[] = {
45         { EVENT_FLAG_SYSTEM, "system" },
46         { EVENT_FLAG_CALL, "call" },
47         { EVENT_FLAG_LOG, "log" },
48         { EVENT_FLAG_VERBOSE, "verbose" },
49         { EVENT_FLAG_COMMAND, "command" },
50         { EVENT_FLAG_AGENT, "agent" },
51         { -1, "all" },
52 };
53
54 static struct mansession *sessions = NULL;
55 static struct manager_action *first_action = NULL;
56 static pthread_mutex_t actionlock = AST_MUTEX_INITIALIZER;
57
58 static int handle_showmancmds(int fd, int argc, char *argv[])
59 {
60         struct manager_action *cur = first_action;
61
62         ast_pthread_mutex_lock(&actionlock);
63         while(cur) { /* Walk the list of actions */
64                 ast_cli(fd, "\t%s  %s\r\n",cur->action, cur->synopsis);
65                 cur = cur->next;
66         }
67
68         ast_pthread_mutex_unlock(&actionlock);
69         return RESULT_SUCCESS;
70 }
71
72 static int handle_showmanconn(int fd, int argc, char *argv[])
73 {
74         struct mansession *s;
75
76         ast_pthread_mutex_lock(&sessionlock);
77         s = sessions;
78         ast_cli(fd, "  Username\tIP Address\n");
79         while(s) {
80                 ast_cli(fd, "  %s\t\t%s\r\n",s->username, inet_ntoa(s->sin.sin_addr));
81                 s = s->next;
82         }
83
84         ast_pthread_mutex_unlock(&sessionlock);
85         return RESULT_SUCCESS;
86 }
87
88 static char showmancmds_help[] = 
89 "Usage: show manager commands\n"
90 "       Prints a listing of all the available manager commands.\n";
91
92 static char showmanconn_help[] = 
93 "Usage: show manager connected\n"
94 "       Prints a listing of the users that are connected to the\n"
95 "manager interface.\n";
96
97 static struct ast_cli_entry show_mancmds_cli =
98         { { "show", "manager", "commands", NULL },
99         handle_showmancmds, "Show manager commands", showmancmds_help };
100
101 static struct ast_cli_entry show_manconn_cli =
102         { { "show", "manager", "connected", NULL },
103         handle_showmanconn, "Show connected manager users", showmanconn_help };
104
105 static void destroy_session(struct mansession *s)
106 {
107         struct mansession *cur, *prev = NULL;
108         ast_pthread_mutex_lock(&sessionlock);
109         cur = sessions;
110         while(cur) {
111                 if (cur == s)
112                         break;
113                 prev = cur;
114                 cur = cur->next;
115         }
116         if (cur) {
117                 if (prev)
118                         prev->next = cur->next;
119                 else
120                         sessions = cur->next;
121                 if (s->fd > -1)
122                         close(s->fd);
123                 free(s);
124         } else
125                 ast_log(LOG_WARNING, "Trying to delete non-existant session %p?\n", s);
126         ast_pthread_mutex_unlock(&sessionlock);
127         
128 }
129
130 static char *get_header(struct message *m, char *var)
131 {
132         char cmp[80];
133         int x;
134         snprintf(cmp, sizeof(cmp), "%s: ", var);
135         for (x=0;x<m->hdrcount;x++)
136                 if (!strncasecmp(cmp, m->headers[x], strlen(cmp)))
137                         return m->headers[x] + strlen(cmp);
138         return "";
139 }
140
141 static void send_error(struct mansession *s, char *error)
142 {
143         ast_pthread_mutex_lock(&s->lock);
144         ast_cli(s->fd, "Response: Error\r\n");
145         ast_cli(s->fd, "Message: %s\r\n\r\n", error);
146         ast_pthread_mutex_unlock(&s->lock);
147 }
148
149 static void send_response(struct mansession *s, char *resp, char *msg)
150 {
151         ast_pthread_mutex_lock(&s->lock);
152         ast_cli(s->fd, "Response: %s\r\n", resp);
153         if (msg)
154                 ast_cli(s->fd, "Message: %s\r\n\r\n", msg);
155         else
156                 ast_cli(s->fd, "\r\n");
157         ast_pthread_mutex_unlock(&s->lock);
158 }
159
160 static void send_ack(struct mansession *s, char *msg)
161 {
162         send_response(s, "Success", msg);
163 }
164
165 static int get_perm(char *instr)
166 {
167         char tmp[256];
168         char *c;
169         int x;
170         int ret = 0;
171         char *stringp=NULL;
172         if (!instr)
173                 return 0;
174         strncpy(tmp, instr, sizeof(tmp) - 1);
175         stringp=tmp;
176         c = strsep(&stringp, ",");
177         while(c) {
178                 for (x=0;x<sizeof(perms) / sizeof(perms[0]);x++) {
179                         if (!strcasecmp(perms[x].label, c)) 
180                                 ret |= perms[x].num;
181                 }
182                 c = strsep(&stringp, ",");
183         }
184         return ret;
185 }
186
187 static int authenticate(struct mansession *s, struct message *m)
188 {
189         struct ast_config *cfg;
190         char *cat;
191         char *user = get_header(m, "Username");
192         char *pass = get_header(m, "Secret");
193         cfg = ast_load("manager.conf");
194         if (!cfg)
195                 return -1;
196         cat = ast_category_browse(cfg, NULL);
197         while(cat) {
198                 if (strcasecmp(cat, "general")) {
199                         /* This is a user */
200                         if (!strcasecmp(cat, user)) {
201                                 char *password = ast_variable_retrieve(cfg, cat, "secret");
202                                 if (password && !strcasecmp(password, pass)) {
203                                         break;
204                                 } else {
205                                         ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", inet_ntoa(s->sin.sin_addr), user);
206                                         ast_destroy(cfg);
207                                         return -1;
208                                 }       
209                         }
210                 }
211                 cat = ast_category_browse(cfg, cat);
212         }
213         if (cat) {
214                 strncpy(s->username, cat, sizeof(s->username) - 1);
215                 s->readperm = get_perm(ast_variable_retrieve(cfg, cat, "read"));
216                 s->writeperm = get_perm(ast_variable_retrieve(cfg, cat, "write"));
217                 ast_destroy(cfg);
218                 return 0;
219         }
220         ast_log(LOG_NOTICE, "%s tried to authenticate with non-existant user '%s'\n", inet_ntoa(s->sin.sin_addr), user);
221         ast_destroy(cfg);
222         return -1;
223 }
224
225 static int action_ping(struct mansession *s, struct message *m)
226 {
227         send_response(s, "Pong", NULL);
228         return 0;
229 }
230
231 static int action_logoff(struct mansession *s, struct message *m)
232 {
233         send_response(s, "Goodbye", "Thanks for all the fish.");
234         return -1;
235 }
236
237 static int action_hangup(struct mansession *s, struct message *m)
238 {
239         struct ast_channel *c = NULL;
240         char *name = get_header(m, "Channel");
241         if (!strlen(name)) {
242                 send_error(s, "No channel specified");
243                 return 0;
244         }
245         c = ast_channel_walk(NULL);
246         while(c) {
247                 if (!strcasecmp(c->name, name)) {
248                         break;
249                 }
250                 c = ast_channel_walk(c);
251         }
252         if (!c) {
253                 send_error(s, "No such channel");
254                 return 0;
255         }
256         ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
257         send_ack(s, "Channel Hungup");
258         return 0;
259 }
260
261 static int action_status(struct mansession *s, struct message *m)
262 {
263         struct ast_channel *c;
264         char bridge[256];
265         send_ack(s, "Channel status will follow");
266         c = ast_channel_walk(NULL);
267         while(c) {
268                 if (c->bridge)
269                         snprintf(bridge, sizeof(bridge), "Link: %s\r\n", c->bridge->name);
270                 else
271                         strcpy(bridge, "");
272                 if (c->pbx) {
273                         ast_cli(s->fd,
274                         "Event: Status\r\n"
275                         "Channel: %s\r\n"
276                         "CallerID: %s\r\n"
277                         "State: %s\r\n"
278                         "Context: %s\r\n"
279                         "Extension: %s\r\n"
280                         "Priority: %d\r\n"
281                         "%s"
282                         "\r\n",
283                         c->name, c->callerid ? c->callerid : "<unknown>", 
284                         ast_state2str(c->_state), c->context,
285                         c->exten, c->priority, bridge);
286                 } else {
287                         ast_cli(s->fd,
288                         "Event: Status\r\n"
289                         "Channel: %s\r\n"
290                         "CallerID: %s\r\n"
291                         "State: %s\r\n"
292                         "%s"
293                         "\r\n",
294                         c->name, c->callerid ? c->callerid : "<unknown>", 
295                         ast_state2str(c->_state), bridge);
296                 }
297                 c = ast_channel_walk(c);
298         }
299         return 0;
300 }
301
302 static int action_redirect(struct mansession *s, struct message *m)
303 {
304         char *name = get_header(m, "Channel");
305         char *name2 = get_header(m, "ExtraChannel");
306         char *exten = get_header(m, "Exten");
307         char *context = get_header(m, "Context");
308         char *priority = get_header(m, "Priority");
309         int pi = 0;
310         int res;
311         if (!name || !strlen(name)) {
312                 send_error(s, "Channel not specified");
313                 return 0;
314         }
315         if (strlen(priority) && (sscanf(priority, "%d", &pi) != 1)) {
316                 send_error(s, "Invalid priority\n");
317                 return 0;
318         }
319         res = ast_async_goto_by_name(name, context, exten, pi);
320         if (!res) {
321                 if (strlen(name2)) {
322                         res = ast_async_goto_by_name(name2, context, exten, pi);
323                         if (!res)
324                                 send_ack(s, "Dual Redirect successful");
325                         else
326                                 send_error(s, "Secondary redirect failed");
327                 } else
328                         send_ack(s, "Redirect successful");
329         } else
330                 send_error(s, "Redirect failed");
331         return 0;
332 }
333
334 static int action_command(struct mansession *s, struct message *m)
335 {
336         char *cmd = get_header(m, "Command");
337         ast_pthread_mutex_lock(&s->lock);
338         s->blocking = 1;
339         ast_pthread_mutex_unlock(&s->lock);
340         ast_cli(s->fd, "Response: Follows\r\n");
341         ast_cli_command(s->fd, cmd);
342         ast_cli(s->fd, "--END COMMAND--\r\n\r\n");
343         ast_pthread_mutex_lock(&s->lock);
344         s->blocking = 0;
345         ast_pthread_mutex_unlock(&s->lock);
346         return 0;
347 }
348
349 static int action_originate(struct mansession *s, struct message *m)
350 {
351         char *name = get_header(m, "Channel");
352         char *exten = get_header(m, "Exten");
353         char *context = get_header(m, "Context");
354         char *priority = get_header(m, "Priority");
355         char *timeout = get_header(m, "Timeout");
356         char *callerid = get_header(m, "CallerID");
357         char *tech, *data;
358         int pi = 0;
359         int res;
360         int to = 30000;
361         int reason = 0;
362         char tmp[256];
363         if (!name) {
364                 send_error(s, "Channel not specified");
365                 return 0;
366         }
367         if (strlen(priority) && (sscanf(priority, "%d", &pi) != 1)) {
368                 send_error(s, "Invalid priority\n");
369                 return 0;
370         }
371         if (strlen(timeout) && (sscanf(timeout, "%d", &to) != 1)) {
372                 send_error(s, "Invalid timeout\n");
373                 return 0;
374         }
375         strncpy(tmp, name, sizeof(tmp) - 1);
376         tech = tmp;
377         data = strchr(tmp, '/');
378         if (!data) {
379                 send_error(s, "Invalid channel\n");
380                 return 0;
381         }
382         *data = '\0';
383         data++;
384         res = ast_pbx_outgoing_exten(tech, AST_FORMAT_SLINEAR, data, to, context, exten, pi, &reason, 0, strlen(callerid) ? callerid : NULL, NULL );
385         if (!res)
386                 send_ack(s, "Originate successfully queued");
387         else
388                 send_error(s, "Originate failed");
389         return 0;
390 }
391
392 static int process_message(struct mansession *s, struct message *m)
393 {
394         char action[80];
395         struct manager_action *tmp = first_action;
396
397         strncpy(action, get_header(m, "Action"), sizeof(action));
398
399         if (!strlen(action)) {
400                 send_error(s, "Missing action in request");
401                 return 0;
402         }
403         if (!s->authenticated) {
404                 if (!strcasecmp(action, "Login")) {
405                         if (authenticate(s, m)) {
406                                 sleep(1);
407                                 send_error(s, "Authentication failed");
408                                 return -1;
409                         } else {
410                                 s->authenticated = 1;
411                                 if (option_verbose > 1) 
412                                         ast_verbose(VERBOSE_PREFIX_2 "Manager '%s' logged on from %s\n", s->username, inet_ntoa(s->sin.sin_addr));
413                                 ast_log(LOG_EVENT, "Manager '%s' logged on from %s\n", s->username, inet_ntoa(s->sin.sin_addr));
414                                 send_ack(s, "Authentication accepted");
415                         }
416                 } else 
417                         send_error(s, "Authentication Required");
418         } else {
419                 while( tmp ) {          
420                         if (!strcasecmp(action, tmp->action)) {
421                                 if ((s->writeperm & tmp->authority) == tmp->authority) {
422                                         if (tmp->func(s, m))
423                                                 return -1;
424                                 } else {
425                                         send_error(s, "Permission denied");
426                                 }
427                                 return 0;
428                         }
429                         tmp = tmp->next;
430                 }
431                 send_error(s, "Invalid/unknown command");
432         }
433         return 0;
434 }
435
436 static int get_input(struct mansession *s, char *output)
437 {
438         /* output must have at least sizeof(s->inbuf) space */
439         int res;
440         int x;
441         fd_set fds;
442         for (x=1;x<s->inlen;x++) {
443                 if ((s->inbuf[x] == '\n') && (s->inbuf[x-1] == '\r')) {
444                         /* Copy output data up to and including \r\n */
445                         memcpy(output, s->inbuf, x + 1);
446                         /* Add trailing \0 */
447                         output[x+1] = '\0';
448                         /* Move remaining data back to the front */
449                         memmove(s->inbuf, s->inbuf + x + 1, s->inlen - x);
450                         s->inlen -= (x + 1);
451                         return 1;
452                 }
453         } 
454         if (s->inlen >= sizeof(s->inbuf) - 1) {
455                 ast_log(LOG_WARNING, "Dumping long line with no return from %s: %s\n", inet_ntoa(s->sin.sin_addr), s->inbuf);
456                 s->inlen = 0;
457         }
458         FD_ZERO(&fds);
459         FD_SET(s->fd, &fds);
460         res = select(s->fd + 1, &fds, NULL, NULL, NULL);
461         if (res < 0) {
462                 ast_log(LOG_WARNING, "Select returned error: %s\n", strerror(errno));
463         } else if (res > 0) {
464                 ast_pthread_mutex_lock(&s->lock);
465                 res = read(s->fd, s->inbuf + s->inlen, sizeof(s->inbuf) - 1 - s->inlen);
466                 ast_pthread_mutex_unlock(&s->lock);
467                 if (res < 1)
468                         return -1;
469         }
470         s->inlen += res;
471         s->inbuf[s->inlen] = '\0';
472         return 0;
473 }
474
475 static void *session_do(void *data)
476 {
477         struct mansession *s = data;
478         struct message m;
479         int res;
480         
481         ast_pthread_mutex_lock(&s->lock);
482         ast_cli(s->fd, "Asterisk Call Manager/1.0\r\n");
483         ast_pthread_mutex_unlock(&s->lock);
484         memset(&m, 0, sizeof(&m));
485         for (;;) {
486                 res = get_input(s, m.headers[m.hdrcount]);
487                 if (res > 0) {
488                         /* Strip trailing \r\n */
489                         if (strlen(m.headers[m.hdrcount]) < 2)
490                                 continue;
491                         m.headers[m.hdrcount][strlen(m.headers[m.hdrcount]) - 2] = '\0';
492                         if (!strlen(m.headers[m.hdrcount])) {
493                                 if (process_message(s, &m))
494                                         break;
495                                 memset(&m, 0, sizeof(&m));
496                         } else if (m.hdrcount < MAX_HEADERS - 1)
497                                 m.hdrcount++;
498                 } else if (res < 0)
499                         break;
500         }
501         if (s->authenticated) {
502                 if (option_verbose > 1) 
503                         ast_verbose(VERBOSE_PREFIX_2 "Manager '%s' logged off from %s\n", s->username, inet_ntoa(s->sin.sin_addr));
504                 ast_log(LOG_EVENT, "Manager '%s' logged off from %s\n", s->username, inet_ntoa(s->sin.sin_addr));
505         } else {
506                 if (option_verbose > 1)
507                         ast_verbose(VERBOSE_PREFIX_2 "Connect attempt from '%s' unable to authenticate\n", inet_ntoa(s->sin.sin_addr));
508                 ast_log(LOG_EVENT, "Failed attempt from %s\n", inet_ntoa(s->sin.sin_addr));
509         }
510         destroy_session(s);
511         return NULL;
512 }
513
514 static void *accept_thread(void *ignore)
515 {
516         int as;
517         struct sockaddr_in sin;
518         int sinlen;
519         struct mansession *s;
520         for (;;) {
521                 sinlen = sizeof(sin);
522                 as = accept(asock, &sin, &sinlen);
523                 if (as < 0) {
524                         ast_log(LOG_NOTICE, "Accept returned -1: %s\n", strerror(errno));
525                         continue;
526                 }
527                 s = malloc(sizeof(struct mansession));
528                 if (!s) {
529                         ast_log(LOG_WARNING, "Failed to allocate management session: %s\n", strerror(errno));
530                         continue;
531                 } 
532                 memset(s, 0, sizeof(struct mansession));
533                 memcpy(&s->sin, &sin, sizeof(sin));
534                 ast_pthread_mutex_init(&s->lock);
535                 s->fd = as;
536                 ast_pthread_mutex_lock(&sessionlock);
537                 s->next = sessions;
538                 sessions = s;
539                 ast_pthread_mutex_unlock(&sessionlock);
540                 if (pthread_create(&t, NULL, session_do, s))
541                         destroy_session(s);
542         }
543         return NULL;
544 }
545
546 int manager_event(int category, char *event, char *fmt, ...)
547 {
548         struct mansession *s;
549         char tmp[4096];
550         va_list ap;
551
552         ast_pthread_mutex_lock(&sessionlock);
553         s = sessions;
554         while(s) {
555                 if ((s->readperm & category) == category) {
556                         ast_pthread_mutex_lock(&s->lock);
557                         if (!s->blocking) {
558                                 ast_cli(s->fd, "Event: %s\r\n", event);
559                                 va_start(ap, fmt);
560                                 vsnprintf(tmp, sizeof(tmp), fmt, ap);
561                                 va_end(ap);
562                                 write(s->fd, tmp, strlen(tmp));
563                                 ast_cli(s->fd, "\r\n");
564                         }
565                         ast_pthread_mutex_unlock(&s->lock);
566                 }
567                 s = s->next;
568         }
569         ast_pthread_mutex_unlock(&sessionlock);
570         return 0;
571 }
572
573 int ast_manager_unregister( char *action ) {
574         struct manager_action *cur = first_action, *prev = first_action;
575
576         ast_pthread_mutex_lock(&actionlock);
577         while( cur ) {          
578                 if (!strcasecmp(action, cur->action)) {
579                         prev->next = cur->next;
580                         free(cur);
581                         if (option_verbose > 1) 
582                                 ast_verbose(VERBOSE_PREFIX_2 "Manager unregistered action %s\n", action);
583                         ast_pthread_mutex_unlock(&actionlock);
584                         return 0;
585                 }
586                 prev = cur;
587                 cur = cur->next;
588         }
589         ast_pthread_mutex_unlock(&actionlock);
590         return 0;
591 }
592
593 int ast_manager_register( char *action, int auth, 
594         int (*func)(struct mansession *s, struct message *m), char *synopsis)
595 {
596         struct manager_action *cur = first_action, *prev = NULL;
597
598         ast_pthread_mutex_lock(&actionlock);
599         while(cur) { /* Walk the list of actions */
600                 prev = cur; 
601                 cur = cur->next;
602         }
603         cur = malloc( sizeof(struct manager_action) );
604         if( !cur ) {
605                 ast_log(LOG_WARNING, "Manager: out of memory trying to register action\n");
606                 ast_pthread_mutex_unlock(&actionlock);
607                 return -1;
608         }
609         strncpy( cur->action, action, 255 );
610         cur->authority = auth;
611         cur->func = func;
612         cur->synopsis = synopsis;
613         cur->next = NULL;
614
615         if( prev ) prev->next = cur;
616         else first_action = cur;
617
618         if (option_verbose > 1) 
619                 ast_verbose(VERBOSE_PREFIX_2 "Manager registered action %s\n", action);
620         ast_pthread_mutex_unlock(&actionlock);
621         return 0;
622 }
623
624 static int registered = 0;
625
626 int init_manager(void)
627 {
628         struct ast_config *cfg;
629         char *val;
630         int oldportno = portno;
631         static struct sockaddr_in ba;
632         int x = 1;
633         if (!registered) {
634                 /* Register default actions */
635                 ast_manager_register( "Ping", 0, action_ping, "Ping" );
636                 ast_manager_register( "Logoff", 0, action_logoff, "Logoff Manager" );
637                 ast_manager_register( "Hangup", EVENT_FLAG_CALL, action_hangup, "Hangup Channel" );
638                 ast_manager_register( "Status", EVENT_FLAG_CALL, action_status, "Status" );
639                 ast_manager_register( "Redirect", EVENT_FLAG_CALL, action_redirect, "Redirect" );
640                 ast_manager_register( "Originate", EVENT_FLAG_CALL, action_originate, "Originate Call" );
641                 ast_manager_register( "Command", EVENT_FLAG_COMMAND, action_command, "Execute Command" );
642
643                 ast_cli_register(&show_mancmds_cli);
644                 ast_cli_register(&show_manconn_cli);
645                 registered = 1;
646         }
647         portno = DEFAULT_MANAGER_PORT;
648         cfg = ast_load("manager.conf");
649         if (!cfg) {
650                 ast_log(LOG_NOTICE, "Unable to open management configuration manager.conf.  Call management disabled.\n");
651                 return 0;
652         }
653         memset(&ba, 0, sizeof(ba));
654         val = ast_variable_retrieve(cfg, "general", "enabled");
655         if (val)
656                 enabled = ast_true(val);
657
658         if ((val = ast_variable_retrieve(cfg, "general", "portno"))) {
659                 if (sscanf(val, "%d", &portno) != 1) {
660                         ast_log(LOG_WARNING, "Invalid port number '%s'\n", val);
661                         portno = DEFAULT_MANAGER_PORT;
662                 }
663         }
664         
665         ba.sin_family = AF_INET;
666         ba.sin_port = htons(portno);
667         memset(&ba.sin_addr, 0, sizeof(ba.sin_addr));
668         
669         if ((val = ast_variable_retrieve(cfg, "general", "bindaddr"))) {
670                 if (!inet_aton(val, &ba.sin_addr)) { 
671                         ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val);
672                         memset(&ba.sin_addr, 0, sizeof(ba.sin_addr));
673                 }
674         }
675
676         if ((asock > -1) && ((portno != oldportno) || !enabled)) {
677 #if 0
678                 /* Can't be done yet */
679                 close(asock);
680                 asock = -1;
681 #else
682                 ast_log(LOG_WARNING, "Unable to change management port / enabled\n");
683 #endif
684         }
685         /* If not enabled, do nothing */
686         if (!enabled)
687                 return 0;
688         if (asock < 0) {
689                 asock = socket(AF_INET, SOCK_STREAM, 0);
690                 if (asock < 0) {
691                         ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
692                         return -1;
693                 }
694                 setsockopt(asock, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
695                 if (bind(asock, &ba, sizeof(ba))) {
696                         ast_log(LOG_WARNING, "Unable to bind socket: %s\n", strerror(errno));
697                         close(asock);
698                         asock = -1;
699                         return -1;
700                 }
701                 if (listen(asock, 2)) {
702                         ast_log(LOG_WARNING, "Unable to listen on socket: %s\n", strerror(errno));
703                         close(asock);
704                         asock = -1;
705                         return -1;
706                 }
707                 if (option_verbose)
708                         ast_verbose("Asterisk Management interface listening on port %d\n", portno);
709                 pthread_create(&t, NULL, accept_thread, NULL);
710         }
711         ast_destroy(cfg);
712         return 0;
713 }
714
715 int reload_manager(void)
716 {
717         return init_manager();
718 }