~ubuntu-branches/ubuntu/trusty/dante/trusty-proposed

« back to all changes in this revision

Viewing changes to sockd/config.c

  • Committer: Bazaar Package Importer
  • Author(s): Adrian Bridgett
  • Date: 2002-04-07 12:45:55 UTC
  • Revision ID: james.westby@ubuntu.com-20020407124555-qke8rt2tdor0naz2
Tags: upstream-1.1.11.12p1
ImportĀ upstreamĀ versionĀ 1.1.11.12p1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 1997, 1998, 1999, 2000, 2001
 
3
 *      Inferno Nettverk A/S, Norway.  All rights reserved.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions
 
7
 * are met:
 
8
 * 1. The above copyright notice, this list of conditions and the following
 
9
 *    disclaimer must appear in all copies of the software, derivative works
 
10
 *    or modified versions, and any portions thereof, aswell as in all
 
11
 *    supporting documentation.
 
12
 * 2. All advertising materials mentioning features or use of this software
 
13
 *    must display the following acknowledgement:
 
14
 *      This product includes software developed by
 
15
 *      Inferno Nettverk A/S, Norway.
 
16
 * 3. The name of the author may not be used to endorse or promote products
 
17
 *    derived from this software without specific prior written permission.
 
18
 *
 
19
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 
20
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
21
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 
22
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 
23
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 
24
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
25
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
26
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
27
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 
28
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
29
 *
 
30
 * Inferno Nettverk A/S requests users of this software to return to
 
31
 *
 
32
 *  Software Distribution Coordinator  or  sdc@inet.no
 
33
 *  Inferno Nettverk A/S
 
34
 *  Oslo Research Park
 
35
 *  Gaustadallļæ½en 21
 
36
 *  NO-0349 Oslo
 
37
 *  Norway
 
38
 *
 
39
 * any improvements or extensions that they make and grant Inferno Nettverk A/S
 
40
 * the rights to redistribute these changes.
 
41
 *
 
42
 */
 
43
 
 
44
#include "common.h"
 
45
 
 
46
static const char rcsid[] =
 
47
"$Id: config.c,v 1.150 2001/12/12 14:42:10 karls Exp $";
 
48
 
 
49
void
 
50
genericinit(void)
 
51
{
 
52
        const char *function = "genericinit()";
 
53
        size_t i;
 
54
 
 
55
        if (!sockscf.state.init) {
 
56
#if !HAVE_SETPROCTITLE
 
57
                /* create a backup to avoid setproctitle replacement overwriting it. */
 
58
                if ((__progname = strdup(__progname)) == NULL)
 
59
                        serrx(EXIT_FAILURE, "%s: %s", function, NOMEM);
 
60
#endif /* !HAVE_SETPROCTITLE */
 
61
        }
 
62
 
 
63
        if (readconfig(sockscf.option.configfile) != 0)
 
64
#if SOCKS_SERVER
 
65
                exit(EXIT_FAILURE);
 
66
#else
 
67
                return;
 
68
#endif
 
69
 
 
70
        newprocinit();
 
71
 
 
72
        switch (sockscf.resolveprotocol) {
 
73
                case RESOLVEPROTOCOL_TCP:
 
74
#if !HAVE_NO_RESOLVESTUFF
 
75
                        _res.options |= RES_USEVC;
 
76
#else /* HAVE_NO_RESOLVESTUFF */
 
77
                        SERRX(sockscf.resolveprotocol);
 
78
#endif  /* HAVE_NO_RESOLVESTUFF */
 
79
                        break;
 
80
 
 
81
                case RESOLVEPROTOCOL_UDP:
 
82
                case RESOLVEPROTOCOL_FAKE:
 
83
                        break;
 
84
 
 
85
                default:
 
86
                        SERRX(sockscf.resolveprotocol);
 
87
        }
 
88
 
 
89
        if (!sockscf.state.init)
 
90
                if (sockscf.option.lbuf)
 
91
                        for (i = 0; i < sockscf.log.fpc; ++i)
 
92
                                if (setvbuf(sockscf.log.fpv[i], NULL, _IOLBF, 0) != 0)
 
93
                                        swarn("%s: setvbuf(_IOLBF)", function);
 
94
 
 
95
        sockscf.state.init = 1;
 
96
 
 
97
#if !HAVE_NO_RESOLVESTUFF
 
98
        res_init();
 
99
#endif /* !HAVE_NO_RESOLVSTUFF */
 
100
}
 
