~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to srclib/apr/network_io/win32/sockopt.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
 
2
 * applicable.
 
3
 *
 
4
 * Licensed under the Apache License, Version 2.0 (the "License");
 
5
 * you may not use this file except in compliance with the License.
 
6
 * You may obtain a copy of the License at
 
7
 *
 
8
 *     http://www.apache.org/licenses/LICENSE-2.0
 
9
 *
 
10
 * Unless required by applicable law or agreed to in writing, software
 
11
 * distributed under the License is distributed on an "AS IS" BASIS,
 
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
13
 * See the License for the specific language governing permissions and
 
14
 * limitations under the License.
 
15
 */
 
16
 
 
17
#include "apr_arch_networkio.h"
 
18
#include "apr_network_io.h"
 
19
#include "apr_general.h"
 
20
#include "apr_strings.h"
 
21
#include <string.h>
 
22
 
 
23
apr_status_t soblock(SOCKET sd)
 
24
{
 
25
    u_long zero = 0;
 
26
 
 
27
    if (ioctlsocket(sd, FIONBIO, &zero) == SOCKET_ERROR) {
 
28
        return apr_get_netos_error();
 
29
    }
 
30
    return APR_SUCCESS;
 
31
}
 
32
 
 
33
apr_status_t sononblock(SOCKET sd)
 
34
{
 
35
    u_long one = 1;
 
36
 
 
37
    if (ioctlsocket(sd, FIONBIO, &one) == SOCKET_ERROR) {
 
38
        return apr_get_netos_error();
 
39
    }
 
40
    return APR_SUCCESS;
 
41
}
 
42
 
 
43
 
 
44
APR_DECLARE(apr_status_t) apr_socket_timeout_set(apr_socket_t *sock, apr_interval_time_t t)
 
45
{
 
46
    apr_status_t stat;
 
47
 
 
48
    if (t == 0) {
 
49
        /* Set the socket non-blocking if it was previously blocking */
 
50
        if (sock->timeout != 0) {
 
51
            if ((stat = sononblock(sock->socketdes)) != APR_SUCCESS)
 
52
                return stat;
 
53
        }
 
54
    }
 
55
    else if (t > 0) {
 
56
        /* Set the socket to blocking if it was previously non-blocking */
 
57
        if (sock->timeout == 0) {
 
58
            if ((stat = soblock(sock->socketdes)) != APR_SUCCESS)
 
59
                return stat;
 
60
        }
 
61
        /* Reset socket timeouts if the new timeout differs from the old timeout */
 
62
        if (sock->timeout != t) 
 
63
        {
 
64
            /* Win32 timeouts are in msec, represented as int */
 
65
            sock->timeout_ms = (int)apr_time_as_msec(t);
 
66
            setsockopt(sock->socketdes, SOL_SOCKET, SO_RCVTIMEO, 
 
67
                       (char *) &sock->timeout_ms, 
 
68
                       sizeof(sock->timeout_ms));
 
69
            setsockopt(sock->socketdes, SOL_SOCKET, SO_SNDTIMEO, 
 
70
                       (char *) &sock->timeout_ms, 
 
71
                       sizeof(sock->timeout_ms));
 
72
        }
 
73
    }
 
74
    else if (t < 0) {
 
75
        int zero = 0;
 
76
        /* Set the socket to blocking with infinite timeouts */
 
77
        if ((stat = soblock(sock->socketdes)) != APR_SUCCESS)
 
78
            return stat;
 
79
        setsockopt(sock->socketdes, SOL_SOCKET, SO_RCVTIMEO, 
 
80
                   (char *) &zero, sizeof(zero));
 
81
        setsockopt(sock->socketdes, SOL_SOCKET, SO_SNDTIMEO, 
 
82
                   (char *) &zero, sizeof(zero));
 
83
    }
 
84
    sock->timeout = t;
 
85
    return APR_SUCCESS;
 
86
}
 
87
 
 
88
 
 
89
APR_DECLARE(apr_status_t) apr_socket_opt_set(apr_socket_t *sock,
 
90
                                             apr_int32_t opt, apr_int32_t on)
 
