]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
thread safety: Don't use getprotobyname()
authorSean Bright <sean.bright@gmail.com>
Sat, 18 Mar 2017 17:30:32 +0000 (13:30 -0400)
committerSean Bright <sean.bright@gmail.com>
Mon, 20 Mar 2017 12:51:47 +0000 (08:51 -0400)
POSIX does not require getprotobyname() to be thread safe and some
implementations use static memory which causes issues when multiple
threads are used.

Further, our usage of it today is just to ultimately get IPPROTO_TCP
for calls to setsockopt(). So instead we just use IPPROTO_TCP directly.

Change-Id: I2e14e58674808f7ce99b2f5e900d0f90d0d8da48

channels/chan_skinny.c
include/asterisk/network.h
main/http.c
main/manager.c

index 9cde775405ccd9184a75a3d51301366e0bd80a33..9c84eec30fd96ef89ae7590dbaca5fe8ae595aa7 100644 (file)
@@ -7642,7 +7642,6 @@ static void *accept_thread(void *ignore)
        struct sockaddr_in sin;
        socklen_t sinlen;
        struct skinnysession *s;
-       struct protoent *p;
        int arg = 1;
 
        for (;;) {
@@ -7659,12 +7658,10 @@ static void *accept_thread(void *ignore)
                        continue;
                }
 
-               p = getprotobyname("tcp");
-               if(p) {
-                       if( setsockopt(as, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
-                               ast_log(LOG_WARNING, "Failed to set Skinny tcp connection to TCP_NODELAY mode: %s\n", strerror(errno));
-                       }
+               if (setsockopt(as, IPPROTO_TCP, TCP_NODELAY, (char *) &arg, sizeof(arg)) < 0) {
+                       ast_log(LOG_WARNING, "Failed to set TCP_NODELAY on Skinny TCP connection: %s\n", strerror(errno));
                }
+
                if (!(s = ast_calloc(1, sizeof(struct skinnysession)))) {
                        close(as);
                        ast_atomic_fetchadd_int(&unauth_sessions, -1);
index 3371e58952f7e60978234d8f19cbbd2143ebfd04..5216f4c61a2bf124cf51f24d72fa99a08a8019c1 100644 (file)
@@ -86,6 +86,11 @@ const char *ast_inet_ntoa(struct in_addr ia);
 #endif
 #define inet_ntoa __dont__use__inet_ntoa__use__ast_inet_ntoa__instead__
 
+#ifdef getprotobyname
+#undef getprotobyname
+#endif
+#define getprotobyname __getprotobyname_is_not_threadsafe__do_not_use__
+
 /*! \brief Compares the source address and port of two sockaddr_in */
 static force_inline int inaddrcmp(const struct sockaddr_in *sin1, const struct sockaddr_in *sin2)
 {
index 155b04b780cce78fae151b71e87cea980f914872..80c7b3cb40201db61083d216b66d1841502cd511 100644 (file)
@@ -1915,8 +1915,7 @@ static int httpd_process_request(struct ast_tcptls_session_instance *ser)
 static void *httpd_helper_thread(void *data)
 {
        struct ast_tcptls_session_instance *ser = data;
-       struct protoent *p;
-       int flags;
+       int flags = 1;
        int timeout;
 
        if (!ser || !ser->f) {
@@ -1936,17 +1935,8 @@ static void *httpd_helper_thread(void *data)
         * This is necessary to prevent delays (caused by buffering) as we
         * write to the socket in bits and pieces.
         */
-       p = getprotobyname("tcp");
-       if (p) {
-               int arg = 1;
-
-               if (setsockopt(ser->fd, p->p_proto, TCP_NODELAY, (char *) &arg, sizeof(arg) ) < 0) {
-                       ast_log(LOG_WARNING, "Failed to set TCP_NODELAY on HTTP connection: %s\n", strerror(errno));
-                       ast_log(LOG_WARNING, "Some HTTP requests may be slow to respond.\n");
-               }
-       } else {
-               ast_log(LOG_WARNING, "Failed to set TCP_NODELAY on HTTP connection, getprotobyname(\"tcp\") failed\n");
-               ast_log(LOG_WARNING, "Some HTTP requests may be slow to respond.\n");
+       if (setsockopt(ser->fd, IPPROTO_TCP, TCP_NODELAY, (char *) &flags, sizeof(flags)) < 0) {
+               ast_log(LOG_WARNING, "Failed to set TCP_NODELAY on HTTP connection: %s\n", strerror(errno));
        }
 
        /* make sure socket is non-blocking */
index b8dbb1a042598094a6e947153138e9cc027c1076..0f7adf0c8ef3e2f45a0fe433c88643f9601379ee 100644 (file)
@@ -6591,10 +6591,9 @@ static void *session_do(void *data)
        struct mansession s = {
                .tcptls_session = data,
        };
-       int flags;
+       int flags = 1;
        int res;
        struct ast_sockaddr ser_remote_address_tmp;
-       struct protoent *p;
 
        if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= authlimit) {
                fclose(ser->f);
@@ -6614,14 +6613,8 @@ static void *session_do(void *data)
        /* here we set TCP_NODELAY on the socket to disable Nagle's algorithm.
         * This is necessary to prevent delays (caused by buffering) as we
         * write to the socket in bits and pieces. */
-       p = getprotobyname("tcp");
-       if (p) {
-               int arg = 1;
-               if( setsockopt(ser->fd, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
-                       ast_log(LOG_WARNING, "Failed to set manager tcp connection to TCP_NODELAY mode: %s\nSome manager actions may be slow to respond.\n", strerror(errno));
-               }
-       } else {
-               ast_log(LOG_WARNING, "Failed to set manager tcp connection to TCP_NODELAY, getprotobyname(\"tcp\") failed\nSome manager actions may be slow to respond.\n");
+       if (setsockopt(ser->fd, IPPROTO_TCP, TCP_NODELAY, (char *) &flags, sizeof(flags)) < 0) {
+               ast_log(LOG_WARNING, "Failed to set TCP_NODELAY on manager connection: %s\n", strerror(errno));
        }
 
        /* make sure socket is non-blocking */