101
 
 
102
#if SOCKS_CLIENT
 
103
 
 
104
struct route_t *
 
105
addroute(newroute)
 
106
        const struct route_t *newroute;
 
107
{
 
108
        const char *function = "addroute()";
 
109
        static const struct serverstate_t state;
 
110
        struct route_t *route;
 
111
 
 
112
        if ((route = (struct route_t *)malloc(sizeof(*route))) == NULL)
 
113
                serrx(EXIT_FAILURE, "%s: %s", function, NOMEM);
 
114
        *route = *newroute;
 
115
 
 
116
        /* check gateway. */
 
117
 
 
118
        /* if no command set, set all. */
 
119
        if (memcmp(&state.command, &route->gw.state.command, sizeof(state.command))
 
120
        == 0)
 
121
                memset(&route->gw.state.command, UCHAR_MAX,
 
122
                sizeof(route->gw.state.command));
 
123
 
 
124
        /* if no protocol set, set all. */
 
125
        if (memcmp(&state.protocol, &route->gw.state.protocol,
 
126
        sizeof(state.protocol)) == 0)
 
127
                memset(&route->gw.state.protocol, UCHAR_MAX,
 
128
                sizeof(route->gw.state.protocol));
 
129
 
 
130
        /* if no proxyprotocol set, set all except msproxy. */
 
131
        if (memcmp(&state.proxyprotocol, &route->gw.state.proxyprotocol,
 
132
        sizeof(state.proxyprotocol)) == 0) {
 
133
                memset(&route->gw.state.proxyprotocol, UCHAR_MAX,
 
134
                sizeof(route->gw.state.proxyprotocol));
 
135
                route->gw.state.proxyprotocol.msproxy_v2 = 0;
 
136
        }
 
137
 
 
138
        /* switch off commands/protocols set but not supported by proxyprotocol. */
 
139
        if (!route->gw.state.proxyprotocol.socks_v5) {
 
140
                route->gw.state.command.udpassociate    = 0;
 
141
                route->gw.state.protocol.udp                            = 0;
 
142
        }
 
143
 
 
144
        if (!route->gw.state.proxyprotocol.socks_v4
 
145
        && !route->gw.state.proxyprotocol.msproxy_v2)
 
146
                route->gw.state.command.bind = 0;
 
147
 
 
148
        /* if no method set, set all we support. */
 
149
        if (route->gw.state.methodc == 0) {
 
150
                int *methodv = route->gw.state.methodv;
 
151
                size_t *methodc = &route->gw.state.methodc;
 
152
 
 
153
                methodv[(*methodc)++] = AUTHMETHOD_NONE;
 
154
                methodv[(*methodc)++] = AUTHMETHOD_UNAME;
 
155
        }
 
156
 
 
157
        if (route->src.atype == SOCKS_ADDR_IFNAME)
 
158
                yyerror("interfacenames not supported for src address");
 
159
 
 
160
        if (route->dst.atype == SOCKS_ADDR_IFNAME)
 
161
                yyerror("interfacenames not supported for src address");
 
162
 
 
163
        if (sockscf.route == NULL) {
 
164
                sockscf.route = route;
 
165
                sockscf.route->number = 1;
 
166
        }
 
167
        else {
 
168
                /* append rule to the end of list. */
 
169
                struct route_t *lastroute;
 
170
 
 
171
                lastroute = sockscf.route;
 
172
                while (lastroute->next != NULL)
 
173
                        lastroute = lastroute->next;
 
174
 
 
175
                route->number = lastroute->number + 1;
 
176
                lastroute->next = route;
 
177
        }
 
178
        route->next = NULL;
 
179
 
 
180
        return route;
 
181
}
 
182
 
 
183
 
 
184
void
 
185
showroute(route)
 
186
        const struct route_t *route;
 
187
{
 
188
        char hstring[MAXSOCKSHOSTSTRING];
 
189
        char addr[MAXRULEADDRSTRING];
 
190
 
 
191
        slog(LOG_INFO, "route #%d", route->number);
 
192
 
 
193
        slog(LOG_INFO, "src: %s",
 
194
        ruleaddress2string(&route->src, addr, sizeof(addr)));
 
195
 
 
196
        slog(LOG_INFO, "dst: %s",
 
197
        ruleaddress2string(&route->dst, addr, sizeof(addr)));
 
198
 
 
199
        slog(LOG_INFO, "gateway: %s",
 
200
        sockshost2string(&route->gw.host, hstring, sizeof(hstring)));
 
201
 
 
202
        showstate(&route->gw.state);
 
203
}
 