91
{
 
92
    int one;
 
93
    apr_status_t stat;
 
94
 
 
95
    one = on ? 1 : 0;
 
96
 
 
97
    switch (opt) {
 
98
    case APR_SO_KEEPALIVE:
 
99
        if (on != apr_is_option_set(sock, APR_SO_KEEPALIVE)) {
 
100
            if (setsockopt(sock->socketdes, SOL_SOCKET, SO_KEEPALIVE, 
 
101
                           (void *)&one, sizeof(int)) == -1) {
 
102
                return apr_get_netos_error();
 
103
            }
 
104
            apr_set_option(sock, APR_SO_KEEPALIVE, on);
 
105
        }
 
106
        break;
 
107
    case APR_SO_DEBUG:
 
108
        if (on != apr_is_option_set(sock, APR_SO_DEBUG)) {
 
109
            if (setsockopt(sock->socketdes, SOL_SOCKET, SO_DEBUG, 
 
110
                           (void *)&one, sizeof(int)) == -1) {
 
111
                return apr_get_netos_error();
 
112
            }
 
113
            apr_set_option(sock, APR_SO_DEBUG, on);
 
114
        }
 
115
        break;
 
116
    case APR_SO_SNDBUF:
 
117
        if (setsockopt(sock->socketdes, SOL_SOCKET, SO_SNDBUF,
 
118
                       (void *)&on, sizeof(int)) == -1) {
 
119
            return apr_get_netos_error();
 
120
        }
 
121
        break;
 
122
    case APR_SO_RCVBUF:
 
123
        if (setsockopt(sock->socketdes, SOL_SOCKET, SO_RCVBUF,
 
124
                       (void *)&on, sizeof(int)) == -1) {
 
125
            return apr_get_netos_error();
 
126
        }
 
127
        break;
 
128
    case APR_SO_REUSEADDR:
 
129
        if (on != apr_is_option_set(sock, APR_SO_REUSEADDR)) {
 
130
            if (setsockopt(sock->socketdes, SOL_SOCKET, SO_REUSEADDR, 
 
131
                           (void *)&one, sizeof(int)) == -1) {
 
132
                return apr_get_netos_error();
 
133
            }
 
134
            apr_set_option(sock, APR_SO_REUSEADDR, on);
 
135
        }
 
136
        break;
 
137
    case APR_SO_NONBLOCK:
 
138
        if (apr_is_option_set(sock, APR_SO_NONBLOCK) != on) {
 
139
            if (on) {
 
140
                if ((stat = sononblock(sock->socketdes)) != APR_SUCCESS) 
 
141
                    return stat;
 
142
            }
 
143
            else {
 
144
                if ((stat = soblock(sock->socketdes)) != APR_SUCCESS)
 
145
                    return stat;
 
146
            }
 
147
            apr_set_option(sock, APR_SO_NONBLOCK, on);
 
148
        }
 
149
        break;
 
150
    case APR_SO_LINGER:
 
151
    {
 
152
        if (apr_is_option_set(sock, APR_SO_LINGER) != on) {
 
153
            struct linger li;
 
154
            li.l_onoff = on;
 
155
            li.l_linger = APR_MAX_SECS_TO_LINGER;
 
156
            if (setsockopt(sock->socketdes, SOL_SOCKET, SO_LINGER, 
 
157
                           (char *) &li, sizeof(struct linger)) == -1) {
 
158
                return apr_get_netos_error();
 
159
            }
 
160
            apr_set_option(sock, APR_SO_LINGER, on);
 
161
        }
 
162
        break;
 
163
    }
 
164
    case APR_TCP_DEFER_ACCEPT:
 
165
#if defined(TCP_DEFER_ACCEPT)
 
166
        if (apr_is_option_set(sock, APR_TCP_DEFER_ACCEPT) != on) {
 
167
            int optlevel = IPPROTO_TCP;
 
168
            int optname = TCP_DEFER_ACCEPT;
 
169
 
 
170
            if (setsockopt(sock->socketdes, optlevel, optname, 
 
171
                           (void *)&on, sizeof(int)) == -1) {
 
172
                return errno;
 
173
            }
 
174
            apr_set_option(sock, APR_TCP_DEFER_ACCEPT, on);
 
175
        }
 
176
#else
 
177
        return APR_ENOTIMPL;
 
178
#endif
 
179
    case APR_TCP_NODELAY:
 
180
        if (apr_is_option_set(sock, APR_TCP_NODELAY) != on) {
 
181
            int optlevel = IPPROTO_TCP;
 
182
            int optname = TCP_NODELAY;
 
183
 
 
184
#if APR_HAVE_SCTP
 
185
            if (sock->protocol == IPPROTO_SCTP) {
 
186
                optlevel = IPPROTO_SCTP;
 
187
                optname = SCTP_NODELAY;
 
188
            }
 
189
#endif
 
190
            if (setsockopt(sock->socketdes, optlevel, optname,
 
191
                           (void *)&on, sizeof(int)) == -1) {
 
192
                return apr_get_netos_error();
 
193
            }
 
194
            apr_set_option(sock, APR_TCP_NODELAY, on);
 
195
        }
 
196
        break;
 
197
    case APR_IPV6_V6ONLY:
 
198
#if APR_HAVE_IPV6 && defined(IPV6_V6ONLY)
 
199
        /* we don't know the initial setting of this option,
 
200
         * so don't check sock->options since that optimization
 
201
         * won't work
 
202
         */
 
203
        if (setsockopt(sock->socketdes, IPPROTO_IPV6, IPV6_V6ONLY,
 
204
                       (void *)&on, sizeof(int)) == -1) {
 
205
            return apr_get_netos_error();
 
206
        }
 
207
        apr_set_option(sock, APR_IPV6_V6ONLY, on);
 
208
#else
 
209
        return APR_ENOTIMPL;
 
210
#endif
 
211
        break;
 
212
    default:
 
213
        return APR_EINVAL;
 
214
        break;
 
215
    }
 
216
    return APR_SUCCESS;
 
217
}
 
