1 /*
2  * Copyright (c) 1997, 1998, 1999, 2000, 2001, 2003, 2005, 2006, 2008, 2009,
3  *               2010, 2011, 2012, 2013, 2014, 2019
4  *      Inferno Nettverk A/S, Norway.  All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. The above copyright notice, this list of conditions and the following
10  *    disclaimer must appear in all copies of the software, derivative works
11  *    or modified versions, and any portions thereof, aswell as in all
12  *    supporting documentation.
13  * 2. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by
16  *      Inferno Nettverk A/S, Norway.
17  * 3. The name of the author may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  * Inferno Nettverk A/S requests users of this software to return to
32  *
33  *  Software Distribution Coordinator  or  sdc@inet.no
34  *  Inferno Nettverk A/S
35  *  Oslo Research Park
36  *  Gaustadall�en 21
37  *  NO-0349 Oslo
38  *  Norway
39  *
40  * any improvements or extensions that they make and grant Inferno Nettverk A/S
41  * the rights to redistribute these changes.
42  *
43  */
44 
45 #include "common.h"
46 #include "config_parse.h"
47 
48 static const char rcsid[] =
49 "$Id: tostring.c,v 1.225.4.9.6.2 2020/11/11 16:11:54 karls Exp $";
50 
51 static const char *stripstring = ", \t\n";
52 
53 char *
aihints2string(hints,buf,buflen)54 aihints2string(hints, buf, buflen)
55    const struct addrinfo *hints;
56    char *buf;
57    size_t buflen;
58 {
59    if (buf == NULL || buflen == 0) {
60       static char _buf[64];
61 
62       buf    = _buf;
63       buflen = sizeof(_buf);
64    }
65 
66    *buf    = NUL;
67 
68    snprintf(buf, buflen,
69             "ai_flags: %d, ai_family: %d, ai_socktype: %d, ai_protocol: %d",
70             hints->ai_flags,
71             hints->ai_family,
72             hints->ai_socktype,
73             hints->ai_protocol);
74 
75    return buf;
76 }
77 
78 char *
fdset2string(nfds,set,docheck,buf,buflen)79 fdset2string(nfds, set, docheck, buf, buflen)
80    const int nfds;
81    const fd_set *set;
82    const int docheck;
83    char *buf;
84    size_t buflen;
85 {
86    size_t bufused;
87    int i, rc;
88 
89    if (buf == NULL || buflen == 0) {
90       static char _buf[10240];
91 
92       buf    = _buf;
93       buflen = sizeof(_buf);
94    }
95 
96    bufused = 0;
97    *buf    = NUL;
98 
99    if (set == NULL)
100       return buf;
101 
102    for (i = 0; i < nfds; ++i) {
103       if (FD_ISSET(i, set)) {
104          rc = snprintf(&buf[bufused], buflen - bufused,
105                       "%d%s, ",
106                       i, docheck ? (fdisopen(i) ? "" : "-invalid") : "");
107          bufused += rc;
108       }
109    }
110 
111    return buf;
112 }
113 
114 int32_t
string2portnumber(string,emsg,emsglen)115 string2portnumber(string, emsg, emsglen)
116    const char *string;
117    char *emsg;
118    size_t emsglen;
119 {
120    char *endptr, visbuf[256];
121    long portnumber;
122 
123    if (emsg == NULL || emsglen == 0) {
124       static char _emsg[256];
125 
126       emsg    = _emsg;
127       emsglen = sizeof(_emsg);
128    }
129 
130    portnumber = strtol(string, &endptr, 10);
131 
132    if (*endptr == NUL || *endptr == '/' || isspace(*endptr)) {
133       if (portnumber >= 0 && portnumber <= IP_MAXPORT)
134          return (int32_t)portnumber;
135       else {
136          snprintf(emsg, emsglen,
137                   "portnumber given (%ld) is out of range.  Must be in the "
138                   "range 0 - %u",
139                   portnumber, IP_MAXPORT);
140 
141          return -1;
142       }
143    }
144 
145    snprintf(emsg, emsglen,
146             "\"%s\" does not appear to be a valid portnumber in the range "
147             "0 - %u",
148             str2vis(string, strlen(string), visbuf, sizeof(visbuf)),
149             IP_MAXPORT);
150 
151    return -1;
152 }
153 
154 char *
proxyprotocols2string(proxyprotocols,str,strsize)155 proxyprotocols2string(proxyprotocols, str, strsize)
156    const proxyprotocol_t *proxyprotocols;
157    char *str;
158    size_t strsize;
159 {
160    size_t strused;
161 
162    if (strsize == 0) {
163       static char buf[256];
164 
165       str = buf;
166       strsize = sizeof(buf);
167    }
168 
169    *str    = NUL;
170    strused = 0;
171 
172    if (proxyprotocols->socks_v4)
173       strused += snprintf(&str[strused], strsize - strused, "%s, ",
174       QUOTE(PROXY_SOCKS_V4s));
175 
176    if (proxyprotocols->socks_v5)
177       strused += snprintf(&str[strused], strsize - strused, "%s, ",
178       QUOTE(PROXY_SOCKS_V5s));
179 
180    if (proxyprotocols->http)
181       strused += snprintf(&str[strused], strsize - strused, "%s, ",
182       QUOTE("HTTP"));
183 
184    if (proxyprotocols->upnp)
185       strused += snprintf(&str[strused], strsize - strused, "%s, ",
186       QUOTE(PROXY_UPNPs));
187 
188    if (proxyprotocols->direct)
189       strused += snprintf(&str[strused], strsize - strused, "%s, ",
190       QUOTE(PROXY_DIRECTs));
191 
192    STRIPTRAILING(str, strused, stripstring);
193    return str;
194 }
195 
196 char *
protocols2string(protocols,str,strsize)197 protocols2string(protocols, str, strsize)
198    const protocol_t *protocols;
199    char *str;
200    size_t strsize;
201 {
202    size_t strused;
203 
204    if (strsize == 0) {
205       static char buf[16];
206 
207       str = buf;
208       strsize = sizeof(buf);
209    }
210 
211    *str    = NUL;
212    strused = 0;
213 
214    if (protocols->tcp)
215       strused += snprintf(&str[strused], strsize - strused, "%s, ",
216       QUOTE(PROTOCOL_TCPs));
217 
218    if (protocols->udp)
219       strused += snprintf(&str[strused], strsize - strused, "%s, ",
220       QUOTE(PROTOCOL_UDPs));
221 
222    STRIPTRAILING(str, strused, stripstring);
223    return str;
224 }
225 
226 const char *
socks_packet2string(packet,isrequest)227 socks_packet2string(packet, isrequest)
228      const void *packet;
229      int isrequest;
230 {
231    static char buf[1024];
232    char hstr[MAXSOCKSHOSTSTRING];
233    unsigned char version;
234    const request_t *request = NULL;
235    const response_t *response = NULL;
236 
237    if (isrequest) {
238       request = (const request_t *)packet;
239       version = request->version;
240    }
241    else {
242       response = (const response_t *)packet;
243       version  = response->version;
244    }
245 
246    switch (version) {
247       case PROXY_SOCKS_V4:
248       case PROXY_SOCKS_V4REPLY_VERSION:
249          if (isrequest)
250             snprintf(buf, sizeof(buf),
251                      "VER: %d CMD: %d address: %s",
252                      request->version,
253                      request->command,
254                      sockshost2string(&request->host, hstr, sizeof(hstr)));
255          else
256             snprintf(buf, sizeof(buf),
257                      "VER: %d REP: %d address: %s",
258                      response->version,
259                      response->reply.socks,
260                      sockshost2string(&response->host, hstr, sizeof(hstr)));
261 
262          break;
263 
264       case PROXY_SOCKS_V5:
265          if (isrequest)
266             snprintf(buf, sizeof(buf),
267                      "VER: %d CMD: %d FLAG: %d ATYP: %d address: %s",
268                      request->version,
269                      request->command,
270                      request->flag,
271                      request->host.atype,
272                      sockshost2string(&request->host, hstr, sizeof(hstr)));
273          else
274             snprintf(buf, sizeof(buf),
275                      "VER: %d REP: %d FLAG: %d ATYP: %d address: %s",
276                      response->version,
277                      response->reply.socks,
278                      response->flag,
279                      response->host.atype,
280                      sockshost2string(&response->host, hstr, sizeof(hstr)));
281 
282          break;
283 
284       case PROXY_HTTP_10:
285       case PROXY_HTTP_11:
286          if (isrequest)
287             snprintf(buf, sizeof(buf),
288                      "VER: %d CMD: %d ATYP: %d address: %s",
289                      request->version,
290                      request->command,
291                      request->host.atype,
292                      sockshost2string(&request->host, hstr, sizeof(hstr)));
293          else
294             snprintf(buf, sizeof(buf),
295                      "VER: %d REP: %d ATYP: %d address: %s",
296                      response->version,
297                      response->reply.http,
298                      response->host.atype,
299                      sockshost2string(&response->host, hstr, sizeof(hstr)));
300 
301          break;
302 
303       default:
304          SERRX(version);
305   }
306 
307   return buf;
308 }
309 
310 enum operator_t
string2operator(string)311 string2operator(string)
312    const char *string;
313 {
314 
315    if (strcmp(string, "eq") == 0 || strcmp(string, "=") == 0)
316       return eq;
317 
318    if (strcmp(string, "ne") == 0 || strcmp(string, "!=") == 0)
319       return neq;
320 
321    if (strcmp(string, "ge") == 0 || strcmp(string, ">=") == 0)
322       return ge;
323 
324    if (strcmp(string, "le") == 0 || strcmp(string, "<=") == 0)
325       return le;
326 
327    if (strcmp(string, "gt") == 0 || strcmp(string, ">") == 0)
328       return gt;
329 
330    if (strcmp(string, "lt") == 0 || strcmp(string, "<") == 0)
331       return lt;
332 
333    /* parser should make sure this never happens. */
334    SERRX(0);
335 
336    /* NOTREACHED */
337 }
338 
339 const char *
operator2string(operator)340 operator2string(operator)
341    enum operator_t operator;
342 {
343 
344    switch (operator) {
345       case none:
346          return QUOTE("none");
347 
348       case eq:
349          return QUOTE("eq");
350 
351       case neq:
352          return QUOTE("neq");
353 
354       case ge:
355          return QUOTE("ge");
356 
357       case le:
358          return QUOTE("le");
359 
360       case gt:
361          return QUOTE("gt");
362 
363       case lt:
364          return QUOTE("lt");
365 
366       case range:
367          return QUOTE("range");
368 
369       default:
370          SERRX(operator);
371    }
372 
373    /* NOTREACHED */
374 }
375 
376 const char *
ruleaddr2string(address,includeinfo,string,len)377 ruleaddr2string(address, includeinfo, string, len)
378    const ruleaddr_t *address;
379    const size_t includeinfo;
380    char *string;
381    size_t len;
382 {
383    const char *function = "ruleaddr2string()";
384    ssize_t lenused;
385 
386    if (string == NULL || len == 0) {
387       static char addrstring[MAXRULEADDRSTRING];
388 
389       string = addrstring;
390       len    = sizeof(addrstring);
391    }
392 
393    lenused = 0;
394 
395    if (includeinfo & ADDRINFO_ATYPE)
396       lenused += snprintf(string, len, "%s ", atype2string(address->atype));
397 
398    switch (address->atype) {
399       case SOCKS_ADDR_IPV4: {
400          char ntop[MAXSOCKADDRSTRING];
401 
402          if (inet_ntop(AF_INET, &address->addr.ipv4.ip, ntop, sizeof(ntop))
403          == NULL)
404             serr("%s: inet_ntop(3) failed on %s %x",
405                  function,
406                  atype2string(address->atype),
407                  address->addr.ipv4.ip.s_addr);
408 
409          lenused += snprintf(&string[lenused], len - lenused, "%s/%d",
410                              ntop,
411                              bitcount((unsigned long)
412                                                address->addr.ipv4.mask.s_addr));
413          break;
414       }
415 
416       case SOCKS_ADDR_IPV6: {
417          char ntop[MAXSOCKADDRSTRING];
418 
419          if (inet_ntop(AF_INET6, &address->addr.ipv6.ip, ntop, sizeof(ntop))
420          == NULL)
421             serr("%s: inet_ntop(3) failed on %s " IP6_FMTSTR,
422                  function,
423                  atype2string(address->atype),
424                  IP6_ELEMENTS(&address->addr.ipv6.ip));
425 
426          lenused += snprintf(&string[lenused], len - lenused, "%s/%u",
427                              ntop, address->addr.ipv6.maskbits);
428          break;
429       }
430 
431       case SOCKS_ADDR_IPVANY:
432          SASSERTX(address->addr.ipvany.ip.s_addr   == htonl(0));
433          SASSERTX(address->addr.ipvany.mask.s_addr == htonl(0));
434 
435          lenused += snprintf(&string[lenused], len - lenused, "%d/%d",
436                              ntohl(address->addr.ipvany.ip.s_addr),
437                              bitcount((unsigned long)
438                                            address->addr.ipvany.mask.s_addr));
439          break;
440 
441       case SOCKS_ADDR_DOMAIN:
442          lenused += snprintf(&string[lenused], len - lenused,
443                              "%s", address->addr.domain);
444          break;
445 
446       case SOCKS_ADDR_IFNAME:
447          lenused += snprintf(&string[lenused], len - lenused,
448                             "%s", address->addr.ifname);
449          break;
450 
451       default:
452          SERRX(address->atype);
453    }
454 
455    if (includeinfo & ADDRINFO_PORT) {
456       switch (address->operator) {
457          case none:
458             break;
459 
460          case eq:
461          case neq:
462          case ge:
463          case le:
464          case gt:
465          case lt:
466             if (address->port.tcp == address->port.udp)
467                lenused += snprintf(&string[lenused], len - lenused,
468                                    " port %s %u",
469                                    operator2string(address->operator),
470                                    ntohs(address->port.tcp));
471             else
472                lenused += snprintf(&string[lenused], len - lenused,
473                                    " port %s %u (tcp) / %u (udp)",
474                                    operator2string(address->operator),
475                                    ntohs(address->port.tcp),
476                                    ntohs(address->port.udp));
477             break;
478 
479          case range:
480             SASSERTX(address->port.tcp == address->port.udp);
481             lenused += snprintf(&string[lenused], len - lenused,
482                                 " port %s %u - %u",
483                                 operator2string(address->operator),
484                                 ntohs(address->port.tcp),
485                                 ntohs(address->portend));
486             break;
487 
488          default:
489             SERRX(address->operator);
490       }
491    }
492 
493    return string;
494 }
495 
496 const char *
protocol2string(protocol)497 protocol2string(protocol)
498    int protocol;
499 {
500 
501    switch (protocol) {
502       case SOCKS_TCP:
503          return QUOTE(PROTOCOL_TCPs);
504 
505       case SOCKS_UDP:
506          return QUOTE(PROTOCOL_UDPs);
507 
508       default:
509          SERRX(protocol);
510    }
511 
512    /* NOTREACHED */
513 }
514 
515 const char *
resolveprotocol2string(resolveprotocol)516 resolveprotocol2string(resolveprotocol)
517    int resolveprotocol;
518 {
519    switch (resolveprotocol) {
520       case RESOLVEPROTOCOL_TCP:
521          return QUOTE(PROTOCOL_TCPs);
522 
523       case RESOLVEPROTOCOL_UDP:
524          return QUOTE(PROTOCOL_UDPs);
525 
526       case RESOLVEPROTOCOL_FAKE:
527          return QUOTE("fake");
528 
529       default:
530          SERRX(resolveprotocol);
531    }
532 
533    /* NOTREACHED */
534 }
535 
536 const char *
command2string(command)537 command2string(command)
538    int command;
539 {
540 
541    switch (command) {
542       case SOCKS_BIND:
543          return QUOTE(SOCKS_BINDs);
544 
545       case SOCKS_CONNECT:
546          return QUOTE(SOCKS_CONNECTs);
547 
548       case SOCKS_UDPASSOCIATE:
549          return QUOTE(SOCKS_UDPASSOCIATEs);
550 
551       /* pseudo commands. */
552       case SOCKS_ACCEPT:
553          return QUOTE(SOCKS_ACCEPTs);
554 
555       case SOCKS_BINDREPLY:
556          return QUOTE(SOCKS_BINDREPLYs);
557 
558       case SOCKS_UDPREPLY:
559          return QUOTE(SOCKS_UDPREPLYs);
560 
561       case SOCKS_DISCONNECT:
562          return QUOTE(SOCKS_DISCONNECTs);
563 
564       case SOCKS_BOUNCETO:
565          return QUOTE(SOCKS_BOUNCETOs);
566 
567       case SOCKS_HOSTID:
568          return QUOTE(SOCKS_HOSTIDs);
569 
570       case SOCKS_UNKNOWN:
571          return QUOTE(SOCKS_UNKNOWNs);
572 
573       default:
574          SERRX(command);
575    }
576 
577    /* NOTREACHED */
578 }
579 
580 char *
commands2string(command,str,strsize)581 commands2string(command, str, strsize)
582    const command_t *command;
583    char *str;
584    size_t strsize;
585 {
586    size_t strused;
587 
588    if (strsize == 0) {
589       static char buf[128];
590 
591       str = buf;
592       strsize = sizeof(buf);
593    }
594 
595    *str    = NUL;
596    strused = 0;
597 
598    if (command->bind)
599       strused += snprintf(&str[strused], strsize - strused, "%s, ",
600       command2string(SOCKS_BIND));
601 
602    if (command->bindreply)
603       strused += snprintf(&str[strused], strsize - strused, "%s, ",
604       command2string(SOCKS_BINDREPLY));
605 
606    if (command->connect)
607       strused += snprintf(&str[strused], strsize - strused, "%s, ",
608       command2string(SOCKS_CONNECT));
609 
610    if (command->udpassociate)
611       strused += snprintf(&str[strused], strsize - strused, "%s, ",
612       command2string(SOCKS_UDPASSOCIATE));
613 
614    if (command->udpreply)
615       strused += snprintf(&str[strused], strsize - strused, "%s, ",
616       command2string(SOCKS_UDPREPLY));
617 
618    STRIPTRAILING(str, strused, stripstring);
619    return str;
620 }
621 
622 const char *
method2string(method)623 method2string(method)
624    int method;
625 {
626 
627    switch (method) {
628       case AUTHMETHOD_NOTSET:
629          return QUOTE(AUTHMETHOD_NOTSETs);
630 
631       case AUTHMETHOD_NONE:
632          return QUOTE(AUTHMETHOD_NONEs);
633 
634       case AUTHMETHOD_GSSAPI:
635          return QUOTE(AUTHMETHOD_GSSAPIs);
636 
637       case AUTHMETHOD_UNAME:
638          return QUOTE(AUTHMETHOD_UNAMEs);
639 
640       case AUTHMETHOD_NOACCEPT:
641          return QUOTE(AUTHMETHOD_NOACCEPTs);
642 
643       case AUTHMETHOD_RFC931:
644          return QUOTE(AUTHMETHOD_RFC931s);
645 
646       case AUTHMETHOD_PAM_ANY:
647          return QUOTE(AUTHMETHOD_PAM_ANYs);
648 
649       case AUTHMETHOD_PAM_ADDRESS:
650          return QUOTE(AUTHMETHOD_PAM_ADDRESSs);
651 
652       case AUTHMETHOD_PAM_USERNAME:
653          return QUOTE(AUTHMETHOD_PAM_USERNAMEs);
654 
655       case AUTHMETHOD_BSDAUTH:
656          return QUOTE(AUTHMETHOD_BSDAUTHs);
657 
658       case AUTHMETHOD_LDAPAUTH:
659          return QUOTE(AUTHMETHOD_LDAPAUTHs);
660 
661       default:
662          return "<unknown>";
663    }
664 
665    /* NOTREACHED */
666 }
667 
668 const char *
proxyprotocol2string(version)669 proxyprotocol2string(version)
670    int version;
671 {
672 
673    switch (version) {
674       case PROXY_SOCKS_V4:
675          return QUOTE(PROXY_SOCKS_V4s);
676 
677       case PROXY_SOCKS_V5:
678          return QUOTE(PROXY_SOCKS_V5s);
679 
680       case PROXY_HTTP_10:
681          return QUOTE(PROXY_HTTP_10s);
682 
683       case PROXY_HTTP_11:
684          return QUOTE(PROXY_HTTP_11s);
685 
686       case PROXY_UPNP:
687          return QUOTE(PROXY_UPNPs);
688 
689       case PROXY_DIRECT:
690          return QUOTE(PROXY_DIRECTs);
691 
692       default:
693          SERRX(version);
694    }
695 
696    /* NOTREACHED */
697 }
698 
699 char *
methods2string(methodc,methodv,str,strsize)700 methods2string(methodc, methodv, str, strsize)
701    size_t methodc;
702    const int methodv[];
703    char *str;
704    size_t strsize;
705 {
706    size_t strused;
707    size_t i;
708 
709    if (strsize == 0) {
710       static char buf[512];
711 
712       str     = buf;
713       strsize = sizeof(buf);
714    }
715 
716    *str    = NUL;
717    strused = 0;
718 
719    for (i = 0; i < methodc; ++i)
720       strused += snprintf(&str[strused], strsize - strused,
721                           "%s, ", method2string(methodv[i]));
722 
723    STRIPTRAILING(str, strused, stripstring);
724    return str;
725 }
726 
727 int
string2method(methodname)728 string2method(methodname)
729    const char *methodname;
730 {
731    struct {
732       char   *methodname;
733       int    method;
734    } method[] = {
735       { AUTHMETHOD_NONEs,         AUTHMETHOD_NONE         },
736       { AUTHMETHOD_UNAMEs,        AUTHMETHOD_UNAME        },
737       { AUTHMETHOD_GSSAPIs,       AUTHMETHOD_GSSAPI       },
738       { AUTHMETHOD_RFC931s,       AUTHMETHOD_RFC931       },
739       { AUTHMETHOD_PAM_ANYs,      AUTHMETHOD_PAM_ANY      },
740       { AUTHMETHOD_PAM_ADDRESSs,  AUTHMETHOD_PAM_ADDRESS  },
741       { AUTHMETHOD_PAM_USERNAMEs, AUTHMETHOD_PAM_USERNAME },
742       { AUTHMETHOD_BSDAUTHs,      AUTHMETHOD_BSDAUTH      },
743       { AUTHMETHOD_LDAPAUTHs,     AUTHMETHOD_LDAPAUTH     }
744    };
745    size_t i;
746 
747    for (i = 0; i < ELEMENTS(method); ++i)
748       if (strcmp(method[i].methodname, methodname) == 0)
749          return method[i].method;
750 
751    return -1;
752 }
753 
754 char *
sockshost2string2(host,includeinfo,string,len)755 sockshost2string2(host, includeinfo, string, len)
756    const sockshost_t *host;
757    const size_t includeinfo;
758    char *string;
759    size_t len;
760 {
761    size_t lenused;
762    char visbuf[sizeof(*host) * 4];
763 
764    if (string == NULL || len == 0) {
765       static char hstr[sizeof(visbuf)];
766 
767       string = hstr;
768       len    = sizeof(hstr);
769    }
770 
771    lenused = 0;
772 
773    if (includeinfo & ADDRINFO_ATYPE)
774       lenused += snprintf(&string[lenused], len - lenused, "%s ",
775                           atype2string(host->atype));
776 
777    switch (host->atype) {
778       case SOCKS_ADDR_IPV4: {
779          char b[MAX(INET_ADDRSTRLEN, 32)];
780 
781          if (inet_ntop(AF_INET, &host->addr.ipv4, b, sizeof(b)) == NULL)
782             STRCPY_ASSERTSIZE(b, "<nonsense address>");
783 
784          lenused += snprintf(&string[lenused], len - lenused, "%s", b);
785          break;
786       }
787 
788       case SOCKS_ADDR_IPV6: {
789          char b[MAX(INET6_ADDRSTRLEN, 32)];
790 
791          if (inet_ntop(AF_INET6, &host->addr.ipv6, b, sizeof(b)) == NULL)
792             STRCPY_ASSERTSIZE(b, "<nonsense address>");
793 
794          lenused += snprintf(&string[lenused], len - lenused, "%s", b);
795          break;
796       }
797 
798       case SOCKS_ADDR_DOMAIN:
799          lenused += snprintf(&string[lenused], len - lenused, "%s",
800                              str2vis(host->addr.domain,
801                                      strlen(host->addr.domain),
802                                      visbuf,
803                                      sizeof(visbuf)));
804          break;
805 
806       case SOCKS_ADDR_IFNAME:
807          lenused += snprintf(&string[lenused], len - lenused, "%s",
808                              str2vis(host->addr.ifname,
809                                       strlen(host->addr.ifname),
810                                       visbuf,
811                                       sizeof(visbuf)));
812          break;
813 
814       case SOCKS_ADDR_URL:
815          lenused += snprintf(&string[lenused], len - lenused, "%s",
816                              str2vis(host->addr.urlname,
817                                      strlen(host->addr.urlname),
818                                      visbuf,
819                                      sizeof(visbuf)));
820          break;
821 
822       default:
823          SERRX(host->atype);
824    }
825 
826    if (includeinfo & ADDRINFO_PORT) {
827       switch (host->atype) {
828          case SOCKS_ADDR_IPV4:
829          case SOCKS_ADDR_IPV6:
830          case SOCKS_ADDR_DOMAIN:
831             lenused += snprintf(&string[lenused], len - lenused,
832                                 ".%d", ntohs(host->port));
833             break;
834       }
835    }
836 
837    return string;
838 }
839 
840 char *
sockshost2string(host,string,len)841 sockshost2string(host, string, len)
842    const sockshost_t *host;
843    char *string;
844    size_t len;
845 {
846 
847    return sockshost2string2(host, ADDRINFO_PORT, string, len);
848 }
849 
850 char *
sockaddr2string(addr,string,len)851 sockaddr2string(addr, string, len)
852    const struct sockaddr_storage *addr;
853    char *string;
854    size_t len;
855 {
856    if (string == NULL || len == 0) {
857       static char addrstring[MAXSOCKADDRSTRING];
858 
859       string = addrstring;
860       len    = sizeof(addrstring);
861    }
862 
863 
864    return sockaddr2string2(addr, ADDRINFO_PORT, string, len);
865 }
866 
867 
868 char *
sockaddr2string2(addr,includeinfo,string,len)869 sockaddr2string2(addr, includeinfo, string, len)
870    const struct sockaddr_storage *addr;
871    const size_t includeinfo;
872    char *string;
873    size_t len;
874 {
875    size_t lenused = 0;
876 
877    if (string == NULL || len == 0) {
878       static char addrstring[MAX(MAXSOCKADDRSTRING, 256)];
879 
880       string = addrstring;
881       len    = sizeof(addrstring);
882    }
883 
884    if (includeinfo & ADDRINFO_ATYPE)
885       lenused += snprintf(&string[lenused], len - lenused, "%s ",
886                           safamily2string(addr->ss_family));
887 
888    switch (addr->ss_family) {
889       case AF_INET:
890       case AF_INET6: {
891          if (inet_ntop(addr->ss_family,
892                        GET_SOCKADDRADDR(addr),
893                        &string[lenused],
894                        len - lenused) != NULL) {
895             if (addr->ss_family == AF_INET6
896             &&  includeinfo & ADDRINFO_SCOPEID
897             &&  TOCIN6(addr)->sin6_scope_id != 0) {
898                lenused = strlen(string);
899 
900                snprintf(&string[lenused], len - lenused,
901                          "%u", (unsigned int)TOCIN6(addr)->sin6_scope_id);
902             }
903 
904             if (includeinfo & ADDRINFO_PORT) {
905                lenused = strlen(string);
906 
907                snprintf(&string[lenused], len - lenused,
908                         ".%d", ntohs(GET_SOCKADDRPORT(addr)));
909             }
910          }
911          else {
912             char addrstr[MAXSOCKADDRSTRING];
913 
914             switch (addr->ss_family) {
915                case AF_INET:
916                   snprintf(addrstr, sizeof(addrstr),
917                            "0x%x", TOCIN(addr)->sin_addr.s_addr);
918                   break;
919 
920                case AF_INET6:
921                   snprintf(addrstr, sizeof(addrstr),
922                            IP6_FMTSTR, IP6_ELEMENTS(&TOCIN6(addr)->sin6_addr));
923                   break;
924 
925                default:
926                   SERRX(addr->ss_family);
927             }
928 
929             snprintf(string, len,
930                      "<inet_ntop(3) on af %d, addr %s, failed: %s>",
931                      addr->ss_family,
932                      strerror(errno),
933                      addrstr);
934 
935             errno = 0;
936          }
937 
938          break;
939       }
940 
941       default:
942          snprintf(string, len, "<undecoded af %d>", addr->ss_family);
943    }
944 
945    return string;
946 }
947 
948 char *
addr2hexstring(addr,safamily,string,len)949 addr2hexstring(addr, safamily, string, len)
950    const void *addr;
951    const sa_family_t safamily;
952    char *string;
953    size_t len;
954 {
955    if (string == NULL || len == 0) {
956       static char stringmem[sizeof(IP6_FMTSTR)];
957 
958       string = stringmem;
959       len    = sizeof(stringmem);
960    }
961 
962    switch (safamily) {
963       case AF_INET:
964          snprintf(string, len, "0x%x", ((const struct in_addr *)addr)->s_addr);
965          break;
966 
967       case AF_INET6:
968          snprintf(string, len,
969                   IP6_FMTSTR,
970                   IP6_ELEMENTS(((const struct in6_addr *)addr)));
971          break;
972 
973       default:
974          SERRX(safamily);
975    }
976 
977    return string;
978 }
979 
980 udpheader_t *
string2udpheader(data,len,header)981 string2udpheader(data, len, header)
982    const char *data;
983    size_t len;
984    udpheader_t *header;
985 {
986 
987    bzero(header, sizeof(*header));
988 
989    if (len < MINSOCKSUDPHLEN)
990       return NULL;
991 
992    if (len < sizeof(header->flag))
993       return NULL;
994 
995    memcpy(&header->flag, data, sizeof(header->flag));
996    data += sizeof(header->flag);
997    len -= sizeof(header->flag);
998 
999    if (len < sizeof(header->frag))
1000       return NULL;
1001 
1002    memcpy(&header->frag, data, sizeof(header->frag));
1003    data += sizeof(header->frag);
1004    len  -= sizeof(header->frag);
1005 
1006    if (mem2sockshost(&header->host,
1007                      (const unsigned char *)data,
1008                      len,
1009                      PROXY_SOCKS_V5) == NULL) {
1010       bzero(header, sizeof(*header));
1011       return NULL;
1012    }
1013 
1014    return header;
1015 }
1016 
1017 char *
extensions2string(extensions,str,strsize)1018 extensions2string(extensions, str, strsize)
1019    const extension_t *extensions;
1020    char *str;
1021    size_t strsize;
1022 {
1023    size_t strused;
1024 
1025    if (strsize == 0) {
1026       static char buf[16];
1027 
1028       str = buf;
1029       strsize = sizeof(buf);
1030    }
1031 
1032    *str    = NUL;
1033    strused = 0;
1034 
1035    if (extensions->bind)
1036       strused += snprintf(&str[strused], strsize - strused, "%s, ",
1037       QUOTE("bind"));
1038 
1039    STRIPTRAILING(str, strused, stripstring);
1040    return str;
1041 }
1042 
1043 char *
str2upper(string)1044 str2upper(string)
1045    char *string;
1046 {
1047 
1048    while (*string != NUL) {
1049       *string = (char)toupper(*string);
1050       ++string;
1051    }
1052 
1053    return string;
1054 }
1055 
1056 char *
sockname2string(s,buf,buflen)1057 sockname2string(s, buf, buflen)
1058    const int s;
1059    char *buf;
1060    size_t buflen;
1061 {
1062    const char *function = "sockname2string()";
1063    struct sockaddr_storage addr;
1064    socklen_t len;
1065 
1066    if (s == -1)
1067       return NULL;
1068 
1069    if (buflen == 0) {
1070       static char sbuf[256];
1071 
1072       buf    = sbuf;
1073       buflen = sizeof(sbuf);
1074    }
1075 
1076    len = sizeof(addr);
1077    if (getsockname(s, TOSA(&addr), &len) == -1) {
1078       slog(LOG_DEBUG, "%s: getsockname(2) on fd %d failed: %s",
1079            function, s, strerror(errno));
1080 
1081       return NULL;
1082    }
1083 
1084    sockaddr2string(&addr, buf, buflen);
1085 
1086    return buf;
1087 }
1088 
1089 char *
peername2string(s,buf,buflen)1090 peername2string(s, buf, buflen)
1091    const int s;
1092    char *buf;
1093    size_t buflen;
1094 {
1095    const char *function = "peername2string()";
1096    struct sockaddr_storage addr;
1097    socklen_t len;
1098 
1099    if (s == -1)
1100       return NULL;
1101 
1102    if (buflen == 0) {
1103       static char sbuf[256];
1104 
1105       buf    = sbuf;
1106       buflen = sizeof(sbuf);
1107    }
1108 
1109    len = sizeof(addr);
1110    if (getpeername(s, TOSA(&addr), &len) == -1) {
1111       slog(LOG_DEBUG, "%s: getpeername(2) on fd %d failed: %s",
1112            function, s, strerror(errno));
1113 
1114       return NULL;
1115    }
1116 
1117    sockaddr2string(&addr, buf, buflen);
1118 
1119    return buf;
1120 }
1121 
1122 char *
socket2string(s,buf,buflen)1123 socket2string(s, buf, buflen)
1124    const int s;
1125    char *buf;
1126    size_t buflen;
1127 {
1128    const char *function = "socket2string()";
1129    const int errno_s = errno;
1130    socklen_t len;
1131    char src[MAXSOCKADDRSTRING], dst[MAXSOCKADDRSTRING], *protocol;
1132    int val;
1133 
1134    if (buflen == 0) {
1135       static char sbuf[256];
1136 
1137       buf    = sbuf;
1138       buflen = sizeof(sbuf);
1139    }
1140 
1141    if (sockname2string(s, src, sizeof(src)) == NULL)
1142       *src = NUL;
1143 
1144    if (peername2string(s, dst, sizeof(dst)) == NULL)
1145       *dst = NUL;
1146 
1147    len = sizeof(val);
1148    if (getsockopt(s, SOL_SOCKET, SO_TYPE, &val, &len) == -1)
1149       protocol = NULL;
1150    else
1151       switch (val) {
1152          case SOCK_DGRAM:
1153             protocol = PROTOCOL_UDPs;
1154             break;
1155 
1156          case SOCK_STREAM:
1157             protocol = PROTOCOL_TCPs;
1158             break;
1159 
1160          default:
1161             protocol = "unknown";
1162       }
1163 
1164    snprintf(buf, buflen,
1165             "laddr: %s, raddr: %s, protocol: %s",
1166             *src     == NUL  ? "N/A" : src,
1167             *dst     == NUL  ? "N/A" : dst,
1168             protocol == NULL ? "N/A" : protocol);
1169 
1170    errno = errno_s;
1171    return buf;
1172 }
1173 
1174 const char *
atype2string(atype)1175 atype2string(atype)
1176    const unsigned int atype;
1177 {
1178 
1179    switch (atype) {
1180       case SOCKS_ADDR_IPV4:
1181          return "IPv4 address";
1182 
1183       case SOCKS_ADDR_IPV6:
1184          return "IPv6 address";
1185 
1186       case SOCKS_ADDR_IPVANY:
1187          return "<IPvAny> address";
1188 
1189       case SOCKS_ADDR_IFNAME:
1190          return "interfacename";
1191 
1192       case SOCKS_ADDR_DOMAIN:
1193          return "host/domain-name";
1194 
1195       case SOCKS_ADDR_URL:
1196          return "url";
1197 
1198       default:
1199          SERRX(atype);
1200    }
1201 
1202    /* NOTREACHED */
1203 }
1204 
1205 const char *
safamily2string(af)1206 safamily2string(af)
1207    const sa_family_t af;
1208 {
1209 
1210    switch (af) {
1211       case AF_INET:
1212          return atype2string(SOCKS_ADDR_IPV4);
1213 
1214       case AF_INET6:
1215          return atype2string(SOCKS_ADDR_IPV6);
1216 
1217       case AF_UNSPEC:
1218          return "AF_UNSPEC";
1219 
1220       case AF_LOCAL:
1221          return "AF_LOCAL";
1222 
1223       default: {
1224          static char buf[sizeof("unknown socket address family: 65535")];
1225 
1226          snprintf(buf, sizeof(buf), "<unknown socket address family: %d>", af);
1227          return buf;
1228       }
1229    }
1230 
1231    /* NOTREACHED */
1232 }
1233 
1234 const char *
socktype2string(socktype)1235 socktype2string(socktype)
1236    const int socktype;
1237 {
1238 
1239    switch (socktype) {
1240       case SOCK_STREAM:
1241          return "SOCK_STREAM";
1242 
1243       case SOCK_DGRAM:
1244          return "SOCK_DGRAM";
1245 
1246       default:
1247          return "<UNKNOWN>";
1248    }
1249 
1250    /* NOTREACHED */
1251 }
1252 
1253 char *
ltoa(l,buf,buflen)1254 ltoa(l, buf, buflen)
1255    long l;
1256    char *buf;
1257    size_t buflen;
1258 {
1259    char *p;
1260    size_t bufused;
1261    int add_minus;
1262 
1263    if (buf == NULL || buflen == 0) {
1264       /* for a 64 bits integer. */
1265       static char bufmem[(sizeof("-") - 1) + sizeof("18446744073709551616")];
1266 
1267       buf    = bufmem;
1268       buflen = sizeof(bufmem);
1269    }
1270    else if (buflen == 1) {
1271       *buf = NUL;
1272       return buf;
1273    }
1274 
1275    p  = &buf[buflen - 1]; /* start at end and go backwards. */
1276    *p = NUL;
1277 
1278    if (l < 0) {
1279       l         = -l;
1280       add_minus = 1;
1281    }
1282    else
1283       add_minus = 0;
1284 
1285    do {
1286       *(--p)  = (char)((l % 10) + '0');
1287       l      /= 10;
1288    } while (l != 0 && p > buf);
1289 
1290    if (l != 0
1291    || (p == buf && add_minus)) { /* buf too small / number too large. */
1292       SASSERTX(p == buf);
1293 
1294       errno = ERANGE;
1295       *buf  = NUL;
1296 
1297       return buf;
1298    }
1299 
1300    if (add_minus)
1301       *(--p) = '-';
1302 
1303    bufused = (&buf[buflen - 1] - p) + 1;
1304    SASSERTX(p + (bufused - 1) <= &buf[buflen - 1]);
1305 
1306    memmove(buf, p, bufused);
1307    SASSERTX(buf[bufused - 1] == NUL);
1308 
1309    return buf;
1310 }
1311 
1312 #if HAVE_GSSAPI
1313 const char *
gssapiprotection2string(protection)1314 gssapiprotection2string(protection)
1315    const int protection;
1316 {
1317    switch (protection) {
1318       case SOCKS_GSSAPI_CLEAR:
1319          return "clear";
1320 
1321       case SOCKS_GSSAPI_INTEGRITY:
1322          return "integrity";
1323 
1324       case SOCKS_GSSAPI_CONFIDENTIALITY:
1325          return "confidentiality";
1326 
1327       case SOCKS_GSSAPI_PERMESSAGE:
1328          return "per-message";
1329    }
1330 
1331    return "unknown gssapi protection";
1332 }
1333 #endif /* HAVE_GSSAPI */
1334 
1335 char *
routeoptions2string(options,str,strsize)1336 routeoptions2string(options, str, strsize)
1337    const routeoptions_t *options;
1338    char *str;
1339    size_t strsize;
1340 {
1341    size_t strused;
1342 
1343    if (strsize == 0) {
1344       static char buf[512];
1345 
1346       str = buf;
1347       strsize = sizeof(buf);
1348    }
1349 
1350    *str    = NUL;
1351    strused = 0;
1352 
1353    strused += snprintf(&str[strused], strsize - strused,
1354                        "\"badexpire: %lu\", ",
1355                        (long)options->badexpire);
1356 
1357    strused += snprintf(&str[strused], strsize - strused,
1358                        "\"maxfail: %lu\"",
1359                        (unsigned long)options->maxfail);
1360 
1361    return str;
1362 }
1363 
1364 char *
logtypes2string(logtypes,str,strsize)1365 logtypes2string(logtypes, str, strsize)
1366    const logtype_t *logtypes;
1367    char *str;
1368    size_t strsize;
1369 {
1370    size_t strused;
1371    size_t i;
1372 
1373    if (strsize == 0) {
1374       static char buf[512];
1375 
1376       str = buf;
1377       strsize = sizeof(buf);
1378    }
1379 
1380    *str    = NUL;
1381    strused = 0;
1382 
1383    if (logtypes->type & LOGTYPE_SYSLOG)
1384       strused += snprintf(&str[strused], strsize - strused, "\"syslog.%s\", ",
1385       logtypes->facilityname);
1386 
1387    if (logtypes->type & LOGTYPE_FILE)
1388       for (i = 0; i < logtypes->filenoc; ++i)
1389          strused += snprintf(&str[strused], strsize - strused, "\"%s\", ",
1390          logtypes->fnamev[i]);
1391 
1392    STRIPTRAILING(str, strused, stripstring);
1393    return str;
1394 }
1395 
1396 const char *
loglevel2string(loglevel)1397 loglevel2string(loglevel)
1398    const int loglevel;
1399 {
1400 
1401    switch (loglevel) {
1402       case LOG_EMERG:
1403          return "emergency";
1404 
1405       case LOG_ALERT:
1406          return "alert";
1407 
1408       case LOG_CRIT:
1409          return "critical";
1410 
1411       case LOG_ERR:
1412          return "error";
1413 
1414       case LOG_WARNING:
1415          return "warning";
1416 
1417       case LOG_NOTICE:
1418          return "notice";
1419 
1420       case LOG_INFO:
1421          return "info";
1422 
1423       case LOG_DEBUG:
1424          return "debug";
1425 
1426       default:
1427          SWARNX(loglevel);
1428          return "unknown loglevel";
1429    }
1430 }
1431 
1432 const char *
signal2string(sig)1433 signal2string(sig)
1434    const int sig;
1435 {
1436 
1437    switch (sig) {
1438 #ifdef SIGABRT
1439       case SIGABRT:
1440          return "SIGABRT";
1441 #endif /* SIGABRT */
1442 
1443 #ifdef SIGALRM
1444       case SIGALRM:
1445          return "SIGALRM";
1446 #endif /* SIGALRM */
1447 
1448 #ifdef SIGBUS
1449       case SIGBUS:
1450          return "SIGBUS";
1451 #endif /* SIGBUS */
1452 
1453 #ifdef SIGCANCEL
1454       case SIGCANCEL:
1455          return "SIGCANCEL";
1456 #endif /* SIGCANCEL */
1457 
1458 #ifdef SIGCHLD
1459       case SIGCHLD:
1460          return "SIGCHLD";
1461 #endif /* SIGCHLD */
1462 
1463 #if (defined SIGCLD) && SIGCLD != SIGCHLD
1464       case SIGCLD:
1465          return "SIGCLD";
1466 #endif /* SIGCLD */
1467 
1468 #ifdef SIGCONT
1469       case SIGCONT:
1470          return "SIGCONT";
1471 #endif /* SIGCONT */
1472 
1473 #ifdef SIGEMT
1474       case SIGEMT:
1475          return "SIGEMT";
1476 #endif /* SIGEMT */
1477 
1478 #ifdef SIGFPE
1479       case SIGFPE:
1480          return "SIGFPE";
1481 #endif /* SIGFPE */
1482 
1483 #ifdef SIGFREEZE
1484       case SIGFREEZE:
1485          return "SIGFREEZE";
1486 #endif /* SIGFREEZE */
1487 
1488 #ifdef SIGHUP
1489       case SIGHUP:
1490          return "SIGHUP";
1491 #endif /* SIGHUP */
1492 
1493 #ifdef SIGILL
1494       case SIGILL:
1495          return "SIGILL";
1496 #endif /* SIGILL */
1497 
1498 #ifdef SIGINFO
1499       case SIGINFO:
1500          return "SIGINFO";
1501 #endif /* SIGINFO */
1502 
1503 #ifdef SIGINT
1504       case SIGINT:
1505          return "SIGINT";
1506 #endif /* SIGINT */
1507 
1508 #ifdef SIGIO
1509       case SIGIO:
1510          return "SIGIO";
1511 #endif /* SIGIO */
1512 
1513 #if (defined SIGIOT) && SIGIOT != SIGABRT
1514       case SIGIOT:
1515          return "SIGIOT";
1516 #endif /* SIGIOT && SIGIOT != SIGABRT */
1517 
1518 #ifdef SIGJVM1
1519       case SIGJVM1:
1520          return "SIGJVM1";
1521 #endif /* SIGJVM1 */
1522 
1523 #ifdef SIGJVM2
1524       case SIGJVM2:
1525          return "SIGJVM2";
1526 #endif /* SIGJVM2 */
1527 
1528 #ifdef SIGKILL
1529       case SIGKILL:
1530          return "SIGKILL";
1531 #endif /* SIGKILL */
1532 
1533 #if (defined SIGLOST) && (!defined SIGABRT || SIGLOST != SIGABRT)
1534       case SIGLOST:
1535          return "SIGLOST";
1536 #endif /* SIGLOST */
1537 
1538 #if (defined SIGLWP) && (!defined SIGTHR || SIGLWP != SIGTHR)
1539       case SIGLWP:
1540          return "SIGLWP";
1541 #endif /* SIGLWP */
1542 
1543 #ifdef SIGPIPE
1544       case SIGPIPE:
1545          return "SIGPIPE";
1546 #endif /* SIGPIPE */
1547 
1548 #if (defined SIGPOLL) && SIGPOLL != SIGIO
1549       case SIGPOLL:
1550          return "SIGPOLL";
1551 #endif /* SIGPOLL */
1552 
1553 #ifdef SIGPROF
1554       case SIGPROF:
1555          return "SIGPROF";
1556 #endif /* SIGPROF */
1557 
1558 #ifdef SIGPWR
1559       case SIGPWR:
1560          return "SIGPWR";
1561 #endif /* SIGPWR */
1562 
1563 #ifdef SIGQUIT
1564       case SIGQUIT:
1565          return "SIGQUIT";
1566 #endif /* SIGQUIT */
1567 
1568 #ifdef SIGSEGV
1569       case SIGSEGV:
1570          return "SIGSEGV";
1571 #endif /* SIGSEGV */
1572 
1573 #ifdef SIGSTKFLT
1574       case SIGSTKFLT:
1575          return "SIGSTKFLT";
1576 #endif /* SIGSTKFLT */
1577 
1578 #ifdef SIGSTOP
1579       case SIGSTOP:
1580          return "SIGSTOP";
1581 #endif /* SIGSTOP */
1582 
1583 #ifdef SIGSYS
1584       case SIGSYS:
1585          return "SIGSYS";
1586 #endif /* SIGSYS */
1587 
1588 #ifdef SIGTERM
1589       case SIGTERM:
1590          return "SIGTERM";
1591 #endif /* SIGTERM */
1592 
1593 #ifdef SIGTHAW
1594       case SIGTHAW:
1595          return "SIGTHAW";
1596 #endif /* SIGTHAW */
1597 
1598 #ifdef SIGTHR
1599       case SIGTHR:
1600          return "SIGTHR";
1601 #endif /* SIGTHR */
1602 
1603 #ifdef SIGTRAP
1604       case SIGTRAP:
1605          return "SIGTRAP";
1606 #endif /* SIGTRAP */
1607 
1608 #ifdef SIGTSTP
1609       case SIGTSTP:
1610          return "SIGTSTP";
1611 #endif /* SIGTSTP */
1612 
1613 #ifdef SIGTTIN
1614       case SIGTTIN:
1615          return "SIGTTIN";
1616 #endif /* SIGTTIN */
1617 
1618 #ifdef SIGTTOU
1619       case SIGTTOU:
1620          return "SIGTTOU";
1621 #endif /* SIGTTOU */
1622 
1623 #ifdef SIGURG
1624       case SIGURG:
1625          return "SIGURG";
1626 #endif /* SIGURG */
1627 
1628 #ifdef SIGUSR1
1629       case SIGUSR1:
1630          return "SIGUSR1";
1631 #endif /* SIGUSR1 */
1632 
1633 #ifdef SIGUSR2
1634       case SIGUSR2:
1635          return "SIGUSR2";
1636 #endif /* SIGUSR2 */
1637 
1638 #ifdef SIGVTALRM
1639       case SIGVTALRM:
1640          return "SIGVTALRM";
1641 #endif /* SIGVTALRM */
1642 
1643 #ifdef SIGWAITING
1644       case SIGWAITING:
1645          return "SIGWAITING";
1646 #endif /* SIGWAITING */
1647 
1648 #ifdef SIGWINCH
1649       case SIGWINCH:
1650          return "SIGWINCH";
1651 #endif /* SIGWINCH */
1652 
1653 #ifdef SIGXCPU
1654       case SIGXCPU:
1655          return "SIGXCPU";
1656 #endif /* SIGXCPU */
1657 
1658 #ifdef SIGXFSZ
1659       case SIGXFSZ:
1660          return "SIGXFSZ";
1661 #endif /* SIGXFSZ */
1662 
1663 #ifdef SIGXRES
1664       case SIGXRES:
1665          return "SIGXRES";
1666 #endif /* SIGXRES */
1667    }
1668 
1669    return "<unknown signal>";
1670 }
1671 
1672 
1673 #undef strerror
1674 const char *
socks_strerror(err)1675 socks_strerror(err)
1676    const int err;
1677 {
1678    const int errno_s = errno;
1679    char *errstr;
1680 
1681    if (sockscf.state.insignal)
1682       return "<cannot retrieve errno string while in signalhandler>";
1683 
1684    if (err == 0)
1685       return "no system error";
1686 
1687    errstr = strerror(err);
1688 
1689    if (errno != errno_s
1690    &&  errno != EINVAL)
1691       /*
1692        * don't expect strerror(3) to change errno normally, but on
1693        * OpenBSD it for some reason can. :-(
1694        */
1695       errno  = errno_s;
1696 
1697    return errstr;
1698 }
1699 
1700 const char *
sockoptval2string(value,type,str,strsize)1701 sockoptval2string(value, type, str, strsize)
1702    socketoptvalue_t value;
1703    socketoptvalue_type_t type;
1704    char *str;
1705    size_t strsize;
1706 {
1707    size_t strused;
1708 
1709    if (strsize == 0) {
1710       static char buf[100];
1711 
1712       str     = buf;
1713       strsize = sizeof(buf);
1714    }
1715 
1716    *str    = NUL;
1717    strused = 0;
1718 
1719    switch (type) {
1720       case int_val:
1721          strused += snprintf(&str[strused], strsize - strused, "%d",
1722                              value.int_val);
1723          break;
1724 
1725       case uchar_val:
1726          strused += snprintf(&str[strused], strsize - strused, "%u",
1727                              (unsigned)value.uchar_val);
1728          break;
1729 
1730       case linger_val:
1731       case timeval_val:
1732       case in_addr_val:
1733       case sockaddr_val:
1734       case ipoption_val:
1735 #if HAVE_TCP_IPA
1736       case option28_val:
1737 #endif /* HAVE_TCP_IPA */
1738 
1739          strused += snprintf(&str[strused], strsize - strused,
1740                              "<value-decoding unimplemented>");
1741          break;
1742 
1743       default:
1744          SERRX(type);
1745    }
1746 
1747    STRIPTRAILING(str, strused, stripstring);
1748    return str;
1749 }
1750 
1751 const char *
sockoptlevel2string(level)1752 sockoptlevel2string(level)
1753    int level;
1754 {
1755 
1756    switch (level) {
1757 #ifdef SOL_SOCKET
1758       case SOL_SOCKET:
1759          return "socket";
1760 #endif /* SOL_SOCKET */
1761 
1762 #ifdef IPPROTO_TCP
1763       case IPPROTO_TCP:
1764          return "tcp";
1765 #endif /* IPPROTO_TCP */
1766 
1767 #ifdef IPPROTO_UDP
1768       case IPPROTO_UDP:
1769          return "udp";
1770 #endif /* IPPROTO_UDP */
1771 
1772 #ifdef IPPROTO_IP
1773       case IPPROTO_IP:
1774          return "ip";
1775 #endif /* IPPROTO_IP */
1776 
1777       default:
1778          SERRX(level);
1779    }
1780 
1781    /* NOTREACHED */
1782 }
1783 
1784 const char *
sockoptvaltype2string(type)1785 sockoptvaltype2string(type)
1786    socketoptvalue_type_t type;
1787 {
1788 
1789    switch (type) {
1790       case int_val:
1791          return "int_val";
1792 
1793       case linger_val:
1794          return "linger_val";
1795 
1796       case timeval_val:
1797          return "timeval_val";
1798 
1799       case in_addr_val:
1800          return "in_addr_val";
1801 
1802       case uchar_val:
1803          return "uchar_val";
1804 
1805       case sockaddr_val:
1806          return "sockaddr_val";
1807 
1808       case ipoption_val:
1809          return "ipoption_val";
1810 #if HAVE_TCP_IPA
1811       case option28_val:
1812          return "option28_val";
1813 #endif /* HAVE_TCP_IPA */
1814 
1815       default:
1816          SERRX(type);
1817    }
1818 
1819    /* NOTREACHED */
1820 }
1821 
1822 const char *
sockopt2string(opt,str,strsize)1823 sockopt2string(opt, str, strsize)
1824    const socketoption_t *opt;
1825    char *str;
1826    size_t strsize;
1827 {
1828    size_t strused;
1829 
1830    if (strsize == 0) {
1831       static char buf[100];
1832 
1833       str     = buf;
1834       strsize = sizeof(buf);
1835    }
1836 
1837    strused = snprintf(str, strsize,
1838                       "%s (%d), level %s (%d), calltype %d, %s-side",
1839                       opt->info == NULL ? "<unknown>" : opt->info->name,
1840                       opt->optname,
1841                       sockoptlevel2string(opt->info == NULL ?
1842                                              opt->level : opt->info->level),
1843                       opt->info == NULL ? opt->level : opt->info->level,
1844                       opt->info == NULL ? -1 : (int)opt->info->calltype,
1845                       opt->info == NULL ?
1846                            "<unknown>" : opt->isinternalside ?
1847                                          "internal" : "external");
1848 
1849 #if 1
1850    strused += snprintf(&str[strused], strsize - strused,
1851                        " value: %s (%s)",
1852                        sockoptval2string(opt->optval, opt->opttype, NULL, 0),
1853                        sockoptvaltype2string(opt->opttype));
1854 #endif
1855 
1856    STRIPTRAILING(str, strused, stripstring);
1857    return str;
1858 }
1859 
1860 
1861 const char *
socketsettime2string(whichtime)1862 socketsettime2string(whichtime)
1863    const int whichtime;
1864 {
1865    const char *function = "socketsettime2string()";
1866 
1867    switch (whichtime) {
1868       case SOCKETOPT_PRE:
1869          return "pre-establishment time";
1870 
1871       case SOCKETOPT_POST:
1872          return "post-establishment time";
1873 
1874       case SOCKETOPT_ANYTIME:
1875          return "any time";
1876    }
1877 
1878    if (whichtime == (SOCKETOPT_PRE | SOCKETOPT_POST))
1879       return "pre/post-establishment time";
1880 
1881    if (whichtime == (SOCKETOPT_PRE | SOCKETOPT_ANYTIME))
1882       return "pre-establishment or any time";
1883 
1884    if (whichtime == (SOCKETOPT_POST | SOCKETOPT_ANYTIME))
1885       return "post-establishment or any time";
1886 
1887    swarnx("%s: unknown value: %d", function, whichtime);
1888    return "<unknown value>";
1889 }
1890 
1891 #if !SOCKS_CLIENT
1892 
1893 const char *
interfaceside2string(side)1894 interfaceside2string(side)
1895    const interfaceside_t side;
1896 {
1897 
1898    switch (side) {
1899       case INTERNALIF:
1900          return "internal/client";
1901 
1902       case EXTERNALIF:
1903          return "external/target";
1904 
1905       default:
1906          SERRX(side);
1907          /* NOTREACHED */
1908    }
1909 
1910 }
1911 
1912 char *
interfaceprotocol2string(ifproto,str,strsize)1913 interfaceprotocol2string(ifproto, str, strsize)
1914    const interfaceprotocol_t *ifproto;
1915    char *str;
1916    size_t strsize;
1917 {
1918 
1919    if (strsize == 0) {
1920       static char buf[1024];
1921 
1922       str     = buf;
1923       strsize = sizeof(buf);
1924    }
1925 
1926    snprintf(str, strsize, "%s: %s, %s: %s",
1927             safamily2string(AF_INET),  ifproto->ipv4 ? "yes" : "no",
1928             safamily2string(AF_INET6), ifproto->ipv6 ? "yes" : "no");
1929 
1930 
1931    return str;
1932 }
1933 
1934 
1935 char *
networktest2string(test,str,strsize)1936 networktest2string(test, str, strsize)
1937    const networktest_t *test;
1938    char *str;
1939    size_t strsize;
1940 {
1941 
1942    if (strsize == 0) {
1943       static char buf[1024];
1944 
1945       str     = buf;
1946       strsize = sizeof(buf);
1947    }
1948 
1949    snprintf(str, strsize, "mtu.dotest: %d", test->mtu.dotest);
1950 
1951    return str;
1952 }
1953 
1954 const char *
addrscope2string(scope)1955 addrscope2string(scope)
1956    const ipv6_addrscope_t scope;
1957 {
1958    switch (scope) {
1959       case addrscope_global:
1960          return "global";
1961 
1962       case addrscope_linklocal:
1963          return "linklocal";
1964 
1965       case addrscope_nodelocal:
1966          return "nodelocal";
1967    }
1968 
1969    SERRX(scope);
1970    /* NOTREACHED */
1971 }
1972 
1973 const char *
alarmside2string(alarmside)1974 alarmside2string(alarmside)
1975    const size_t alarmside;
1976 {
1977 
1978    switch (alarmside) {
1979       case ALARM_INTERNAL:
1980          return "internal";
1981 
1982       case ALARM_INTERNAL_RECV:
1983          return "internal.recv";
1984 
1985       case ALARM_INTERNAL_SEND:
1986          return "internal.send";
1987 
1988       case ALARM_EXTERNAL:
1989          return "external";
1990 
1991       case ALARM_EXTERNAL_RECV:
1992          return "external.recv";
1993 
1994       case ALARM_EXTERNAL_SEND:
1995          return "external.send";
1996 
1997       case ALARM_RECV:
1998          return "recv";
1999 
2000       case ALARM_SEND:
2001          return "send";
2002 
2003       default:
2004          SERRX(alarmside);
2005    }
2006 }
2007 
2008 const char *
clientinfo2string(cinfo,str,strsize)2009 clientinfo2string(cinfo, str, strsize)
2010    const clientinfo_t *cinfo;
2011    char *str;
2012    size_t strsize;
2013 {
2014    const char *function = "clientinfo2string()";
2015    size_t strused;
2016 
2017    if (strsize == 0) {
2018       static char buf[1024];
2019 
2020       str     = buf;
2021       strsize = sizeof(buf);
2022    }
2023 
2024    strused = 0;
2025 
2026 #if HAVE_SOCKS_HOSTID
2027 {
2028    size_t i;
2029 
2030    for (i = 0; i < (size_t)cinfo->hostidc; ++i) {
2031       char ntop[MAXSOCKADDRSTRING];
2032 
2033       if (inet_ntop(AF_INET, &cinfo->hostidv[i], ntop, sizeof(ntop)) == NULL) {
2034          slog(LOG_DEBUG, "%s: inet_ntop(3) failed on %s %x: %s",
2035               function,
2036               atype2string(SOCKS_ADDR_IPV4),
2037               cinfo->hostidv[i].s_addr,
2038               strerror(errno));
2039 
2040          snprintf(ntop, sizeof(ntop), "<unknown>");
2041          errno = 0;
2042       }
2043 
2044       strused += snprintf(&str[strused], strsize - strused, "[%s] ", ntop);
2045    }
2046 }
2047 #endif /* HAVE_SOCKS_HOSTID */
2048 
2049    strused += snprintf(&str[strused], strsize - strused, "%s",
2050                        sockaddr2string(&cinfo->from, NULL, 0));
2051 
2052    return str;
2053 }
2054 
2055 const char *
statekey2string(key)2056 statekey2string(key)
2057    const statekey_t key;
2058 {
2059 
2060    switch (key) {
2061       case key_unset:
2062          return "unset";
2063 
2064       case key_from:
2065          return "from (client IP-address)";
2066 
2067       case key_hostid:
2068          return "hostid (client hostid)";
2069 
2070       default:
2071          SERRX(key);
2072    }
2073 
2074    /* NOTREACHED */
2075 }
2076 
2077 statekey_t
string2statekey(string)2078 string2statekey(string)
2079    const char *string;
2080 {
2081 
2082    if (strcmp(string, "from") == 0)
2083       return key_from;
2084    else if (strcmp(string, "hostid") == 0)
2085       return key_hostid;
2086 
2087    return key_unset;
2088 }
2089 
2090 const char *
objecttype2string(type)2091 objecttype2string(type)
2092    const objecttype_t type;
2093 {
2094 
2095    switch (type) {
2096       case object_sockaddr:
2097          return "sockaddr";
2098 
2099       case object_sockshost:
2100          return "sockshost";
2101 
2102       case object_crule:
2103          return "client-rule";
2104 
2105 #if HAVE_SOCKS_HOSTID
2106       case object_hrule:
2107          return "hostid-rule";
2108 #endif /* HAVE_SOCKS_HOSTID */
2109 
2110       case object_srule:
2111          return "socks-rule";
2112 
2113       case object_monitor:
2114          return "monitor";
2115 
2116       default:
2117          SERRX(type);
2118    }
2119 
2120    /* NOTREACHED */
2121    return NULL;
2122 }
2123 
2124 
2125 char *
options2string(options,prefix,str,strsize)2126 options2string(options, prefix, str, strsize)
2127    const option_t *options;
2128    const char *prefix;
2129    char *str;
2130    size_t strsize;
2131 {
2132    size_t strused;
2133 
2134    if (strsize == 0) {
2135       static char buf[1024];
2136 
2137       str = buf;
2138       strsize = sizeof(buf);
2139    }
2140 
2141    *str    = NUL;
2142    strused = 0;
2143 
2144    strused += snprintf(&str[strused], strsize - strused,
2145                        "\"%sdaemon\": \"%d\",\n",
2146                        prefix, options->daemon);
2147 
2148    strused += snprintf(&str[strused], strsize - strused,
2149                        "\"%sservercount\": \"%lu\",\n",
2150                        prefix, (unsigned long)options->serverc);
2151 
2152    strused += snprintf(&str[strused], strsize - strused,
2153                        "\"%sverifyonly\": \"%s\",\n",
2154                        prefix, options->verifyonly ? "yes" : "no");
2155 
2156    strused += snprintf(&str[strused], strsize - strused,
2157                        "\"%sdebug\": \"%d\",\n",
2158                        prefix, options->debug);
2159 
2160    strused += snprintf(&str[strused], strsize - strused,
2161                        "\"%sconfigfile\": \"%s\",\n",
2162                        prefix,
2163                        options->configfile == NULL ?
2164                           SOCKD_CONFIGFILE : options->configfile);
2165 
2166    strused += snprintf(&str[strused], strsize - strused,
2167                        "\"%sdebuglevel\": \"%d\",\n",
2168                        prefix, options->debug);
2169 
2170    strused += snprintf(&str[strused], strsize - strused,
2171                        "\"%skeepalive\": \"%d\",\n",
2172                        prefix, options->keepalive);
2173 
2174    strused += snprintf(&str[strused], strsize - strused,
2175                        "\"%spidfile\": \"%s\",\n",
2176                        prefix,
2177                        options->pidfile == NULL ?
2178                           SOCKD_PIDFILE : options->pidfile);
2179 
2180    STRIPTRAILING(str, strused, stripstring);
2181    return str;
2182 }
2183 
2184 char *
logs2string(logs,str,strsize)2185 logs2string(logs, str, strsize)
2186    const log_t *logs;
2187    char *str;
2188    size_t strsize;
2189 {
2190    size_t strused;
2191 
2192    if (strsize == 0) {
2193       static char buf[128];
2194 
2195       str = buf;
2196       strsize = sizeof(buf);
2197    }
2198 
2199    *str    = NUL;
2200    strused = 0;
2201 
2202    if (logs->connect)
2203       strused += snprintf(&str[strused], strsize - strused, "%s, ",
2204       QUOTE(SOCKS_LOG_CONNECTs));
2205 
2206    if (logs->disconnect)
2207       strused += snprintf(&str[strused], strsize - strused, "%s, ",
2208       QUOTE(SOCKS_LOG_DISCONNECTs));
2209 
2210    if (logs->data)
2211       strused += snprintf(&str[strused], strsize - strused, "%s, ",
2212       QUOTE(SOCKS_LOG_DATAs));
2213 
2214    if (logs->error)
2215       strused += snprintf(&str[strused], strsize - strused, "%s, ",
2216       QUOTE(SOCKS_LOG_ERRORs));
2217 
2218    if (logs->iooperation)
2219       strused += snprintf(&str[strused], strsize - strused, "%s, ",
2220       QUOTE(SOCKS_LOG_IOOPERATIONs));
2221 
2222    if (logs->tcpinfo)
2223       strused += snprintf(&str[strused], strsize - strused, "%s, ",
2224       QUOTE(SOCKS_LOG_TCPINFOs));
2225 
2226    STRIPTRAILING(str, strused, stripstring);
2227    return str;
2228 }
2229 
2230 const char *
childtype2string(type)2231 childtype2string(type)
2232    int type;
2233 {
2234 
2235    switch (type) {
2236       case PROC_MOTHER:
2237          return "mother";
2238 
2239       case PROC_MONITOR:
2240          return "monitor-child";
2241 
2242       case PROC_NEGOTIATE:
2243          return "negotiate-child";
2244 
2245       case PROC_REQUEST:
2246          return "request-child";
2247 
2248       case PROC_IO:
2249          return "io-child";
2250 
2251       default:
2252          SERRX(type);
2253    }
2254 
2255    /* NOTREACHED */
2256 }
2257 
2258 const char *
verdict2string(verdict)2259 verdict2string(verdict)
2260    int verdict;
2261 {
2262 
2263    switch (verdict) {
2264       case VERDICT_PASS:
2265          return QUOTE(VERDICT_PASSs);
2266 
2267       case VERDICT_BLOCK:
2268          return QUOTE(VERDICT_BLOCKs);
2269    }
2270 
2271    SERRX(verdict);
2272    /* NOTREACHED */
2273 }
2274 
2275 char *
list2string(list,str,strsize)2276 list2string(list, str, strsize)
2277    const linkedname_t *list;
2278    char *str;
2279    size_t strsize;
2280 {
2281    size_t strused;
2282 
2283    if (strsize)
2284       *str = NUL; /* make sure we return a NUL terminated string. */
2285    else
2286       return str;
2287 
2288    strused = 0;
2289    for (; list != NULL; list = list->next)
2290       strused += snprintf(&str[strused], strsize - strused, "\"%s\", ",
2291                           list->name);
2292 
2293    return str;
2294 }
2295 
2296 char *
compats2string(compats,str,strsize)2297 compats2string(compats, str, strsize)
2298    const compat_t *compats;
2299    char *str;
2300    size_t strsize;
2301 {
2302    size_t strused;
2303 
2304    if (strsize == 0) {
2305       static char buf[32];
2306 
2307       str = buf;
2308       strsize = sizeof(buf);
2309    }
2310 
2311    *str    = NUL;
2312    strused = 0;
2313 
2314    if (compats->sameport)
2315       strused += snprintf(&str[strused], strsize - strused, "%s, ",
2316       QUOTE("sameport"));
2317 
2318    STRIPTRAILING(str, strused, stripstring);
2319    return str;
2320 }
2321 
2322 char *
srchosts2string(srchost,prefix,str,strsize)2323 srchosts2string(srchost, prefix, str, strsize)
2324    const srchost_t *srchost;
2325    const char *prefix;
2326    char *str;
2327    size_t strsize;
2328 {
2329    size_t strused;
2330 
2331    if (strsize == 0) {
2332       static char buf[32];
2333 
2334       str = buf;
2335       strsize = sizeof(buf);
2336    }
2337 
2338    *str    = NUL;
2339    strused = 0;
2340 
2341    if (srchost->nodnsmismatch)
2342       strused += snprintf(&str[strused], strsize - strused,
2343       "\"%snodnsmismatch\", ", prefix);
2344 
2345    if (srchost->nodnsunknown)
2346       strused += snprintf(&str[strused], strsize - strused,
2347       "\"%snodnsunknown\",", prefix);
2348 
2349    STRIPTRAILING(str, strused, stripstring);
2350    return str;
2351 }
2352 
2353 const char *
uid2name(uid)2354 uid2name(uid)
2355    uid_t uid;
2356 {
2357    struct passwd *pw;
2358 
2359    if ((pw = getpwuid(uid)) == NULL)
2360       return NULL;
2361 
2362    return pw->pw_name;
2363 }
2364 
2365 const char *
timeouttype2string(type)2366 timeouttype2string(type)
2367    timeouttype_t type;
2368 {
2369 
2370    switch (type) {
2371       case TIMEOUT_NEGOTIATE:
2372          return "negotiate timeout";
2373 
2374       case TIMEOUT_CONNECT:
2375          return "connect timeout";
2376 
2377       case TIMEOUT_IO:
2378          return "i/o timeout";
2379 
2380       case TIMEOUT_TCP_FIN_WAIT:
2381          return "tcp-fin-wait timeout";
2382 
2383       default:
2384          SERRX(type);
2385    }
2386 
2387    /* NOTREACHED */
2388 }
2389 
2390 char *
timeouts2string(timeouts,prefix,str,strsize)2391 timeouts2string(timeouts, prefix, str, strsize)
2392    const timeout_t *timeouts;
2393    const char *prefix;
2394    char *str;
2395    size_t strsize;
2396 {
2397    size_t strused;
2398 
2399    if (strsize == 0) {
2400       static char buf[64];
2401 
2402       str = buf;
2403       strsize = sizeof(buf);
2404    }
2405 
2406    *str    = NUL;
2407    strused = 0;
2408 
2409    strused += snprintf(&str[strused], strsize - strused,
2410                        "\"%sconnecttimeout\": \"%ld\",\n",
2411                        prefix, (unsigned long)timeouts->negotiate);
2412 
2413    strused += snprintf(&str[strused], strsize - strused,
2414                        "\"%siotimeout\": tcp: \"%lu\", udp: \"%lu\" \n",
2415                        prefix,
2416                        (unsigned long)timeouts->tcpio,
2417                        (unsigned long)timeouts->udpio);
2418 
2419    STRIPTRAILING(str, strused, stripstring);
2420    return str;
2421 }
2422 
2423 const char *
rotation2string(rotation)2424 rotation2string(rotation)
2425    int rotation;
2426 {
2427 
2428    switch (rotation) {
2429       case ROTATION_NONE:
2430          return "none";
2431 
2432       case ROTATION_SAMESAME:
2433          return "same-same";
2434 
2435       case ROTATION_ROUTE:
2436          return "route";
2437 
2438       default:
2439          SERRX(rotation);
2440    }
2441 
2442    /* NOTREACHED */
2443 }
2444 
2445 const char *
privop2string(op)2446 privop2string(op)
2447    const priv_op_t op;
2448 {
2449    switch (op) {
2450       case PRIV_ON:
2451          return "on";
2452 
2453       case PRIV_OFF:
2454          return "off";
2455    }
2456 
2457 
2458    /* NOTREACHED */
2459    SERRX(op);
2460 }
2461 
2462 
2463 
2464 #if HAVE_SCHED_SETAFFINITY
2465 char *
cpuset2string(set,str,strsize)2466 cpuset2string(set, str, strsize)
2467    const cpu_set_t *set;
2468    char *str;
2469    size_t strsize;
2470 {
2471    const size_t setsize = cpu_get_setsize();
2472    size_t i, strused;
2473 
2474    if (strsize == 0) {
2475       static char buf[2048];
2476 
2477       str     = buf;
2478       strsize = sizeof(buf);
2479    }
2480 
2481    *str    = NUL;
2482    strused = 0;
2483 
2484    for (i = 0; i < setsize; ++i)
2485       if (cpu_isset(i, set))
2486          strused += snprintf(&str[strused], strsize - strused, "%ld ", (long)i);
2487 
2488    return str;
2489 }
2490 #endif /* HAVE_SCHED_SETAFFINITY */
2491 
2492 
2493 #if !HAVE_PRIVILEGES
2494 char *
userids2string(userids,prefix,str,strsize)2495 userids2string(userids, prefix, str, strsize)
2496    const userid_t *userids;
2497    const char *prefix;
2498    char *str;
2499    size_t strsize;
2500 {
2501    size_t strused;
2502 
2503    if (strsize == 0) {
2504       static char buf[128];
2505 
2506       str = buf;
2507       strsize = sizeof(buf);
2508    }
2509 
2510    *str    = NUL;
2511    strused = 0;
2512 
2513    strused += snprintf(&str[strused], strsize - strused,
2514                        "\"%sprivileged\": \"%s\",\n",
2515                        prefix, uid2name(userids->privileged_uid));
2516 
2517    strused += snprintf(&str[strused], strsize - strused,
2518                        "\"%sunprivileged\": \"%s\",\n",
2519                        prefix, uid2name(userids->unprivileged_uid));
2520 
2521    strused += snprintf(&str[strused], strsize - strused,
2522                        "\"%slibwrap\": \"%s\",\n",
2523                        prefix, uid2name(userids->libwrap_uid));
2524 
2525    STRIPTRAILING(str, strused, stripstring);
2526    return str;
2527 }
2528 #endif /* !HAVE_PRIVILEGES */
2529 
2530 #if COVENANT
2531 const char *
httpcode2string(version,code)2532 httpcode2string(version, code)
2533    const int version;
2534    const int code;
2535 {
2536    static char prefix[16], buf[64];
2537 
2538    SASSERTX(version == PROXY_HTTP_10
2539    ||       version == PROXY_HTTP_11);
2540 
2541    snprintf(prefix, sizeof(prefix), "HTTP/1.%d %d",
2542    version == PROXY_HTTP_10 ? 0 : 1, code);
2543 
2544    switch (code) {
2545       case HTTP_SUCCESS:
2546          snprintf(buf, sizeof(buf), "%s Success", prefix);
2547          break;
2548 
2549       case HTTP_FORBIDDEN:
2550          snprintf(buf, sizeof(buf), "%s Not allowed", prefix);
2551          break;
2552 
2553       case HTTP_NOTALLOWED:
2554          snprintf(buf, sizeof(buf), "%s Not authorized", prefix);
2555          break;
2556 
2557       case HTTP_PROXYAUTHREQUIRED:
2558          snprintf(buf, sizeof(buf), "%s Not authorized", prefix);
2559          break;
2560 
2561       case HTTP_HOSTUNREACH:
2562          snprintf(buf, sizeof(buf), "%s Not reachable", prefix);
2563          break;
2564 
2565       case HTTP_FAILURE:
2566          snprintf(buf, sizeof(buf), "%s Unknown proxy server error", prefix);
2567          break;
2568 
2569       default:
2570          SERRX(code);
2571    }
2572 
2573    return buf;
2574 }
2575 #endif /* COVENANT */
2576 
2577 #endif /* !SOCKS_CLIENT */
2578