204
 
 
205
 
 
206
struct route_t *
 
207
socks_getroute(req, src, dst)
 
208
        const struct request_t *req;
 
209
        const struct sockshost_t *src;
 
210
        const struct sockshost_t *dst;
 
211
{
 
212
/*      const char *function = "socks_getroute()"; */
 
213
        struct route_t *route;
 
214
        int protocol;
 
215
 
 
216
#if SOCKS_CLIENT
 
217
        clientinit();
 
218
#endif
 
219
 
 
220
        for (route = sockscf.route; route != NULL; route = route->next) {
 
221
                if (route->state.bad)
 
222
                        /* CONSTCOND */
 
223
                        if (BADROUTE_EXPIRE == 0
 
224
                        ||  difftime(time(NULL), route->state.badtime) <= BADROUTE_EXPIRE)
 
225
                                continue;
 
226
                        else
 
227
                                route->state.bad = 0;
 
228
 
 
229
                switch (req->version) {
 
230
                        case SOCKS_V4:
 
231
                                if (!route->gw.state.proxyprotocol.socks_v4)
 
232
                                        continue;
 
233
 
 
234
                                switch (req->host.atype) {
 
235
                                        case SOCKS_ADDR_IPV4:
 
236
                                                break;
 
237
 
 
238
                                        case SOCKS_ADDR_IPV6:
 
239
                                        case SOCKS_ADDR_DOMAIN:
 
240
                                                continue; /* not failure, just checking. */
 
241
 
 
242
                                        default:
 
243
                                                SERRX(req->host.atype); /* failure, nothing else exists. */
 
244
                                }
 
245
                                break;
 
246
 
 
247
                        case SOCKS_V5:
 
248
                                if (!route->gw.state.proxyprotocol.socks_v5)
 
249
                                        continue;
 
250
 
 
251
                                switch (req->host.atype) {
 
252
                                        case SOCKS_ADDR_IPV4:
 
253
                                        case SOCKS_ADDR_IPV6:
 
254
                                        case SOCKS_ADDR_DOMAIN:
 
255
                                                break;
 
256
 
 
257
                                        default:
 
258
                                                SERRX(req->host.atype); /* failure, nothing else exists. */
 
259
                                }
 
260
                                break;
 
261
 
 
262
                        case MSPROXY_V2:
 
263
                                if (!route->gw.state.proxyprotocol.msproxy_v2)
 
264
                                        continue;
 
265
                                break;
 
266
 
 
267
                        case HTTP_V1_0:
 
268
                                if (!route->gw.state.proxyprotocol.http_v1_0)
 
269
                                        continue;
 
270
                                break;
 
271
 
 
272
                        default:
 
273
                                SERRX(req->version);
 
274
                }
 
275
 
 
276
                switch (req->command) {
 
277
                        case SOCKS_BIND:
 
278
                                if (!route->gw.state.command.bind)
 
279
                                        continue;
 
280
 
 
281
                                if (req->host.atype == SOCKS_ADDR_IPV4
 
282
                                &&  req->host.addr.ipv4.s_addr == htonl(0))
 
283
                                        if (req->version == MSPROXY_V2)
 
284
                                                ; /* supports binding wildcard */
 
285
                                        else if (!route->gw.state.extension.bind)
 
286
                                                continue;
 
287
                                break;
 
288
 
 
289
                        case SOCKS_CONNECT:
 
290
                                if (!route->gw.state.command.connect)
 
291
                                        continue;
 
292
                                break;
 
293
 
 
294
                        case SOCKS_UDPASSOCIATE:
 
295
                                if (!route->gw.state.command.udpassociate)
 
296
                                        continue;
 
297
                                break;
 
298
 
 
299
                        default:
 
300
                                SERRX(req->command);
 
301
                }
 
302
 
 
303
                /* server supports protocol? */
 
304
                switch (req->command) {
 
305
                        case SOCKS_BIND:
 
306
                        case SOCKS_CONNECT:
 
307
                                if (!route->gw.state.protocol.tcp)
 
308
                                        continue;
 
309
                                protocol = SOCKS_TCP;
 
310
                                break;
 
311
 
 
312
                        case SOCKS_UDPASSOCIATE:
 
313
                                if (!route->gw.state.protocol.udp)
 
314
                                        continue;
 
315
                                protocol = SOCKS_UDP;
 
316
                                break;
 
317
 
 
318
                        default:
 
319
                                SERRX(req->command);
 
320
                }
 
321
 
 
322
                if (src != NULL)
 
323
                        if (!addressmatch(&route->src, src, protocol, 0))
 
324
                                continue;
 
325
 
 
326
                if (dst != NULL)
 
327
                        if (!addressmatch(&route->dst, dst, protocol, 0))
 
328
                                continue;
 
329
 
 
330
                if (route->state.direct)
 
331
                        return NULL; /* don't use any route, connect directly. */
 
332
 
 
333
                break;  /* all matched */
 
334
        }
 
335
 
 
336
        return route;
 
337
}
 
