util.c
上传用户:zm130024
上传日期:2007-01-04
资源大小:432k
文件大小:27k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /*
  2.  * Copyright (c) 1997, 1998, 1999
  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.  *  Gaustadal閑n 21
  36.  *  N-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. #include "common.h"
  44. /* XXX */
  45. #if HAVE_STRVIS
  46. #include <vis.h>
  47. #else
  48. #include "compat.h"
  49. #endif  /* HAVE_STRVIS */
  50. static const char rcsid[] =
  51. "$Id: util.c,v 1.98 1999/12/22 09:29:25 karls Exp $";
  52. /* fake "ip address", for clients without dns access. */
  53. static char **ipv;
  54. static in_addr_t ipc;
  55. const char *
  56. strcheck(string)
  57. const char *string;
  58. {
  59. return string == NULL ? NOMEM : string;
  60. }
  61. char *
  62. sockshost2string(host, string, len)
  63. const struct sockshost_t *host;
  64. char *string;
  65. size_t len;
  66. {
  67. if (string == NULL) { /* to ease debugging. */
  68. static char hstring[MAXSOCKSHOSTSTRING];
  69. string = hstring;
  70. len = sizeof(hstring);
  71. }
  72. switch (host->atype) {
  73. case SOCKS_ADDR_IPV4:
  74. snprintf(string, len, "%s.%d",
  75. inet_ntoa(host->addr.ipv4), ntohs(host->port));
  76. break;
  77. case SOCKS_ADDR_IPV6:
  78. snprintf(string, len, "%s.%d",
  79. "<IPV6 address not supported>", ntohs(host->port));
  80. break;
  81. case SOCKS_ADDR_DOMAIN:
  82. snprintf(string, len, "%s.%d",
  83. host->addr.domain, ntohs(host->port));
  84. break;
  85. default:
  86. SERRX(host->atype);
  87. }
  88. return string;
  89. }
  90. const char *
  91. command2string(command)
  92. int command;
  93. {
  94. switch (command) {
  95. case SOCKS_BIND:
  96. return SOCKS_BINDs;
  97. case SOCKS_CONNECT:
  98. return SOCKS_CONNECTs;
  99. case SOCKS_UDPASSOCIATE:
  100. return SOCKS_UDPASSOCIATEs;
  101. /* pseudo commands. */
  102. case SOCKS_ACCEPT:
  103. return SOCKS_ACCEPTs;
  104. case SOCKS_BINDREPLY:
  105. return SOCKS_BINDREPLYs;
  106. case SOCKS_UDPREPLY:
  107. return SOCKS_UDPREPLYs;
  108. case SOCKS_DISCONNECT:
  109. return SOCKS_DISCONNECTs;
  110. default:
  111. SERRX(command);
  112. }
  113. /* NOTREACHED */
  114. }
  115. const char *
  116. method2string(method)
  117. int method;
  118. {
  119. switch (method) {
  120. case AUTHMETHOD_NONE:
  121. return AUTHMETHOD_NONEs;
  122. case AUTHMETHOD_GSSAPI:
  123. return AUTHMETHOD_GSSAPIs;
  124. case AUTHMETHOD_UNAME:
  125. return AUTHMETHOD_UNAMEs;
  126. case AUTHMETHOD_NOACCEPT:
  127. return AUTHMETHOD_NOACCEPTs;
  128. case AUTHMETHOD_RFC931:
  129. return AUTHMETHOD_RFC931s;
  130. default:
  131. SERRX(method);
  132. }
  133. /* NOTREACHED */
  134. }
  135. int
  136. string2method(methodname)
  137. const char *methodname;
  138. {
  139. struct {
  140. char *methodname;
  141. int method;
  142. } method[] = {
  143. { AUTHMETHOD_NONEs, AUTHMETHOD_NONE },
  144. { AUTHMETHOD_UNAMEs, AUTHMETHOD_UNAME },
  145. { AUTHMETHOD_RFC931s, AUTHMETHOD_RFC931 }
  146. };
  147. size_t i;
  148. for (i = 0; i < ELEMENTS(method); ++i)
  149. if (strcmp(method[i].methodname, methodname) == 0)
  150. return method[i].method;
  151. return -1;
  152. }
  153. int
  154. sockscode(version, code)
  155. int version;
  156. int code;
  157. {
  158. switch (version) {
  159. case SOCKS_V4:
  160. case SOCKS_V4REPLY_VERSION:
  161. switch (code) {
  162. case SOCKS_SUCCESS:
  163. return SOCKSV4_SUCCESS;
  164. default:
  165. return SOCKSV4_FAIL; /* v4 is not very specific. */
  166. }
  167. /* NOTREACHED */
  168. case SOCKS_V5:
  169. switch (code) {
  170. default:
  171. return code; /* current codes are all V5. */
  172. }
  173. /* NOTREACHED */
  174. case MSPROXY_V2:
  175. switch (code) {
  176. case SOCKS_SUCCESS:
  177. return MSPROXY_SUCCESS;
  178. case SOCKS_FAILURE:
  179. return MSPROXY_FAILURE;
  180. default:
  181. SERRX(code);
  182. }
  183. /* NOTREACHED */
  184. default:
  185. SERRX(version);
  186. }
  187. /* NOTREACHED */
  188. }
  189. int
  190. errno2reply(errnum, version)
  191. int errnum;
  192. int version;
  193. {
  194. switch (errnum) {
  195. case ENETUNREACH:
  196. return sockscode(version, SOCKS_NETUNREACH);
  197. case EHOSTUNREACH:
  198. return sockscode(version, SOCKS_HOSTUNREACH);
  199. case ECONNREFUSED:
  200. return sockscode(version, SOCKS_CONNREFUSED);
  201. case ETIMEDOUT:
  202. return sockscode(version, SOCKS_TTLEXPIRED);
  203. }
  204. return sockscode(version, SOCKS_FAILURE);
  205. }
  206. struct sockaddr *
  207. sockshost2sockaddr(host, addr)
  208. const struct sockshost_t *host;
  209. struct sockaddr *addr;
  210. {
  211. const char *function = "sockshost2sockaddr()";
  212. bzero(addr, sizeof(*addr));
  213. /* LINTED pointer casts may be troublesome */
  214. ((struct sockaddr_in *)addr)->sin_family = AF_INET;
  215. switch (host->atype) {
  216. case SOCKS_ADDR_IPV4:
  217. /* LINTED pointer casts may be troublesome */
  218. ((struct sockaddr_in *)addr)->sin_addr = host->addr.ipv4;
  219. break;
  220. case SOCKS_ADDR_DOMAIN: {
  221. struct hostent *hostent;
  222. if ((hostent = gethostbyname(host->addr.domain)) == NULL
  223. ||   hostent->h_addr_list == NULL) {
  224. /* LINTED pointer casts may be troublesome */
  225. swarnx("%s: gethostbyname(%s): %s",
  226. function, host->addr.domain, hstrerror(h_errno));
  227. /* LINTED pointer casts may be troublesome */
  228. ((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(INADDR_ANY);
  229. break;
  230. }
  231. /* LINTED pointer casts may be troublesome */
  232. ((struct sockaddr_in *)addr)->sin_addr
  233. = *(struct in_addr *)(*hostent->h_addr_list);
  234. break;
  235. }
  236. default:
  237. SERRX(host->atype);
  238. }
  239. /* LINTED pointer casts may be troublesome */
  240. ((struct sockaddr_in *)addr)->sin_port = host->port;
  241. /* LINTED pointer casts may be troublesome */
  242. return addr;
  243. }
  244. struct sockaddr *
  245. fakesockshost2sockaddr(host, addr)
  246. const struct sockshost_t *host;
  247. struct sockaddr *addr;
  248. {
  249. const char *function = "fakesockshost2sockaddr()";
  250. #if SOCKS_CLIENT /* may be called before normal init, log to right place. */
  251. clientinit();
  252. #endif
  253. slog(LOG_DEBUG, "%s: %s", function, sockshost2string(host, NULL, 0));
  254. bzero(addr, sizeof(*addr));
  255. /* LINTED pointer casts may be troublesome */
  256. ((struct sockaddr_in *)addr)->sin_family = AF_INET;
  257. switch (host->atype) {
  258. case SOCKS_ADDR_DOMAIN:
  259. /* LINTED pointer casts may be troublesome */
  260. if (socks_getfakeip(host->addr.domain,
  261. &((struct sockaddr_in *)addr)->sin_addr)) {
  262. /* LINTED pointer casts may be troublesome */
  263. break;
  264. }
  265. /* else; */ /* FALLTHROUGH */
  266. default:
  267. return sockshost2sockaddr(host, addr);
  268. }
  269. /* LINTED pointer casts may be troublesome */
  270. ((struct sockaddr_in *)addr)->sin_port = host->port;
  271. return addr;
  272. }
  273. struct sockshost_t *
  274. sockaddr2sockshost(addr, host)
  275. const struct sockaddr *addr;
  276. struct sockshost_t *host;
  277. {
  278. switch (addr->sa_family) {
  279. case AF_INET:
  280. host->atype = SOCKS_ADDR_IPV4;
  281. /* LINTED pointer casts may be troublesome */
  282. host->addr.ipv4 = ((const struct sockaddr_in *)addr)->sin_addr;
  283. /* LINTED pointer casts may be troublesome */
  284. host->port = ((const struct sockaddr_in *)addr)->sin_port;
  285. break;
  286. default:
  287. SERRX(addr->sa_family);
  288. }
  289. return host;
  290. }
  291. const char *
  292. operator2string(operator)
  293. enum operator_t operator;
  294. {
  295. switch (operator) {
  296. case none:
  297. return "none";
  298. case eq:
  299. return "eq";
  300. case neq:
  301. return "neq";
  302. case ge:
  303. return "ge";
  304. case le:
  305. return "le";
  306. case gt:
  307. return "gt";
  308. case lt:
  309. return "lt";
  310. case range:
  311. return "range";
  312. default:
  313. SERRX(operator);
  314. }
  315. /* NOTREACHED */
  316. }
  317. enum operator_t
  318. string2operator(string)
  319. const char *string;
  320. {
  321. if (strcmp(string, "eq") == 0 || strcmp(string, "=") == 0)
  322. return eq;
  323. if (strcmp(string, "neq") == 0 || strcmp(string, "!=") == 0)
  324. return neq;
  325. if (strcmp(string, "ge") == 0 || strcmp(string, ">=") == 0)
  326. return ge;
  327. if (strcmp(string, "le") == 0 || strcmp(string, "<=") == 0)
  328. return le;
  329. if (strcmp(string, "gt") == 0 || strcmp(string, ">") == 0)
  330. return gt;
  331. if (strcmp(string, "lt") == 0 || strcmp(string, "<") == 0)
  332. return lt;
  333. /* parser should make sure this never happens. */
  334. SERRX(string);
  335. /* NOTREACHED */
  336. }
  337. const char *
  338. ruleaddress2string(address, string, len)
  339. const struct ruleaddress_t *address;
  340. char *string;
  341. size_t len;
  342. {
  343. switch (address->atype) {
  344. case SOCKS_ADDR_IPV4: {
  345. char *a, *b;
  346. snprintf(string, len, "%s/%s, tcp port: %d, udp port: %d op: %s %d",
  347. strcheck(a = strdup(inet_ntoa(address->addr.ipv4.ip))),
  348. strcheck(b = strdup(inet_ntoa(address->addr.ipv4.mask))),
  349. ntohs(address->port.tcp), ntohs(address->port.udp),
  350. operator2string(address->operator),
  351. ntohs(address->portend));
  352. free(a);
  353. free(b);
  354. break;
  355. }
  356. case SOCKS_ADDR_DOMAIN:
  357. snprintf(string, len, "%s, tcp port: %d, udp port: %d op: %s %d",
  358. address->addr.domain,
  359. ntohs(address->port.tcp), ntohs(address->port.udp),
  360. operator2string(address->operator),
  361. ntohs(address->portend));
  362. break;
  363. default:
  364. SERRX(address->atype);
  365. }
  366. return string;
  367. }
  368. struct sockshost_t *
  369. ruleaddress2sockshost(address, host, protocol)
  370. const struct ruleaddress_t *address;
  371. struct sockshost_t *host;
  372. int protocol;
  373. {
  374. switch (host->atype = address->atype) {
  375. case SOCKS_ADDR_IPV4:
  376. host->addr.ipv4 = address->addr.ipv4.ip;
  377. break;
  378. case SOCKS_ADDR_DOMAIN:
  379. SASSERTX(strlen(address->addr.domain) < sizeof(host->addr.domain));
  380. strcpy(host->addr.domain, address->addr.domain);
  381. break;
  382. default:
  383. SERRX(address->atype);
  384. }
  385. switch (protocol) {
  386. case SOCKS_TCP:
  387. host->port = address->port.tcp;
  388. break;
  389. case SOCKS_UDP:
  390. host->port = address->port.udp;
  391. break;
  392. default:
  393. SERRX(protocol);
  394. }
  395. return host;
  396. }
  397. struct ruleaddress_t *
  398. sockshost2ruleaddress(host, addr)
  399. const struct sockshost_t *host;
  400. struct ruleaddress_t *addr;
  401. {
  402. switch (addr->atype = host->atype) {
  403. case SOCKS_ADDR_IPV4:
  404. addr->addr.ipv4.ip = host->addr.ipv4;
  405. addr->addr.ipv4.mask.s_addr = htonl(0xffffffff);
  406. break;
  407. case SOCKS_ADDR_DOMAIN:
  408. SASSERTX(strlen(host->addr.domain) < sizeof(addr->addr.domain));
  409. strcpy(addr->addr.domain, host->addr.domain);
  410. break;
  411. default:
  412. SERRX(host->atype);
  413. }
  414. addr->port.tcp = host->port;
  415. addr->port.udp = host->port;
  416. addr->portend = host->port;
  417. if (host->port == htons(0))
  418. addr->operator = none;
  419. else
  420. addr->operator = eq;
  421. return addr;
  422. }
  423. struct ruleaddress_t *
  424. sockaddr2ruleaddress(addr, ruleaddr)
  425. const struct sockaddr *addr;
  426. struct ruleaddress_t *ruleaddr;
  427. {
  428. struct sockshost_t host;
  429. sockaddr2sockshost(addr, &host);
  430. sockshost2ruleaddress(&host, ruleaddr);
  431. return ruleaddr;
  432. }
  433. const char *
  434. protocol2string(protocol)
  435. int protocol;
  436. {
  437. switch (protocol) {
  438. case SOCKS_TCP:
  439. return PROTOCOL_TCPs;
  440. case SOCKS_UDP:
  441. return PROTOCOL_UDPs;
  442. default:
  443. SERRX(protocol);
  444. }
  445. /* NOTREACHED */
  446. }
  447. char *
  448. sockaddr2string(address, string, len)
  449. const struct sockaddr *address;
  450. char *string;
  451. size_t len;
  452. {
  453. if (string == NULL) {
  454. static char addrstring[MAXSOCKADDRSTRING];
  455. string = addrstring;
  456. len = sizeof(addrstring);
  457. }
  458. switch (address->sa_family) {
  459. case AF_UNIX: {
  460. /* LINTED pointer casts may be troublesome */
  461. const struct sockaddr_un *addr = (const struct sockaddr_un *)address;
  462. strncpy(string, addr->sun_path, len - 1);
  463. string[len - 1] = NUL;
  464. break;
  465. }
  466. case AF_INET: {
  467. /* LINTED pointer casts may be troublesome */
  468. const struct sockaddr_in *addr = (const struct sockaddr_in *)address;
  469. snprintf(string, len, "%s.%d",
  470. inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
  471. break;
  472. }
  473. default:
  474. SERRX(address->sa_family);
  475. }
  476. return string;
  477. }
  478. void
  479. #ifdef STDC_HEADERS
  480. serr(int eval, const char *fmt, ...)
  481. #else
  482. serr(eval, fmt, va_alist)
  483. int eval;
  484. const char *fmt;
  485. va_dcl
  486. #endif  /* STDC_HEADERS */
  487. {
  488. if (fmt != NULL) {
  489. va_list ap;
  490. char buf[2048];
  491. size_t bufused;
  492. #ifdef STDC_HEADERS
  493. /* LINTED pointer casts may be troublesome */
  494. va_start(ap, fmt);
  495. #else
  496. va_start(ap);
  497. #endif  /* STDC_HEADERS */
  498. bufused = vsnprintf(buf, sizeof(buf), fmt, ap);
  499. bufused += snprintf(&buf[bufused], sizeof(buf) - bufused,
  500. ": %s (errno = %d)", strerror(errno), errno);
  501. slog(LOG_ERR, buf);
  502. /* LINTED expression has null effect */
  503. va_end(ap);
  504. }
  505. #if SOCKS_SERVER
  506. sockdexit(-eval);
  507. #else
  508. exit(eval);
  509. #endif
  510. }
  511. void
  512. #ifdef STDC_HEADERS
  513. serrx(int eval, const char *fmt, ...)
  514. #else
  515. serrx(eval, fmt, va_alist)
  516.       int eval;
  517.       const char *fmt;
  518.       va_dcl
  519. #endif  /* STDC_HEADERS */
  520. {
  521. if (fmt != NULL) {
  522. va_list ap;
  523. #ifdef STDC_HEADERS
  524. /* LINTED pointer casts may be troublesome */
  525. va_start(ap, fmt);
  526. #else
  527. va_start(ap);
  528. #endif  /* STDC_HEADERS */
  529. vslog(LOG_ERR, fmt, ap);
  530. /* LINTED expression has null effect */
  531. va_end(ap);
  532. }
  533. #if SOCKS_SERVER
  534. sockdexit(-eval);
  535. #else
  536. exit(eval);
  537. #endif
  538. }
  539. void
  540. #ifdef STDC_HEADERS
  541. swarn(const char *fmt, ...)
  542. #else
  543. swarn(fmt, va_alist)
  544. const char *fmt;
  545. va_dcl
  546. #endif  /* STDC_HEADERS */
  547. {
  548. if (fmt != NULL) {
  549. va_list ap;
  550. char buf[2048];
  551. size_t bufused;
  552. #ifdef STDC_HEADERS
  553. /* LINTED pointer casts may be troublesome */
  554. va_start(ap, fmt);
  555. #else
  556. va_start(ap);
  557. #endif  /* STDC_HEADERS */
  558. bufused = vsnprintf(buf, sizeof(buf), fmt, ap);
  559. bufused += snprintf(&buf[bufused], sizeof(buf) - bufused,
  560. ": %s (errno = %d)", strerror(errno), errno);
  561. slog(LOG_ERR, buf);
  562. /* LINTED expression has null effect */
  563. va_end(ap);
  564. }
  565. }
  566. void
  567. #ifdef STDC_HEADERS
  568. swarnx(const char *fmt, ...)
  569. #else
  570. swarnx(fmt, va_alist)
  571. const char *fmt;
  572. va_dcl
  573. #endif  /* STDC_HEADERS */
  574. {
  575. if (fmt != NULL) {
  576. va_list ap;
  577. #ifdef STDC_HEADERS
  578. /* LINTED pointer casts may be troublesome */
  579. va_start(ap, fmt);
  580. #else
  581. va_start(ap);
  582. #endif  /* STDC_HEADERS */
  583. vslog(LOG_ERR, fmt, ap);
  584. /* LINTED expression has null effect */
  585. va_end(ap);
  586. }
  587. }
  588. in_addr_t
  589. socks_addfakeip(host)
  590. const char *host;
  591. {
  592. const char *function = "socks_addfakeip()";
  593. char **tmpmem;
  594. struct in_addr addr;
  595. if (socks_getfakeip(host, &addr) == 1)
  596. return addr.s_addr;
  597. #if FAKEIP_END < FAKEIP_START
  598. error ""FAKEIP_END" can't be smaller than "FAKEIP_START""
  599. #endif
  600. if (ipc >= FAKEIP_END - FAKEIP_START) {
  601. swarnx("%s: fakeip range (%d - %d) exhausted",
  602. function, FAKEIP_START, FAKEIP_END);
  603. return INADDR_NONE;
  604. }
  605. if ((tmpmem = (char **)realloc(ipv, sizeof(*ipv) * (ipc + 1))) == NULL
  606. || (tmpmem[ipc] = (char *)malloc(sizeof(*tmpmem) * (strlen(host) + 1)))
  607. == NULL) {
  608. swarnx("%s: %s", function, NOMEM);
  609. return INADDR_NONE;
  610. }
  611. ipv = tmpmem;
  612. strcpy(ipv[ipc], host);
  613. return htonl(ipc++ + FAKEIP_START);
  614. }
  615. const char *
  616. socks_getfakehost(addr)
  617. in_addr_t addr;
  618. {
  619. if (ntohl(addr) - FAKEIP_START < ipc)
  620. return ipv[ntohl(addr) - FAKEIP_START];
  621. return NULL;
  622. }
  623. int
  624. socks_getfakeip(host, addr)
  625. const char *host;
  626. struct in_addr *addr;
  627. {
  628. unsigned int i;
  629. for (i = 0; i < ipc; ++i)
  630. if (strcasecmp(host, ipv[i]) == 0) {
  631. addr->s_addr = htonl(i + FAKEIP_START);
  632. return 1;
  633. }
  634. return 0;
  635. }
  636. struct sockshost_t *
  637. fakesockaddr2sockshost(addr, host)
  638. const struct sockaddr *addr;
  639. struct sockshost_t *host;
  640. {
  641. const char *function = "fakesockaddr2sockshost()";
  642. #if SOCKS_CLIENT /* may be called before normal init, log to right place. */
  643. clientinit();
  644. #endif
  645. /* LINTED pointer casts may be troublesome */
  646. slog(LOG_DEBUG, "%s: %s -> %s",
  647. function, sockaddr2string(addr, NULL, 0),
  648. socks_getfakehost(((const struct sockaddr_in *)addr)->sin_addr.s_addr)
  649. == NULL ? sockaddr2string(addr, NULL, 0)
  650. : socks_getfakehost(((const struct sockaddr_in *)addr)->sin_addr.s_addr));
  651. /* LINTED pointer casts may be troublesome */
  652. if (socks_getfakehost(((const struct sockaddr_in *)addr)->sin_addr.s_addr)
  653. != NULL) {
  654. const char *ipname
  655. /* LINTED pointer casts may be troublesome */
  656. = socks_getfakehost(((const struct sockaddr_in *)addr)->sin_addr.s_addr);
  657. SASSERTX(ipname != NULL);
  658. host->atype = SOCKS_ADDR_DOMAIN;
  659. SASSERTX(strlen(ipname) < sizeof(host->addr.domain));
  660. strcpy(host->addr.domain, ipname);
  661. /* LINTED pointer casts may be troublesome */
  662. host->port = ((const struct sockaddr_in *)addr)->sin_port;
  663. }
  664. else
  665. sockaddr2sockshost(addr, host);
  666. return host;
  667. }
  668. const char *
  669. socks_packet2string(packet, type)
  670.   const void *packet;
  671.   int type;
  672. {
  673. static char buf[1024];
  674. char hstring[MAXSOCKSHOSTSTRING];
  675. unsigned char version;
  676. const struct request_t *request = NULL;
  677. const struct response_t *response = NULL;
  678. switch (type) {
  679. case SOCKS_REQUEST:
  680. request = (const struct request_t *)packet;
  681. version = request->version;
  682. break;
  683. case SOCKS_RESPONSE:
  684. response = (const struct response_t *)packet;
  685. version = response->version;
  686. break;
  687.   default:
  688.  SERRX(type);
  689.   }
  690. switch (version) {
  691. case SOCKS_V4:
  692. case SOCKS_V4REPLY_VERSION:
  693. switch (type) {
  694. case SOCKS_REQUEST:
  695. snprintf(buf, sizeof(buf),
  696. "(V4) VN: %d CD: %d address: %s",
  697. request->version, request->command,
  698. sockshost2string(&request->host, hstring, sizeof(hstring)));
  699. break;
  700. case SOCKS_RESPONSE:
  701. snprintf(buf, sizeof(buf), "(V4) VN: %d CD: %d address: %s",
  702. response->version, response->reply,
  703. sockshost2string(&response->host, hstring, sizeof(hstring)));
  704. break;
  705. }
  706. break;
  707. case SOCKS_V5:
  708. switch (type) {
  709. case SOCKS_REQUEST:
  710. snprintf(buf, sizeof(buf),
  711. "VER: %d CMD: %d FLAG: %d ATYP: %d address: %s",
  712. request->version, request->command, request->flag,
  713. request->host.atype,
  714. sockshost2string(&request->host, hstring, sizeof(hstring)));
  715. break;
  716. case SOCKS_RESPONSE:
  717. snprintf(buf, sizeof(buf),
  718. "VER: %d REP: %d FLAG: %d ATYP: %d address: %s",
  719. response->version, response->reply, response->flag,
  720. response->host.atype,
  721. sockshost2string(&response->host, hstring, sizeof(hstring)));
  722. break;
  723. }
  724. break;
  725. default:
  726. SERRX(version);
  727.   }
  728. return buf;
  729. }
  730. int
  731. socks_logmatch(d, log)
  732. unsigned int d;
  733. const struct logtype_t *log;
  734. {
  735. int i;
  736. for (i = 0; i < log->fpc; ++i)
  737. if (d == (unsigned int)log->fplockv[i]
  738. ||  d == (unsigned int)fileno(log->fpv[i]))
  739. return 1;
  740. return 0;
  741. }
  742. int
  743. sockaddrareeq(a, b)
  744. const struct sockaddr *a;
  745. const struct sockaddr *b;
  746. {
  747. if (a->sa_family != b->sa_family)
  748. return 0;
  749. switch (a->sa_family) {
  750. case AF_INET: {
  751. /* LINTED pointer casts may be troublesome */
  752. const struct sockaddr_in *in_a = (const struct sockaddr_in *)a;
  753. /* LINTED pointer casts may be troublesome */
  754. const struct sockaddr_in *in_b = (const struct sockaddr_in *)b;
  755. if (in_a->sin_addr.s_addr != in_b->sin_addr.s_addr
  756. ||  in_a->sin_port   != in_b->sin_port)
  757. return 0;
  758. return 1;
  759. }
  760. default:
  761. SERRX(a->sa_family);
  762. }
  763. /* NOTREACHED */
  764. }
  765. int
  766. sockshostareeq(a, b)
  767. const struct sockshost_t *a;
  768. const struct sockshost_t *b;
  769. {
  770. if (a->atype != b->atype)
  771. return 0;
  772. switch (a->atype) {
  773. case SOCKS_ADDR_IPV4:
  774. if (memcmp(&a->addr.ipv4, &b->addr.ipv4, sizeof(a->addr.ipv4)) != 0)
  775. return 0;
  776. break;
  777. case SOCKS_ADDR_IPV6:
  778. if (memcmp(a->addr.ipv6, b->addr.ipv6, sizeof(a->addr.ipv6)) != 0)
  779. return 0;
  780. break;
  781. case SOCKS_ADDR_DOMAIN:
  782. if (strcmp(a->addr.domain, b->addr.domain) != 0)
  783. return 0;
  784. break;
  785. default:
  786. SERRX(a->atype);
  787. }
  788. if (a->port != b->port)
  789. return 0;
  790. return 1;
  791. }
  792. int
  793. fdsetop(nfds, op, a, b, result)
  794. int nfds;
  795. int op;
  796. const fd_set *a;
  797. const fd_set *b;
  798. fd_set *result;
  799. {
  800. int i, bits;
  801. FD_ZERO(result);
  802. bits = -1;
  803. switch (op) {
  804. case '&':
  805. for (i = 0; i < nfds; ++i)
  806. if (FD_ISSET(i, a) && FD_ISSET(i, b)) {
  807. FD_SET(i, result);
  808. bits = MAX(i, bits);
  809. }
  810. break;
  811. case '^':
  812. for (i = 0; i < nfds; ++i)
  813. if (FD_ISSET(i, a) != FD_ISSET(i, b)) {
  814. FD_SET(i, result);
  815. bits = MAX(i, bits);
  816. }
  817. break;
  818. default:
  819. SERRX(op);
  820. }
  821. return bits;
  822. }
  823. int
  824. methodisset(method, methodv, methodc)
  825. int method;
  826. const int *methodv;
  827. size_t methodc;
  828. {
  829. size_t i;
  830. for (i = 0; i < methodc; ++i)
  831. if (methodv[i] == method)
  832. return 1;
  833. return 0;
  834. }
  835. int
  836. socketoptdup(s)
  837. int s;
  838. {
  839. const char *function = "socketoptdup()";
  840. unsigned int i;
  841. int flags, new_s;
  842. socklen_t len;
  843. union {
  844. int int_val;
  845. struct linger linger_val;
  846. struct timeval timeval_val;
  847. struct in_addr in_addr_val;
  848. u_char u_char_val;
  849. struct sockaddr sockaddr_val;
  850. struct ipoption ipoption;
  851. } val;
  852. int levelname[][2] = {
  853. /* socket options */
  854. #ifdef SO_BROADCAST
  855. { SOL_SOCKET, SO_BROADCAST },
  856. #endif
  857. #ifdef SO_DEBUG
  858. { SOL_SOCKET, SO_DEBUG },
  859. #endif
  860. #ifdef SO_DONTROUTE
  861. { SOL_SOCKET, SO_DONTROUTE },
  862. #endif
  863. #ifdef SO_ERROR
  864. { SOL_SOCKET, SO_ERROR },
  865. #endif
  866. #ifdef SO_KEEPALIVE
  867. { SOL_SOCKET, SO_KEEPALIVE },
  868. #endif
  869. #ifdef SO_LINGER
  870. { SOL_SOCKET, SO_LINGER },
  871. #endif
  872. #ifdef SO_OOBINLINE
  873. { SOL_SOCKET, SO_OOBINLINE },
  874. #endif
  875. #ifdef SO_RCVBUF
  876. { SOL_SOCKET, SO_RCVBUF },
  877. #endif
  878. #ifdef SO_SNDBUF
  879. { SOL_SOCKET, SO_SNDBUF },
  880. #endif
  881. #ifdef SO_RCVLOWAT
  882. { SOL_SOCKET, SO_RCVLOWAT },
  883. #endif
  884. #ifdef SO_SNDLOWAT
  885. { SOL_SOCKET, SO_SNDLOWAT },
  886. #endif
  887. #ifdef SO_RCVTIMEO
  888. { SOL_SOCKET, SO_RCVTIMEO },
  889. #endif
  890. #ifdef SO_SNDTIMEO
  891. { SOL_SOCKET, SO_SNDTIMEO },
  892. #endif
  893. #ifdef SO_REUSEADDR
  894. { SOL_SOCKET, SO_REUSEADDR },
  895. #endif
  896. #ifdef SO_REUSEPORT
  897. { SOL_SOCKET, SO_REUSEPORT },
  898. #endif
  899. #ifdef SO_USELOOPBACK
  900. { SOL_SOCKET, SO_USELOOPBACK },
  901. #endif
  902. /* IP options */
  903. #ifdef IP_HDRINCL
  904. { IPPROTO_IP, IP_HDRINCL },
  905. #endif
  906. #ifdef IP_OPTIONS
  907. { IPPROTO_IP, IP_OPTIONS },
  908. #endif
  909. #ifdef IP_RECVDSTADDR
  910. { IPPROTO_IP, IP_RECVDSTADDR },
  911. #endif
  912. #ifdef IP_RECVIF
  913. { IPPROTO_IP, IP_RECVIF },
  914. #endif
  915. #ifdef IP_TOS
  916. { IPPROTO_IP, IP_TOS },
  917. #endif
  918. #ifdef IP_TTL
  919. { IPPROTO_IP, IP_TTL },
  920. #endif
  921. #ifdef IP_MULTICAST_IF
  922. { IPPROTO_IP, IP_MULTICAST_IF },
  923. #endif
  924. #ifdef IP_MULTICAST_TTL
  925. { IPPROTO_IP, IP_MULTICAST_TTL },
  926. #endif
  927. #ifdef IP_MULTICAST_LOOP
  928. { IPPROTO_IP, IP_MULTICAST_LOOP },
  929. #endif
  930. /* TCP options */
  931. #ifdef TCP_KEEPALIVE
  932. { IPPROTO_TCP, TCP_KEEPALIVE },
  933. #endif
  934. #ifdef TCP_MAXRT
  935. { IPPROTO_TCP, TCP_MAXRT },
  936. #endif
  937. #ifdef TCP_MAXSEG
  938. { IPPROTO_TCP, TCP_MAXSEG },
  939. #endif
  940. #ifdef TCP_NODELAY
  941. { IPPROTO_TCP, TCP_NODELAY },
  942. #endif
  943. #ifdef TCP_STDURG
  944. { IPPROTO_TCP, TCP_STDURG }
  945. #endif
  946. };
  947. len = sizeof(val);
  948. if (getsockopt(s, SOL_SOCKET, SO_TYPE, &val, &len) == -1) {
  949. swarn("%s: getsockopt(SO_TYPE)", function);
  950. return -1;
  951. }
  952. if ((new_s = socket(AF_INET, val.int_val, 0)) == -1) {
  953. swarn("%s: socket(AF_INET, %d)", function, val.int_val);
  954. return -1;
  955. }
  956. for (i = 0; i < ELEMENTS(levelname); ++i) {
  957. len = sizeof(val);
  958. if (getsockopt(s, levelname[i][0], levelname[i][1], &val, &len) == -1) {
  959. if (config.option.debug)
  960. swarn("%s: getsockopt(%d, %d)",
  961. function, levelname[i][0], levelname[i][1]);
  962. continue;
  963. }
  964. if (setsockopt(new_s, levelname[i][0], levelname[i][1], &val, len) == -1)
  965. swarn("%s: setsockopt(%d, %d)",
  966. function, levelname[i][0], levelname[i][1]);
  967. }
  968. if ((flags = fcntl(s, F_GETFL, 0)) == -1
  969. ||  fcntl(new_s, F_SETFL, flags) == -1)
  970. swarn("%s: fcntl(F_GETFL/F_SETFL)", function);
  971. #if SOCKS_SERVER && HAVE_LIBWRAP
  972. if ((s = fcntl(new_s, F_GETFD, 0)) == -1
  973. || fcntl(new_s, F_SETFD, s | FD_CLOEXEC) == -1)
  974. swarn("%s: fcntl(F_GETFD/F_SETFD)", function);
  975. #endif
  976. return new_s;
  977. }
  978. char *
  979. str2vis(string, len)
  980. const char *string;
  981. size_t len;
  982. {
  983. const int visflag = VIS_TAB | VIS_NL | VIS_CSTYLE | VIS_OCTAL;
  984. char *visstring;
  985. /* see vis(3) for "* 4" */
  986. if ((visstring = (char *)malloc((sizeof(*visstring) * len * 4)
  987. + sizeof(char))) != NULL)
  988. strvisx(visstring, string, len, visflag);
  989. return visstring;
  990. }
  991. int
  992. socks_mklock(template)
  993. const char *template;
  994. {
  995. const char *function = "socks_mklock()";
  996. char *prefix, *newtemplate;
  997. int s;
  998. size_t len;
  999. #if SOCKS_SERVER && HAVE_LIBWRAP
  1000. int flag;
  1001. #endif
  1002. if ((prefix = getenv("TMPDIR")) != NULL)
  1003. if (*prefix == NUL)
  1004. prefix = NULL;
  1005. if (prefix == NULL)
  1006. prefix = "/tmp";
  1007. len = strlen(prefix) + strlen("/") + strlen(template) + 1;
  1008. if ((newtemplate = (char *)malloc(sizeof(*newtemplate) * len)) == NULL)
  1009. return -1;
  1010. snprintf(newtemplate, len, "%s/%s", prefix, template);
  1011. if ((s = mkstemp(newtemplate)) == -1) {
  1012. swarn("%s: mkstemp(%s)", function, newtemplate);
  1013. free(newtemplate);
  1014. return -1;
  1015. }
  1016. if (unlink(newtemplate) == -1) {
  1017. swarn("%s: unlink(%s)", function, newtemplate);
  1018. free(newtemplate);
  1019. return -1;
  1020. }
  1021. free(newtemplate);
  1022. #if SOCKS_SERVER && HAVE_LIBWRAP
  1023. if ((flag = fcntl(s, F_GETFD, 0)) == -1
  1024. || fcntl(s, F_SETFD, flag | FD_CLOEXEC) == -1)
  1025. swarn("%s: fcntl(F_GETFD/F_SETFD)", function);
  1026. #endif
  1027. return s;
  1028. }
  1029. int
  1030. socks_lock(descriptor, type, timeout)
  1031. int descriptor;
  1032. int type;
  1033. int timeout;
  1034. {
  1035. /* const char *function = "socks_lock()"; */
  1036. struct flock lock;
  1037. int rc;
  1038. lock.l_type = (short)type;
  1039. lock.l_start = 0;
  1040. lock.l_whence = SEEK_SET;
  1041. lock.l_len = 0;
  1042. SASSERTX(timeout <= 0);
  1043. #if 0 /* missing some bits here to handle racecondition. */
  1044. if (timeout > 0) {
  1045. struct sigaction sigact;
  1046. #if SOCKS_CLIENT
  1047. if (sigaction(SIGALRM, NULL, &sigact) != 0)
  1048. return -1;
  1049. /* if handler already set for signal, don't override. */
  1050. if (sigact.sa_handler == SIG_DFL || sigact.sa_handler == SIG_IGN) {
  1051. #else /* !SOCKS_CLIENT */
  1052. /* CONSTCOND */
  1053. if (1) {
  1054. #endif /* !SOCKS_CLIENT */
  1055. sigemptyset(&sigact.sa_mask);
  1056. sigact.sa_flags = 0;
  1057. sigact.sa_handler = SIG_IGN;
  1058. if (sigaction(SIGALRM, &sigact, NULL) != 0)
  1059. return -1;
  1060. }
  1061. alarm((unsigned int)timeout);
  1062. }
  1063. #endif
  1064. do
  1065. rc = fcntl(descriptor, timeout ? F_SETLKW : F_SETLK, &lock);
  1066. while (rc == -1 && timeout == -1 && errno == EINTR);
  1067. if (rc == -1)
  1068. switch (errno) {
  1069. case EACCES:
  1070. case EAGAIN:
  1071. case EINTR:
  1072. break;
  1073. case ENOLCK:
  1074. sleep(1);
  1075. return socks_lock(descriptor, type, timeout);
  1076. default:
  1077. SERR(descriptor);
  1078. }
  1079. #if 0
  1080. if (timeout > 0)
  1081. alarm(0);
  1082. #endif
  1083. if (rc != 0 && timeout == -1)
  1084. abort();
  1085. return rc == -1 ? rc : 0;
  1086. }
  1087. void
  1088. socks_unlock(d)
  1089. int d;
  1090. {
  1091. socks_lock(d, F_UNLCK, -1);
  1092. }
  1093. int
  1094. socks_socketisbound(s)
  1095. int s;
  1096. {
  1097. struct sockaddr_in addr;
  1098. socklen_t len;
  1099. len = sizeof(addr);
  1100. /* LINTED pointer casts may be troublesome */
  1101. if (getsockname(s, (struct sockaddr *)&addr, &len) != 0)
  1102. return -1;
  1103. return ADDRISBOUND(addr);
  1104. }
  1105. int
  1106. freedescriptors(message)
  1107. const char *message;
  1108. {
  1109. const int errno_s = errno;
  1110. int i, freed, max;
  1111. /* LINTED expression has null effect */
  1112. for (freed = 0, i = 0, max = getdtablesize(); i < max; ++i)
  1113. if (!fdisopen(i))
  1114. ++freed;
  1115. if (message != NULL)
  1116. slog(LOG_DEBUG, "freedescriptors(%s): %d/%d", message, freed, max);
  1117. errno = errno_s;
  1118. return freed;
  1119. }
  1120. int
  1121. fdisopen(fd)
  1122. int fd;
  1123. {
  1124. if (fcntl(fd, F_GETFD, 0) == 0)
  1125. return 1;
  1126. return 0;
  1127. }
  1128. void
  1129. closev(array, count)
  1130. int *array;
  1131. int count;
  1132. {
  1133. for (--count; count >= 0; --count)
  1134. if (array[count] >= 0)
  1135. if (close(array[count]) != 0)
  1136. SERR(-1);
  1137. }