Add IPv6 Support To Manager
authorMichael L. Young <elgueromexicano@gmail.com>
Wed, 20 Jun 2012 03:18:50 +0000 (03:18 +0000)
committerMichael L. Young <elgueromexicano@gmail.com>
Wed, 20 Jun 2012 03:18:50 +0000 (03:18 +0000)
This patch adds IPv6 support to AMI.

(Closes issue ASTERISK-19965)
Reported by: Michael L. Young
Tested by: Michael L. Young
Patches:
    ami_ipv6_v3.diff uploaded by Michael L. Young (license 5026)

Review: https://reviewboard.asterisk.org/r/1968/

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@369126 65c4cc65-6c06-0410-ace0-fbb531ad65f3

CHANGES
main/manager.c

diff --git a/CHANGES b/CHANGES
index 61ea78b..782b37d 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -200,6 +200,8 @@ AMI (Asterisk Manager Interface) changes
    behavior to hanging up a single channel is unchanged, but if you pass a regex,
    the manager will send you a list of channels back that were hung up.
 
+ * Support for IPv6 addresses has been added.
+
 FAX changes
 -----------
  * FAXOPT(faxdetect) will enable a generic fax detect framehook for dialplan
index 588d880..c7ff32e 100644 (file)
@@ -1018,7 +1018,7 @@ static const struct {
  */
 struct mansession_session {
                                /*! \todo XXX need to document which fields it is protecting */
-       struct sockaddr_in sin; /*!< address we are connecting from */
+       struct ast_sockaddr addr;       /*!< address we are connecting from */
        FILE *f;                /*!< fdopen() on the underlying fd */
        int fd;                 /*!< descriptor used for output. Either the socket (AMI) or a temporary file (HTTP) */
        int inuse;              /*!< number of HTTP sessions using this entry */
@@ -1395,7 +1395,7 @@ static void session_destructor(void *obj)
 }
 
 /*! \brief Allocate manager session structure and add it to the list of sessions */
-static struct mansession_session *build_mansession(struct sockaddr_in sin)
+static struct mansession_session *build_mansession(const struct ast_sockaddr *addr)
 {
        struct mansession_session *newsession;
 
@@ -1417,7 +1417,7 @@ static struct mansession_session *build_mansession(struct sockaddr_in sin)
        newsession->waiting_thread = AST_PTHREADT_NULL;
        newsession->writetimeout = 100;
        newsession->send_events = -1;
-       newsession->sin = sin;
+       ast_sockaddr_copy(&newsession->addr, addr);
 
        ao2_link(sessions, newsession);
 
@@ -1728,8 +1728,8 @@ static char *handle_showmanconn(struct ast_cli_entry *e, int cmd, struct ast_cli
 {
        struct mansession_session *session;
        time_t now = time(NULL);
-#define HSMCONN_FORMAT1 "  %-15.15s  %-15.15s  %-10.10s  %-10.10s  %-8.8s  %-8.8s  %-5.5s  %-5.5s\n"
-#define HSMCONN_FORMAT2 "  %-15.15s  %-15.15s  %-10d  %-10d  %-8d  %-8d  %-5.5d  %-5.5d\n"
+#define HSMCONN_FORMAT1 "  %-15.15s  %-55.55s  %-10.10s  %-10.10s  %-8.8s  %-8.8s  %-5.5s  %-5.5s\n"
+#define HSMCONN_FORMAT2 "  %-15.15s  %-55.55s  %-10d  %-10d  %-8d  %-8d  %-5.5d  %-5.5d\n"
        int count = 0;
        struct ao2_iterator i;
 
@@ -1750,7 +1750,7 @@ static char *handle_showmanconn(struct ast_cli_entry *e, int cmd, struct ast_cli
        i = ao2_iterator_init(sessions, 0);
        while ((session = ao2_iterator_next(&i))) {
                ao2_lock(session);
-               ast_cli(a->fd, HSMCONN_FORMAT2, session->username, ast_inet_ntoa(session->sin.sin_addr), (int)(session->sessionstart), (int)(now - session->sessionstart), session->fd, session->inuse, session->readperm, session->writeperm);
+               ast_cli(a->fd, HSMCONN_FORMAT2, session->username, ast_sockaddr_stringify_addr(&session->addr), (int)(session->sessionstart), (int)(now - session->sessionstart), session->fd, session->inuse, session->readperm, session->writeperm);
                count++;
                ao2_unlock(session);
                unref_mansession(session);
@@ -2211,7 +2211,6 @@ static enum ast_security_event_transport_type mansession_get_transport(const str
 
 static void report_invalid_user(const struct mansession *s, const char *username)
 {
-       struct ast_sockaddr addr_remote;
        char session_id[32];
        struct ast_security_event_inval_acct_id inval_acct_id = {
                .common.event_type = AST_SECURITY_EVENT_INVAL_ACCT_ID,
@@ -2224,14 +2223,12 @@ static void report_invalid_user(const struct mansession *s, const char *username
                        .transport = mansession_get_transport(s),
                },
                .common.remote_addr = {
-                       .addr      = &addr_remote,
+                       .addr      = &s->session->addr,
                        .transport = mansession_get_transport(s),
                },
                .common.session_id = session_id,
        };
 
-       ast_sockaddr_from_sin(&addr_remote, &s->session->sin);
-
        snprintf(session_id, sizeof(session_id), "%p", s);
 
        ast_security_event_report(AST_SEC_EVT(&inval_acct_id));
@@ -2239,7 +2236,6 @@ static void report_invalid_user(const struct mansession *s, const char *username
 
 static void report_failed_acl(const struct mansession *s, const char *username)
 {
-       struct ast_sockaddr addr_remote;
        char session_id[32];
        struct ast_security_event_failed_acl failed_acl_event = {
                .common.event_type = AST_SECURITY_EVENT_FAILED_ACL,
@@ -2252,14 +2248,12 @@ static void report_failed_acl(const struct mansession *s, const char *username)
                        .transport = mansession_get_transport(s),
                },
                .common.remote_addr = {
-                       .addr      = &addr_remote,
+                       .addr      = &s->session->addr,
                        .transport = mansession_get_transport(s),
                },
                .common.session_id = session_id,
        };
 
-       ast_sockaddr_from_sin(&addr_remote, &s->session->sin);
-
        snprintf(session_id, sizeof(session_id), "%p", s->session);
 
        ast_security_event_report(AST_SEC_EVT(&failed_acl_event));
@@ -2267,7 +2261,6 @@ static void report_failed_acl(const struct mansession *s, const char *username)
 
 static void report_inval_password(const struct mansession *s, const char *username)
 {
-       struct ast_sockaddr addr_remote;
        char session_id[32];
        struct ast_security_event_inval_password inval_password = {
                .common.event_type = AST_SECURITY_EVENT_INVAL_PASSWORD,
@@ -2280,14 +2273,12 @@ static void report_inval_password(const struct mansession *s, const char *userna
                        .transport = mansession_get_transport(s),
                },
                .common.remote_addr = {
-                       .addr      = &addr_remote,
+                       .addr      = &s->session->addr,
                        .transport = mansession_get_transport(s),
                },
                .common.session_id = session_id,
        };
 
-       ast_sockaddr_from_sin(&addr_remote, &s->session->sin);
-
        snprintf(session_id, sizeof(session_id), "%p", s->session);
 
        ast_security_event_report(AST_SEC_EVT(&inval_password));
@@ -2295,7 +2286,6 @@ static void report_inval_password(const struct mansession *s, const char *userna
 
 static void report_auth_success(const struct mansession *s)
 {
-       struct ast_sockaddr addr_remote;
        char session_id[32];
        struct ast_security_event_successful_auth successful_auth = {
                .common.event_type = AST_SECURITY_EVENT_SUCCESSFUL_AUTH,
@@ -2308,14 +2298,12 @@ static void report_auth_success(const struct mansession *s)
                        .transport = mansession_get_transport(s),
                },
                .common.remote_addr = {
-                       .addr      = &addr_remote,
+                       .addr      = &s->session->addr,
                        .transport = mansession_get_transport(s),
                },
                .common.session_id = session_id,
        };
 
-       ast_sockaddr_from_sin(&addr_remote, &s->session->sin);
-
        snprintf(session_id, sizeof(session_id), "%p", s->session);
 
        ast_security_event_report(AST_SEC_EVT(&successful_auth));
@@ -2323,7 +2311,6 @@ static void report_auth_success(const struct mansession *s)
 
 static void report_req_not_allowed(const struct mansession *s, const char *action)
 {
-       struct ast_sockaddr addr_remote;
        char session_id[32];
        char request_type[64];
        struct ast_security_event_req_not_allowed req_not_allowed = {
@@ -2337,7 +2324,7 @@ static void report_req_not_allowed(const struct mansession *s, const char *actio
                        .transport = mansession_get_transport(s),
                },
                .common.remote_addr = {
-                       .addr      = &addr_remote,
+                       .addr      = &s->session->addr,
                        .transport = mansession_get_transport(s),
                },
                .common.session_id = session_id,
@@ -2345,8 +2332,6 @@ static void report_req_not_allowed(const struct mansession *s, const char *actio
                .request_type      = request_type,
        };
 
-       ast_sockaddr_from_sin(&addr_remote, &s->session->sin);
-
        snprintf(session_id, sizeof(session_id), "%p", s->session);
        snprintf(request_type, sizeof(request_type), "Action: %s", action);
 
@@ -2355,7 +2340,6 @@ static void report_req_not_allowed(const struct mansession *s, const char *actio
 
 static void report_req_bad_format(const struct mansession *s, const char *action)
 {
-       struct ast_sockaddr addr_remote;
        char session_id[32];
        char request_type[64];
        struct ast_security_event_req_bad_format req_bad_format = {
@@ -2369,7 +2353,7 @@ static void report_req_bad_format(const struct mansession *s, const char *action
                        .transport = mansession_get_transport(s),
                },
                .common.remote_addr = {
-                       .addr      = &addr_remote,
+                       .addr      = &s->session->addr,
                        .transport = mansession_get_transport(s),
                },
                .common.session_id = session_id,
@@ -2377,8 +2361,6 @@ static void report_req_bad_format(const struct mansession *s, const char *action
                .request_type      = request_type,
        };
 
-       ast_sockaddr_from_sin(&addr_remote, &s->session->sin);
-
        snprintf(session_id, sizeof(session_id), "%p", s->session);
        snprintf(request_type, sizeof(request_type), "Action: %s", action);
 
@@ -2388,7 +2370,6 @@ static void report_req_bad_format(const struct mansession *s, const char *action
 static void report_failed_challenge_response(const struct mansession *s,
                const char *response, const char *expected_response)
 {
-       struct ast_sockaddr addr_remote;
        char session_id[32];
        struct ast_security_event_chal_resp_failed chal_resp_failed = {
                .common.event_type = AST_SECURITY_EVENT_CHAL_RESP_FAILED,
@@ -2401,7 +2382,7 @@ static void report_failed_challenge_response(const struct mansession *s,
                        .transport = mansession_get_transport(s),
                },
                .common.remote_addr = {
-                       .addr      = &addr_remote,
+                       .addr      = &s->session->addr,
                        .transport = mansession_get_transport(s),
                },
                .common.session_id = session_id,
@@ -2411,8 +2392,6 @@ static void report_failed_challenge_response(const struct mansession *s,
                .expected_response = expected_response,
        };
 
-       ast_sockaddr_from_sin(&addr_remote, &s->session->sin);
-
        snprintf(session_id, sizeof(session_id), "%p", s->session);
 
        ast_security_event_report(AST_SEC_EVT(&chal_resp_failed));
@@ -2420,7 +2399,6 @@ static void report_failed_challenge_response(const struct mansession *s,
 
 static void report_session_limit(const struct mansession *s)
 {
-       struct ast_sockaddr addr_remote;
        char session_id[32];
        struct ast_security_event_session_limit session_limit = {
                .common.event_type = AST_SECURITY_EVENT_SESSION_LIMIT,
@@ -2433,14 +2411,12 @@ static void report_session_limit(const struct mansession *s)
                        .transport = mansession_get_transport(s),
                },
                .common.remote_addr = {
-                       .addr      = &addr_remote,
+                       .addr      = &s->session->addr,
                        .transport = mansession_get_transport(s),
                },
                .common.session_id = session_id,
        };
 
-       ast_sockaddr_from_sin(&addr_remote, &s->session->sin);
-
        snprintf(session_id, sizeof(session_id), "%p", s->session);
 
        ast_security_event_report(AST_SEC_EVT(&session_limit));
@@ -2461,7 +2437,6 @@ static int authenticate(struct mansession *s, const struct message *m)
        struct ast_manager_user *user = NULL;
        regex_t *regex_filter;
        struct ao2_iterator filter_iter;
-       struct ast_sockaddr addr;
 
        if (ast_strlen_zero(username)) {        /* missing username */
                return -1;
@@ -2470,14 +2445,12 @@ static int authenticate(struct mansession *s, const struct message *m)
        /* locate user in locked state */
        AST_RWLIST_WRLOCK(&users);
 
-       ast_sockaddr_from_sin(&addr, &s->session->sin);
-
        if (!(user = get_manager_by_name_locked(username))) {
                report_invalid_user(s, username);
-               ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username);
-       } else if (user->ha && !ast_apply_ha(user->ha, &addr)) {
+               ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_sockaddr_stringify_addr(&s->session->addr), username);
+       } else if (user->ha && !ast_apply_ha(user->ha, &s->session->addr)) {
                report_failed_acl(s, username);
-               ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username);
+               ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_sockaddr_stringify_addr(&s->session->addr), username);
        } else if (!strcasecmp(astman_get_header(m, "AuthType"), "MD5")) {
                const char *key = astman_get_header(m, "Key");
                if (!ast_strlen_zero(key) && !ast_strlen_zero(s->session->challenge) && user->secret) {
@@ -2511,7 +2484,7 @@ static int authenticate(struct mansession *s, const struct message *m)
        }
 
        if (error) {
-               ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", ast_inet_ntoa(s->session->sin.sin_addr), username);
+               ast_log(LOG_NOTICE, "%s failed to authenticate as '%s'\n", ast_sockaddr_stringify_addr(&s->session->addr), username);
                AST_RWLIST_UNLOCK(&users);
                return -1;
        }
@@ -3160,7 +3133,7 @@ static int action_login(struct mansession *s, const struct message *m)
        s->session->authenticated = 1;
        ast_atomic_fetchadd_int(&unauth_sessions, -1);
        if (manager_displayconnects(s->session)) {
-               ast_verb(2, "%sManager '%s' logged on from %s\n", (s->session->managerid ? "HTTP " : ""), s->session->username, ast_inet_ntoa(s->session->sin.sin_addr));
+               ast_verb(2, "%sManager '%s' logged on from %s\n", (s->session->managerid ? "HTTP " : ""), s->session->username, ast_sockaddr_stringify_addr(&s->session->addr));
        }
        astman_send_ack(s, m, "Authentication accepted");
        if ((s->session->send_events & EVENT_FLAG_SYSTEM)
@@ -3239,7 +3212,7 @@ static int action_hangup(struct mansession *s, const struct message *m)
                ast_verb(3, "%sManager '%s' from %s, hanging up channel: %s\n",
                        (s->session->managerid ? "HTTP " : ""),
                        s->session->username,
-                       ast_inet_ntoa(s->session->sin.sin_addr),
+                       ast_sockaddr_stringify_addr(&s->session->addr),
                        ast_channel_name(c));
 
                ast_channel_softhangup_withcause_locked(c, causecode);
@@ -3285,7 +3258,7 @@ static int action_hangup(struct mansession *s, const struct message *m)
                        ast_verb(3, "%sManager '%s' from %s, hanging up channel: %s\n",
                                (s->session->managerid ? "HTTP " : ""),
                                s->session->username,
-                               ast_inet_ntoa(s->session->sin.sin_addr),
+                               ast_sockaddr_stringify_addr(&s->session->addr),
                                ast_channel_name(c));
 
                        ast_channel_softhangup_withcause_locked(c, causecode);
@@ -5101,7 +5074,7 @@ static int get_input(struct mansession *s, char *output)
        }
        if (s->session->inlen >= maxlen) {
                /* no crlf found, and buffer full - sorry, too long for us */
-               ast_log(LOG_WARNING, "Dumping long line with no return from %s: %s\n", ast_inet_ntoa(s->session->sin.sin_addr), src);
+               ast_log(LOG_WARNING, "Dumping long line with no return from %s: %s\n", ast_sockaddr_stringify_addr(&s->session->addr), src);
                s->session->inlen = 0;
        }
        res = 0;
@@ -5196,7 +5169,7 @@ static int do_message(struct mansession *s)
 
                                if (now - s->session->authstart > authtimeout) {
                                        if (displayconnects) {
-                                               ast_verb(2, "Client from %s, failed to authenticate in %d seconds\n", ast_inet_ntoa(s->session->sin.sin_addr), authtimeout);
+                                               ast_verb(2, "Client from %s, failed to authenticate in %d seconds\n", ast_sockaddr_stringify_addr(&s->session->addr), authtimeout);
                                        }
                                        res = -1;
                                        break;
@@ -5257,7 +5230,7 @@ static void *session_do(void *data)
        };
        int flags;
        int res;
-       struct sockaddr_in ser_remote_address_tmp;
+       struct ast_sockaddr ser_remote_address_tmp;
        struct protoent *p;
 
        if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= authlimit) {
@@ -5266,8 +5239,8 @@ static void *session_do(void *data)
                goto done;
        }
 
-       ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp);
-       session = build_mansession(ser_remote_address_tmp);
+       ast_sockaddr_copy(&ser_remote_address_tmp, &ser->remote_address);
+       session = build_mansession(&ser_remote_address_tmp);
 
        if (session == NULL) {
                fclose(ser->f);
@@ -5305,7 +5278,7 @@ static void *session_do(void *data)
        /* these fields duplicate those in the 'ser' structure */
        session->fd = s.fd = ser->fd;
        session->f = s.f = ser->f;
-       session->sin = ser_remote_address_tmp;
+       ast_sockaddr_copy(&session->addr, &ser_remote_address_tmp);
        s.session = session;
 
        AST_LIST_HEAD_INIT_NOLOCK(&session->datastores);
@@ -5328,12 +5301,12 @@ static void *session_do(void *data)
        /* session is over, explain why and terminate */
        if (session->authenticated) {
                if (manager_displayconnects(session)) {
-                       ast_verb(2, "Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
+                       ast_verb(2, "Manager '%s' logged off from %s\n", session->username, ast_sockaddr_stringify_addr(&session->addr));
                }
        } else {
                ast_atomic_fetchadd_int(&unauth_sessions, -1);
                if (displayconnects) {
-                       ast_verb(2, "Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr));
+                       ast_verb(2, "Connect attempt from '%s' unable to authenticate\n", ast_sockaddr_stringify_addr(&session->addr));
                }
        }
 
@@ -5359,7 +5332,7 @@ static void purge_sessions(int n_max)
                if (session->sessiontimeout && (now > session->sessiontimeout) && !session->inuse) {
                        if (session->authenticated && manager_displayconnects(session)) {
                                ast_verb(2, "HTTP Manager '%s' timed out from %s\n",
-                                       session->username, ast_inet_ntoa(session->sin.sin_addr));
+                                       session->username, ast_sockaddr_stringify_addr(&session->addr));
                        }
                        ao2_unlock(session);
                        session_destroy(session);
@@ -6113,7 +6086,7 @@ static void process_output(struct mansession *s, struct ast_str **out, struct as
 static int generic_http_callback(struct ast_tcptls_session_instance *ser,
                                             enum ast_http_method method,
                                             enum output_format format,
-                                            struct sockaddr_in *remote_address, const char *uri,
+                                            const struct ast_sockaddr *remote_address, const char *uri,
                                             struct ast_variable *get_params,
                                             struct ast_variable *headers)
 {
@@ -6150,14 +6123,11 @@ static int generic_http_callback(struct ast_tcptls_session_instance *ser,
                /* Create new session.
                 * While it is not in the list we don't need any locking
                 */
-               if (!(session = build_mansession(*remote_address))) {
+               if (!(session = build_mansession(remote_address))) {
                        ast_http_error(ser, 500, "Server Error", "Internal Server Error (out of memory)\n");
                        return -1;
                }
                ao2_lock(session);
-               session->sin = *remote_address;
-               session->fd = -1;
-               session->waiting_thread = AST_PTHREADT_NULL;
                session->send_events = 0;
                session->inuse = 1;
                /*!\note There is approximately a 1 in 1.8E19 chance that the following
@@ -6215,11 +6185,11 @@ static int generic_http_callback(struct ast_tcptls_session_instance *ser,
        if (process_message(&s, &m)) {
                if (session->authenticated) {
                        if (manager_displayconnects(session)) {
-                               ast_verb(2, "HTTP Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
+                               ast_verb(2, "HTTP Manager '%s' logged off from %s\n", session->username, ast_sockaddr_stringify_addr(&session->addr));
                        }
                } else {
                        if (displayconnects) {
-                               ast_verb(2, "HTTP Connect attempt from '%s' unable to authenticate\n", ast_inet_ntoa(session->sin.sin_addr));
+                               ast_verb(2, "HTTP Connect attempt from '%s' unable to authenticate\n", ast_sockaddr_stringify_addr(&session->addr));
                        }
                }
                session->needdestroy = 1;
@@ -6328,7 +6298,7 @@ generic_callback_out:
 static int auth_http_callback(struct ast_tcptls_session_instance *ser,
                                             enum ast_http_method method,
                                             enum output_format format,
-                                            struct sockaddr_in *remote_address, const char *uri,
+                                            const struct ast_sockaddr *remote_address, const char *uri,
                                             struct ast_variable *get_params,
                                             struct ast_variable *headers)
 {
@@ -6354,7 +6324,6 @@ static int auth_http_callback(struct ast_tcptls_session_instance *ser,
        int u_writeperm;
        int u_writetimeout;
        int u_displayconnects;
-       struct ast_sockaddr addr;
 
        if (method != AST_HTTP_GET && method != AST_HTTP_HEAD && method != AST_HTTP_POST) {
                ast_http_error(ser, 501, "Not Implemented", "Attempt to use unimplemented / unsupported method");
@@ -6393,16 +6362,15 @@ static int auth_http_callback(struct ast_tcptls_session_instance *ser,
        user = get_manager_by_name_locked(d.username);
        if(!user) {
                AST_RWLIST_UNLOCK(&users);
-               ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_inet_ntoa(remote_address->sin_addr), d.username);
+               ast_log(LOG_NOTICE, "%s tried to authenticate with nonexistent user '%s'\n", ast_sockaddr_stringify_addr(&session->addr), d.username);
                nonce = 0;
                goto out_401;
        }
 
-       ast_sockaddr_from_sin(&addr, remote_address);
        /* --- We have User for this auth, now check ACL */
-       if (user->ha && !ast_apply_ha(user->ha, &addr)) {
+       if (user->ha && !ast_apply_ha(user->ha, remote_address)) {
                AST_RWLIST_UNLOCK(&users);
-               ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_inet_ntoa(remote_address->sin_addr), d.username);
+               ast_log(LOG_NOTICE, "%s failed to pass IP ACL as '%s'\n", ast_sockaddr_stringify_addr(&session->addr), d.username);
                ast_http_error(ser, 403, "Permission denied", "Permission denied\n");
                return -1;
        }
@@ -6452,7 +6420,7 @@ static int auth_http_callback(struct ast_tcptls_session_instance *ser,
                 * Create new session.
                 * While it is not in the list we don't need any locking
                 */
-               if (!(session = build_mansession(*remote_address))) {
+               if (!(session = build_mansession(remote_address))) {
                        ast_http_error(ser, 500, "Server Error", "Internal Server Error (out of memory)\n");
                        return -1;
                }
@@ -6468,7 +6436,7 @@ static int auth_http_callback(struct ast_tcptls_session_instance *ser,
                session->writetimeout = u_writetimeout;
 
                if (u_displayconnects) {
-                       ast_verb(2, "HTTP Manager '%s' logged in from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
+                       ast_verb(2, "HTTP Manager '%s' logged in from %s\n", session->username, ast_sockaddr_stringify_addr(&session->addr));
                }
                session->noncetime = session->sessionstart = time_now;
                session->authenticated = 1;
@@ -6550,7 +6518,7 @@ static int auth_http_callback(struct ast_tcptls_session_instance *ser,
 
        if (process_message(&s, &m)) {
                if (u_displayconnects) {
-                       ast_verb(2, "HTTP Manager '%s' logged off from %s\n", session->username, ast_inet_ntoa(session->sin.sin_addr));
+                       ast_verb(2, "HTTP Manager '%s' logged off from %s\n", session->username, ast_sockaddr_stringify_addr(&session->addr));
                }
 
                session->needdestroy = 1;
@@ -6641,33 +6609,33 @@ out_401:
 static int manager_http_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params,  struct ast_variable *headers)
 {
        int retval;
-       struct sockaddr_in ser_remote_address_tmp;
+       struct ast_sockaddr ser_remote_address_tmp;
 
-       ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp);
+       ast_sockaddr_copy(&ser_remote_address_tmp, &ser->remote_address);
        retval = generic_http_callback(ser, method, FORMAT_HTML, &ser_remote_address_tmp, uri, get_params, headers);
-       ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp);
+       ast_sockaddr_copy(&ser->remote_address, &ser_remote_address_tmp);
        return retval;
 }
 
 static int mxml_http_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
 {
        int retval;
-       struct sockaddr_in ser_remote_address_tmp;
+       struct ast_sockaddr ser_remote_address_tmp;
 
-       ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp);
+       ast_sockaddr_copy(&ser_remote_address_tmp, &ser->remote_address);
        retval = generic_http_callback(ser, method, FORMAT_XML, &ser_remote_address_tmp, uri, get_params, headers);
-       ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp);
+       ast_sockaddr_copy(&ser->remote_address, &ser_remote_address_tmp);
        return retval;
 }
 
 static int rawman_http_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
 {
        int retval;
-       struct sockaddr_in ser_remote_address_tmp;
+       struct ast_sockaddr ser_remote_address_tmp;
 
-       ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp);
+       ast_sockaddr_copy(&ser_remote_address_tmp, &ser->remote_address);
        retval = generic_http_callback(ser, method, FORMAT_RAW, &ser_remote_address_tmp, uri, get_params, headers);
-       ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp);
+       ast_sockaddr_copy(&ser->remote_address, &ser_remote_address_tmp);
        return retval;
 }
 
@@ -6700,33 +6668,33 @@ static struct ast_http_uri managerxmluri = {
 static int auth_manager_http_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params,  struct ast_variable *headers)
 {
        int retval;
-       struct sockaddr_in ser_remote_address_tmp;
+       struct ast_sockaddr ser_remote_address_tmp;
 
-       ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp);
+       ast_sockaddr_copy(&ser_remote_address_tmp, &ser->remote_address);
        retval = auth_http_callback(ser, method, FORMAT_HTML, &ser_remote_address_tmp, uri, get_params, headers);
-       ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp);
+       ast_sockaddr_copy(&ser->remote_address, &ser_remote_address_tmp);
        return retval;
 }
 
 static int auth_mxml_http_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
 {
        int retval;
-       struct sockaddr_in ser_remote_address_tmp;
+       struct ast_sockaddr ser_remote_address_tmp;
 
-       ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp);
+       ast_sockaddr_copy(&ser_remote_address_tmp, &ser->remote_address);
        retval = auth_http_callback(ser, method, FORMAT_XML, &ser_remote_address_tmp, uri, get_params, headers);
-       ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp);
+       ast_sockaddr_copy(&ser->remote_address, &ser_remote_address_tmp);
        return retval;
 }
 
 static int auth_rawman_http_callback(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_params, struct ast_variable *headers)
 {
        int retval;
-       struct sockaddr_in ser_remote_address_tmp;
+       struct ast_sockaddr ser_remote_address_tmp;
 
-       ast_sockaddr_to_sin(&ser->remote_address, &ser_remote_address_tmp);
+       ast_sockaddr_copy(&ser_remote_address_tmp, &ser->remote_address);
        retval = auth_http_callback(ser, method, FORMAT_RAW, &ser_remote_address_tmp, uri, get_params, headers);
-       ast_sockaddr_from_sin(&ser->remote_address, &ser_remote_address_tmp);
+       ast_sockaddr_copy(&ser->remote_address, &ser_remote_address_tmp);
        return retval;
 }
 
@@ -6804,7 +6772,7 @@ static char *handle_manager_show_settings(struct ast_cli_entry *e, int cmd, stru
        case CLI_GENERATE:
                return NULL;
        }
-#define FORMAT "  %-25.25s  %-15.15s\n"
+#define FORMAT "  %-25.25s  %-15.55s\n"
 #define FORMAT2 "  %-25.25s  %-15d\n"
        if (a->argc != 3) {
                return CLI_SHOWUSAGE;
@@ -6892,8 +6860,8 @@ static int __init_manager(int reload)
        struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
        char a1[256];
        char a1_hash[256];
-       struct sockaddr_in ami_desc_local_address_tmp = { 0, };
-       struct sockaddr_in amis_desc_local_address_tmp = { 0, };
+       struct ast_sockaddr ami_desc_local_address_tmp;
+       struct ast_sockaddr amis_desc_local_address_tmp;
        int tls_was_enabled = 0;
 
        manager_enabled = 0;
@@ -6962,10 +6930,8 @@ static int __init_manager(int reload)
        ast_sockaddr_setnull(&ami_desc.local_address);
        ast_sockaddr_setnull(&amis_desc.local_address);
 
-       ami_desc_local_address_tmp.sin_family = AF_INET;
-       amis_desc_local_address_tmp.sin_family = AF_INET;
-
-       ami_desc_local_address_tmp.sin_port = htons(DEFAULT_MANAGER_PORT);
+       ast_sockaddr_parse(&ami_desc_local_address_tmp, "[::]", 0);
+       ast_sockaddr_set_port(&ami_desc_local_address_tmp, DEFAULT_MANAGER_PORT);
 
        tls_was_enabled = (reload && ami_tls_cfg.enabled);
 
@@ -6999,13 +6965,26 @@ static int __init_manager(int reload)
                } else if (!strcasecmp(var->name, "webenabled")) {
                        webmanager_enabled = ast_true(val);
                } else if (!strcasecmp(var->name, "port")) {
-                       ami_desc_local_address_tmp.sin_port = htons(atoi(val));
+                       int bindport;
+                       if (ast_parse_arg(val, PARSE_UINT32|PARSE_IN_RANGE, &bindport, 1024, 65535)) {
+                               ast_log(LOG_WARNING, "Invalid port number '%s'\n", val);
+                       }
+                       ast_sockaddr_set_port(&ami_desc_local_address_tmp, bindport);
                } else if (!strcasecmp(var->name, "bindaddr")) {
-                       if (!inet_aton(val, &ami_desc_local_address_tmp.sin_addr)) {
-                               ast_log(LOG_WARNING, "Invalid address '%s' specified, using 0.0.0.0\n", val);
-                               memset(&ami_desc_local_address_tmp.sin_addr, 0,
-                                      sizeof(ami_desc_local_address_tmp.sin_addr));
+                       /* remember port if it has already been set */
+                       int setport = ast_sockaddr_port(&ami_desc_local_address_tmp);
+
+                       if (ast_parse_arg(val, PARSE_ADDR|PARSE_PORT_IGNORE, NULL)) {
+                               ast_log(LOG_WARNING, "Invalid address '%s' specified, default '%s' will be used\n", val,
+                                               ast_sockaddr_stringify_addr(&ami_desc_local_address_tmp));
+                       } else {
+                               ast_sockaddr_parse(&ami_desc_local_address_tmp, val, PARSE_PORT_IGNORE);
                        }
+
+                       if (setport) {
+                               ast_sockaddr_set_port(&ami_desc_local_address_tmp, setport);
+                       }
+
                } else if (!strcasecmp(var->name, "brokeneventsaction")) {
                        broken_events_action = ast_true(val);
                } else if (!strcasecmp(var->name, "allowmultiplelogin")) {
@@ -7042,21 +7021,25 @@ static int __init_manager(int reload)
                }
        }
 
-       ast_sockaddr_to_sin(&amis_desc.local_address, &amis_desc_local_address_tmp);
+       ast_sockaddr_copy(&amis_desc_local_address_tmp, &amis_desc.local_address);
 
        /* if the amis address has not been set, default is the same as non secure ami */
-       if (!amis_desc_local_address_tmp.sin_addr.s_addr) {
-               amis_desc_local_address_tmp.sin_addr =
-                   ami_desc_local_address_tmp.sin_addr;
+       if (ast_sockaddr_isnull(&amis_desc_local_address_tmp)) {
+               ast_sockaddr_copy(&amis_desc_local_address_tmp, &ami_desc_local_address_tmp);
        }
 
-       if (!amis_desc_local_address_tmp.sin_port) {
-               amis_desc_local_address_tmp.sin_port = htons(DEFAULT_MANAGER_TLS_PORT);
+       /* if the amis address was not set, it will have non-secure ami port set; if
+          amis address was set, we need to check that a port was set or not, if not
+          use the default tls port */
+       if (ast_sockaddr_port(&amis_desc_local_address_tmp) == 0 ||
+                       (ast_sockaddr_port(&ami_desc_local_address_tmp) == ast_sockaddr_port(&amis_desc_local_address_tmp))) {
+
+               ast_sockaddr_set_port(&amis_desc_local_address_tmp, DEFAULT_MANAGER_TLS_PORT);
        }
 
        if (manager_enabled) {
-               ast_sockaddr_from_sin(&ami_desc.local_address, &ami_desc_local_address_tmp);
-               ast_sockaddr_from_sin(&amis_desc.local_address, &amis_desc_local_address_tmp);
+               ast_sockaddr_copy(&ami_desc.local_address, &ami_desc_local_address_tmp);
+               ast_sockaddr_copy(&amis_desc.local_address, &amis_desc_local_address_tmp);
        }
 
        AST_RWLIST_WRLOCK(&users);