338
 
 
339
 
 
340
struct route_t *
 
341
socks_connectroute(s, packet, src, dst)
 
342
        int s;
 
343
        struct socks_t *packet;
 
344
        const struct sockshost_t *src;
 
345
        const struct sockshost_t *dst;
 
346
{
 
347
        const char *function = "socks_connectroute()";
 
348
        int sdup, current_s, errno_s;
 
349
        struct route_t *route;
 
350
 
 
351
        /*
 
352
         * This is a little tricky since we attempt to support trying
 
353
         * more than one socksserver.  If the first one fails, we try
 
354
         * the next, etc.  Ofcourse, if connect() on one socket fails,
 
355
         * that socket can no longer be used, so we need to be able to
 
356
         * copy/dup the original socket as much as possible.  Later,
 
357
         * if it turned out a connection failed and we had to use a
 
358
         * different socket than the orignal 's', we try to dup the
 
359
         * differently numbered socket to 's' and hope the best.
 
360
         *
 
361
         * sdup:                        copy of the original socket.  Need to create this
 
362
         *                                      before the first connectattempt since the connectattempt
 
363
         *                                 could prevent us from doing it later, depending on failure
 
364
         *                                      reason.
 
365
         *
 
366
         * current_s:   socket to use for next connection attempt.  For the
 
367
         *                                      first attempt this is 's'.
 
368
         */
 
369
 
 
370
        errno                   = 0; /* let caller differentiate between missing route and not.*/
 
371
        current_s       = s;
 
372
        sdup                    = -1;
 
373
 
 
374
        while ((route = socks_getroute(&packet->req, src, dst)) != NULL) {
 
375
                char hstring[MAXSOCKSHOSTSTRING];
 
376
 
 
377
                /* inside loop since if no route, no need for it. */
 
378
                if (sdup == -1)
 
379
                        sdup = socketoptdup(s);
 
380
 
 
381
                if (current_s == -1)
 
382
                        if ((current_s = socketoptdup(sdup == -1 ? s : sdup)) == -1)
 
383
                                return NULL;
 
384
 
 
385
                slog(LOG_DEBUG, "%s: trying route #%d (%s)",
 
386
                function, route->number,
 
387
                sockshost2string(&route->gw.host, hstring, sizeof(hstring)));
 
388
 
 
389
                if (socks_connect(current_s, &route->gw.host) == 0)
 
390
                        break;
 
391
                else
 
392
                        /*
 
393
                         * Check whether the error indicates bad socksserver or
 
394
                         * something else.
 
395
                         */
 
396
                        if (errno == EINPROGRESS) {
 
397
                                SASSERTX(current_s == s);
 
398
                                break;
 
399
                        }
 
400
                        else if (errno == EADDRINUSE) {
 
401
                                /* see Rbind() for explanation. */
 
402
                                SASSERTX(current_s == s);
 
403
                                route = NULL;
 
404
                                break;
 
405
                        }
 
406
                        else {
 
407
                                swarn("%s: socks_connect(%s)",
 
408
                                function, sockshost2string(&route->gw.host, hstring,
 
409
                                sizeof(hstring)));
 
410
                                socks_badroute(route);
 
411
                                close(current_s);
 
412
                                current_s = -1;
 
413
                }
 
414
        }
 
415
 
 
416
        errno_s = errno;
 
417
 
 
418
        if (sdup != -1)
 
419
                close(sdup);
 
420
 
 
421
        if (current_s != s && current_s != -1)  {
 
422
                /* created a new socket for connect, need to make it same descriptor #. */
 
423
                if (dup2(current_s, s) == -1) {
 
424
                        close(current_s);
 
425
                        return NULL;
 
426
                }
 
427
                close(current_s);
 
428
 
 
429
#if SOCKS_SERVER && HAVE_LIBWRAP
 
430
                if ((current_s = fcntl(s, F_GETFD, 0)) == -1
 
431
                || fcntl(s, F_SETFD, current_s | FD_CLOEXEC) == -1)
 
432
                        swarn("%s: fcntl(F_GETFD/F_SETFD)", function);
 
433
#endif
 
434
        }
 
435
 
 
436
        if (route != NULL) {
 
437
                static int init;
 
438
 
 
439
                packet->gw = route->gw;
 
440
 
 
441
                /* need to set up misc. crap for msproxy stuff. */
 
442
                if (!init && route->gw.state.proxyprotocol.msproxy_v2) {
 
443
                        if (msproxy_init() != 0)
 
444
                                ;       /* yes, then what? */
 
445
                        init = 1;
 
446
                }
 
447
        }
 
448
 
 
449
        errno = errno_s;
 
450
        return route;
 
451
}
 
