~ubuntu-branches/ubuntu/saucy/clamav/saucy-backports

« back to all changes in this revision

Viewing changes to clamd/tcpserver.c

  • Committer: Package Import Robot
  • Author(s): Scott Kitterman
  • Date: 2014-07-15 01:08:10 UTC
  • mfrom: (0.35.47 sid)
  • Revision ID: package-import@ubuntu.com-20140715010810-ru66ek4fun2iseba
Tags: 0.98.4+dfsg-2~ubuntu13.10.1
No-change backport to saucy (LP: #1341962)

Show diffs side-by-side

added added

removed removed

Lines of Context:
46
46
#include "server.h"
47
47
#include "tcpserver.h"
48
48
 
49
 
int tcpserver(const struct optstruct *opts)
 
49
int tcpserver(int **lsockets, unsigned int *nlsockets, char *ipaddr, const struct optstruct *opts)
50
50
{
51
 
    struct sockaddr_in server;
 
51
    struct addrinfo hints, *info, *p;
 
52
    int *sockets;
52
53
    int sockfd, backlog;
53
 
    char *estr;
54
 
    int true = 1;
55
 
 
56
 
    if (cfg_tcpsock(opts, &server, INADDR_ANY) == -1) {
57
 
        logg("!TCP: Couldn't configure socket, check your configuration\n");
58
 
        return -1;
59
 
    }
60
 
 
61
 
    if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
62
 
        estr = strerror(errno);
63
 
        logg("!TCP: socket() error: %s\n", estr);
64
 
        return -1;
65
 
    }
66
 
 
67
 
    if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *) &true, sizeof(true)) == -1) {
68
 
        logg("!TCP: setsocktopt(SO_REUSEADDR) error: %s\n", strerror(errno));
69
 
    }
70
 
 
71
 
    if(bind(sockfd, (struct sockaddr *) &server, (socklen_t)sizeof(struct sockaddr_in)) == -1) {
72
 
        estr = strerror(errno);
73
 
        logg("!TCP: bind() error: %s\n", estr);
74
 
        closesocket(sockfd);
75
 
        return -1;
76
 
    } else {
77
 
        const struct optstruct *taddr = optget(opts, "TCPAddr");
78
 
        if(taddr->enabled)
79
 
            logg("#TCP: Bound to address %s on port %u\n", taddr->strarg, (unsigned int) optget(opts, "TCPSocket")->numarg);
80
 
        else
81
 
            logg("#TCP: Bound to port %u\n", (unsigned int) optget(opts, "TCPSocket")->numarg);
82
 
    }
83
 
 
84
 
    backlog = optget(opts, "MaxConnectionQueueLength")->numarg;
85
 
    logg("#TCP: Setting connection queue length to %d\n", backlog);
86
 
 
87
 
    if(listen(sockfd, backlog) == -1) {
88
 
        estr = strerror(errno);
89
 
        logg("!TCP: listen() error: %s\n", estr);
90
 
        closesocket(sockfd);
91
 
        return -1;
92
 
    }
93
 
 
94
 
    return sockfd;
 
54
    int *t;
 
55
    char *estr, port[10];
 
56
    int yes = 1;
 
57
    int res;
 
58
    unsigned int i=0;
 
59
 
 
60
    sockets = *lsockets;
 
61
 
 
62
    snprintf(port, sizeof(port), "%lld", optget(opts, "TCPSocket")->numarg);
 
63
 
 
64
    memset(&hints, 0x00, sizeof(struct addrinfo));
 
65
    hints.ai_family = AF_UNSPEC;
 
66
    hints.ai_socktype = SOCK_STREAM;
 
67
    hints.ai_flags = AI_PASSIVE;
 
68
 
 
69
#if C_LINUX
 
70
    if (!(ipaddr)) {
 
71
        /*
 
72
         * By default, getaddrinfo() will return 0.0.0.0 if NULL is passed in as the first parameter.
 
73
         * Binding to 0.0.0.0 will prevent us from also binding IPv6 ::0 (errno = EADDRINUSE). However,
 
74
         * if we bind to ::0 (or shorthand, ::), then Linux will bind to both IPv4 and IPv6.
 
75
         */
 
76
        ipaddr = "::";
 
77
    }
 
78
#endif
 
79
 
 
80
    if ((res = getaddrinfo(ipaddr, port, &hints, &info))) {
 
81
        logg("!TCP: getaddrinfo: %s\n", gai_strerror(res));
 
82
        return -1;
 
83
    }
 
84
 
 
85
    for (p = info; p != NULL; p = p->ai_next, i++) {
 
86
        t = realloc(sockets, sizeof(int) * (*nlsockets + 1));
 
87
        if (!(t)) {
 
88
            for (i=0; i < *nlsockets; i++)
 
89
                close(sockets[i]);
 
90
 
 
91
            return -1;
 
92
        }
 
93
        sockets = t;
 
94
 
 
95
        if ((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) {
 
96
            estr = strerror(errno);
 
97
            logg("!TCP: socket() error: %s\n", estr);
 
98
            continue;
 
99
        }
 
100
 
 
101
        if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *) &yes, sizeof(yes)) == -1) {
 
102
            logg("!TCP: setsocktopt(SO_REUSEADDR) error: %s\n", strerror(errno));
 
103
        }
 
104
 
 
105
        if(bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
 
106
            estr = strerror(errno);
 
107
            if (ipaddr || i == 0)
 
108
                logg("!TCP: bind() error when trying to listen on [%s]:%s: %s\n", ipaddr, port, estr);
 
109
            closesocket(sockfd);
 
110
 
 
111
            continue;
 
112
        } else {
 
113
            if((ipaddr))
 
114
                logg("#TCP: Bound to address %s on port %u\n", ipaddr, (unsigned int) optget(opts, "TCPSocket")->numarg);
 
115
            else
 
116
                logg("#TCP: Bound to port %u\n", (unsigned int) optget(opts, "TCPSocket")->numarg);
 
117
        }
 
118
 
 
119
        backlog = optget(opts, "MaxConnectionQueueLength")->numarg;
 
120
        logg("#TCP: Setting connection queue length to %d\n", backlog);
 
121
 
 
122
        if(listen(sockfd, backlog) == -1) {
 
123
            estr = strerror(errno);
 
124
            logg("!TCP: listen() error: %s\n", estr);
 
125
            closesocket(sockfd);
 
126
 
 
127
            continue;
 
128
        }
 
129
 
 
130
        sockets[*nlsockets] = sockfd;
 
131
        (*nlsockets)++;
 
132
    }
 
133
 
 
134
    freeaddrinfo(info);
 
135
    *lsockets = sockets;
 
136
 
 
137
    return 0;
95
138
}