218
 
 
219
 
 
220
APR_DECLARE(apr_status_t) apr_socket_timeout_get(apr_socket_t *sock, apr_interval_time_t *t)
 
221
{
 
222
    *t = sock->timeout;
 
223
    return APR_SUCCESS;
 
224
}
 
225
 
 
226
 
 
227
APR_DECLARE(apr_status_t) apr_socket_opt_get(apr_socket_t *sock,
 
228
                                             apr_int32_t opt, apr_int32_t *on)
 
229
{
 
230
    switch (opt) {
 
231
    case APR_SO_DISCONNECTED:
 
232
        *on = sock->disconnected;
 
233
        break;
 
234
    case APR_SO_KEEPALIVE:
 
235
    case APR_SO_DEBUG:
 
236
    case APR_SO_REUSEADDR:
 
237
    case APR_SO_NONBLOCK:
 
238
    case APR_SO_LINGER:
 
239
    default:
 
240
        *on = apr_is_option_set(sock, opt);
 
241
        break;
 
242
    }
 
243
    return APR_SUCCESS;
 
244
}
 
245
 
 
246
 
 
247
APR_DECLARE(apr_status_t) apr_socket_atmark(apr_socket_t *sock, int *atmark)
 
248
{
 
249
    u_long oobmark;
 
250
 
 
251
    if (ioctlsocket(sock->socketdes, SIOCATMARK, (void*) &oobmark) < 0)
 
252
        return apr_get_netos_error();
 
253
 
 
254
    *atmark = (oobmark != 0);
 
255
 
 
256
    return APR_SUCCESS;
 
257
}
 
258
 
 
259
 
 
260
APR_DECLARE(apr_status_t) apr_gethostname(char *buf, int len,
 
261
                                          apr_pool_t *cont)
 
262
{
 
263
    if (gethostname(buf, len) == -1) {
 
264
        buf[0] = '\0';
 
265
        return apr_get_netos_error();
 
266
    }
 
267
    else if (!memchr(buf, '\0', len)) { /* buffer too small */
 
268
        buf[0] = '\0';
 
269
        return APR_ENAMETOOLONG;
 
270
    }
 
271
    return APR_SUCCESS;
 
272
}
 
273