452
 
 
453
void
 
454
socks_badroute(route)
 
455
        struct route_t *route;
 
456
{
 
457
        const char *function = "socks_badroute()";
 
458
 
 
459
        slog(LOG_DEBUG, "%s: badrouting route #%d", function, route->number);
 
460
        route->state.bad = 1;
 
461
        time(&route->state.badtime);
 
462
}
 
463
 
 
464
 
 
465
struct request_t *
 
466
socks_requestpolish(req, src, dst)
 
467
        struct request_t *req;
 
468
        const struct sockshost_t *src;
 
469
        const struct sockshost_t *dst;
 
470
{
 
471
        const char *function = "socks_requestpolish()";
 
472
        const unsigned char originalversion = req->version;
 
473
 
 
474
        if (socks_getroute(req, src, dst) != NULL)
 
475
                return req;
 
476
 
 
477
        switch (req->command) {
 
478
                case SOCKS_BIND:
 
479
                        /*
 
480
                         * bind semantics differ between v4 and everything else.
 
481
                         * Assuming we always start with v5 semantics makes the
 
482
                         * following code much simpler.
 
483
                         */
 
484
                        SASSERTX(req->version == SOCKS_V5);
 
485
                        break;
 
486
 
 
487
                case SOCKS_CONNECT:
 
488
                        break;
 
489
 
 
490
                case SOCKS_UDPASSOCIATE:
 
491
                        SERRX(req->command);    /* currently not implemented, shouldn't happen. */
 
492
                        /* NOTREACHED */
 
493
 
 
494
                default:
 
495
                        SERRX(req->command);
 
496
        }
 
497
 
 
498
        /*
 
499
         * Try all proxyprotocols we support.
 
500
         */
 
501
 
 
502
        req->version = SOCKS_V4;
 
503
        if (socks_getroute(req, src, dst) != NULL) {
 
504
                if (req->command == SOCKS_BIND) /* v4/v5 difference in portsemantics. */
 
505
                        /* LINTED pointer casts may be troublesome */
 
506
                        req->host.port = TOIN(&sockscf.state.lastconnect)->sin_port;
 
507
                return req;
 
508
        }
 
509
 
 
510
        req->version = HTTP_V1_0;
 
511
        if (socks_getroute(req, src, dst) != NULL)
 
512
                return req;
 
513
 
 
514
        req->version = MSPROXY_V2;
 
515
        if (socks_getroute(req, src, dst) != NULL)
 
516
                return req;
 
517
 
 
518
        req->version = originalversion;
 
519
 
 
520
        /* changing proxyprotocol didn't do it, can we try other things? */
 
521
        switch (req->command) {
 
522
                case SOCKS_BIND:
 
523
                        if (req->host.addr.ipv4.s_addr == htonl(0)) {
 
524
                                in_port_t originalport;
 
525
 
 
526
                                /* attempting to use bind extension, can we retry without it? */
 
527
                                /* LINTED pointer casts may be troublesome */
 
528
                                if (!ADDRISBOUND(sockscf.state.lastconnect)) {
 
529
                                        slog(LOG_DEBUG, "%s: couldn't find route for bind(2), "
 
530
                                        "try enabling \"extension: bind\"?", function);
 
531
                                        return NULL;
 
532
                                }
 
533
 
 
534
                                originalport = req->host.port;
 
535
                                fakesockaddr2sockshost(&sockscf.state.lastconnect, &req->host);
 
536
                                /* keep portnumber req. for bind(2), not a previous connect(2). */
 
537
                                req->host.port = originalport;
 
538
 
 
539
                                if (socks_requestpolish(req, src, dst) == NULL)
 
540
                                        return NULL; /* giving up. */
 
541
 
 
542
                                /*
 
543
                                 * else, it may be that socks_requestpolish() was
 
544
                                 * forced to change req.version to succeed.  We may
 
545
                                 * the need to change req->host.port due to difference
 
546
                                 * in v4 and v5 semantics.
 
547
                                */
 
548
                                if (req->version != originalversion) { /* version changed. */
 
549
                                        SASSERTX(originalversion == SOCKS_V5);
 
550
 
 
551
                                        switch (req->version) {
 
552
                                                case SOCKS_V4: /* the only one with this strangeness. */
 
553
                                                        /* LINTED pointer casts may be troublesome */
 
554
                                                        req->host.port
 
555
                                                        = TOIN(&sockscf.state.lastconnect)->sin_port;
 
556
                                                        break;
 
557
                                        }
 
558
                                }
 
559
 
 
560
                                return req;
 
561
                        }
 
562
                        break;
 
563
        }
 
564
 
 
565
        return NULL;
 
566
}
 
567
 
 
568
#endif /* SOCKS_CLIENT */
 
569
 
 
570
void
 
571
showstate(state)
 
572
        const struct serverstate_t *state;
 
573
{
 
574
        char buf[1024];
 
575
        size_t bufused;
 
576
 
 
577
        bufused = snprintfn(buf, sizeof(buf), "command(s): ");
 
578
        if (state->command.bind)
 
579
                bufused += snprintfn(&buf[bufused], sizeof(buf) - bufused, "%s, ",
 
580
                SOCKS_BINDs);
 
581
        if (state->command.bindreply)
 
582
                bufused += snprintfn(&buf[bufused], sizeof(buf) - bufused, "%s, ",
 
583
                SOCKS_BINDREPLYs);
 
584
        if (state->command.connect)
 
585
                bufused += snprintfn(&buf[bufused], sizeof(buf) - bufused, "%s, ",
 
586
                SOCKS_CONNECTs);
 
587
        if (state->command.udpassociate)
 
588
                bufused += snprintfn(&buf[bufused], sizeof(buf) - bufused, "%s, ",
 
589
                SOCKS_UDPASSOCIATEs);
 
590
        if (state->command.udpreply)
 
591
                bufused += snprintfn(&buf[bufused], sizeof(buf) - bufused, "%s, ",
 
592
                SOCKS_UDPREPLYs);
 
593
        slog(LOG_INFO, buf);
 
594
 
 
595
        bufused = snprintfn(buf, sizeof(buf), "extension(s): ");
 
596
        if (state->extension.bind)
 
597
                bufused += snprintfn(&buf[bufused], sizeof(buf) - bufused, "bind");
 
598
        slog(LOG_INFO, buf);
 
599
 
 
600
        bufused = snprintfn(buf, sizeof(buf), "protocol(s): ");
 
601
        protocols2string(&state->protocol,
 
602
        &buf[bufused], sizeof(buf) - bufused);
 
603
        slog(LOG_INFO, buf);
 
604
 
 
605
        showmethod(state->methodc, state->methodv);
 
606
 
 
607
        bufused = snprintfn(buf, sizeof(buf), "proxyprotocol(s): ");
 
608
        proxyprotocols2string(&state->proxyprotocol,
 
609
        &buf[bufused], sizeof(buf) - bufused);
 
610
        slog(LOG_INFO, buf);
 
611
 
 
612
}
 
613
 
 
614
void
 
615
showmethod(methodc, methodv)
 
616
        size_t methodc;
 
617
        const int *methodv;
 
618
{
 
619
        char buf[1024];
 
620
 
 
621
        slog(LOG_INFO, "method(s): %s",
 
622
        methods2string(methodc, methodv, buf, sizeof(buf)));
 
623
}