tcp-wrappers-7.6-ipv6-1.14.diff 36 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249
  1. ;; IPv6 patch for tcp_wrappers_7.6 1.14
  2. ;; Dec 29, 2001 by Hajimu UMEMOTO <ume@mahoroba.org>
  3. ;;
  4. ;; This patch supports IPv4/IPv6 dual stack and IPv4-mapped IPv6 address.
  5. ;; You can replace stock tcpd or libwrap.a with this.
  6. ;; IPv6 address pattern is as a `[net]/prefixlen' pair.
  7. ;; This patch was tested on KAME/FreeBSD, KAME/FreeBSD3, KAME/NetBSD,
  8. ;; RedHat 5.1 with kernel 2.1.126, and RedHat 6.0 with kernel 2.2.10.
  9. ;; Solaris 8 is now supported. Thanks Alexander Gall <gall@switch.ch>
  10. ;; and Shigechika AIKAWA <shige@cin.nihon-u.ac.jp>.
  11. ;;
  12. ;; This version is using getaddrinfo()/getnameinfo() instead of
  13. ;; getipnode*() to support scoped address. Use of
  14. ;; getaddrinfo()/getnameinfo() and scoped address support is only
  15. ;; tested on KAME.
  16. ;;
  17. ;; CAUTION:
  18. ;; Back out change for field separater. Now, field separater is `:'
  19. ;; not `|'. To specify IPv6 address, enclose IPv6 address with `['
  20. ;; and `]'.
  21. ;;
  22. ;; For Linux users:
  23. ;; If your libc doesn't have sockaddr_storage, try target `linux-old'.
  24. Index: src/tcp_wrappers/Makefile
  25. diff -u src/tcp_wrappers/Makefile:1.1.1.1 src/tcp_wrappers/Makefile:1.10
  26. --- src/tcp_wrappers/Makefile:1.1.1.1 Tue May 4 21:56:04 1999
  27. +++ src/tcp_wrappers/Makefile Fri May 5 20:11:48 2000
  28. @@ -454,7 +474,7 @@
  29. # host name aliases. Compile with -DSOLARIS_24_GETHOSTBYNAME_BUG to work
  30. # around this. The workaround does no harm on other Solaris versions.
  31. -BUGS = -DGETPEERNAME_BUG -DBROKEN_FGETS -DLIBC_CALLS_STRTOK
  32. +#BUGS = -DGETPEERNAME_BUG -DBROKEN_FGETS -DLIBC_CALLS_STRTOK
  33. #BUGS = -DGETPEERNAME_BUG -DBROKEN_FGETS -DINET_ADDR_BUG
  34. #BUGS = -DGETPEERNAME_BUG -DBROKEN_FGETS -DSOLARIS_24_GETHOSTBYNAME_BUG
  35. Index: src/tcp_wrappers/fix_options.c
  36. diff -u src/tcp_wrappers/fix_options.c:1.1.1.1 src/tcp_wrappers/fix_options.c:1.4
  37. --- src/tcp_wrappers/fix_options.c:1.1.1.1 Tue May 4 21:56:04 1999
  38. +++ src/tcp_wrappers/fix_options.c Tue Sep 28 04:13:19 1999
  39. @@ -11,6 +11,9 @@
  40. #include <sys/types.h>
  41. #include <sys/param.h>
  42. +#ifdef INET6
  43. +#include <sys/socket.h>
  44. +#endif
  45. #include <netinet/in.h>
  46. #include <netinet/in_systm.h>
  47. #include <netinet/ip.h>
  48. @@ -41,6 +44,22 @@
  49. unsigned int opt;
  50. int optlen;
  51. struct in_addr dummy;
  52. +#ifdef INET6
  53. + struct sockaddr_storage ss;
  54. + int sslen;
  55. +
  56. + /*
  57. + * check if this is AF_INET socket
  58. + * XXX IPv6 support?
  59. + */
  60. + sslen = sizeof(ss);
  61. + if (getsockname(fd, (struct sockaddr *)&ss, &sslen) < 0) {
  62. + syslog(LOG_ERR, "getpeername: %m");
  63. + clean_exit(request);
  64. + }
  65. + if (ss.ss_family != AF_INET)
  66. + return;
  67. +#endif
  68. if ((ip = getprotobyname("ip")) != 0)
  69. ipproto = ip->p_proto;
  70. Index: src/tcp_wrappers/inetcf.c
  71. diff -u src/tcp_wrappers/inetcf.c:1.1.1.1 src/tcp_wrappers/inetcf.c:1.2
  72. --- src/tcp_wrappers/inetcf.c:1.1.1.1 Tue May 4 21:56:04 1999
  73. +++ src/tcp_wrappers/inetcf.c Tue May 4 21:58:36 1999
  74. @@ -26,6 +26,9 @@
  75. * guesses. Shorter names follow longer ones.
  76. */
  77. char *inet_files[] = {
  78. +#ifdef INET6
  79. + "/usr/local/v6/etc/inet6d.conf", /* KAME */
  80. +#endif
  81. "/private/etc/inetd.conf", /* NEXT */
  82. "/etc/inet/inetd.conf", /* SYSV4 */
  83. "/usr/etc/inetd.conf", /* IRIX?? */
  84. Index: src/tcp_wrappers/misc.c
  85. diff -u src/tcp_wrappers/misc.c:1.1.1.1 src/tcp_wrappers/misc.c:1.4
  86. --- src/tcp_wrappers/misc.c:1.1.1.1 Tue May 4 21:56:04 1999
  87. +++ src/tcp_wrappers/misc.c Mon Aug 23 01:32:43 1999
  88. @@ -58,9 +58,31 @@
  89. {
  90. char *cp;
  91. +#ifdef INET6
  92. + int bracket = 0;
  93. +
  94. + for (cp = string; cp && *cp; cp++) {
  95. + switch (*cp) {
  96. + case '[':
  97. + bracket++;
  98. + break;
  99. + case ']':
  100. + bracket--;
  101. + break;
  102. + default:
  103. + if (bracket == 0 && *cp == delimiter) {
  104. + *cp++ = 0;
  105. + return cp;
  106. + }
  107. + break;
  108. + }
  109. + }
  110. + return (NULL);
  111. +#else
  112. if ((cp = strchr(string, delimiter)) != 0)
  113. *cp++ = 0;
  114. return (cp);
  115. +#endif
  116. }
  117. /* dot_quad_addr - convert dotted quad to internal form */
  118. Index: src/tcp_wrappers/refuse.c
  119. diff -u src/tcp_wrappers/refuse.c:1.1.1.1 src/tcp_wrappers/refuse.c:1.2
  120. --- src/tcp_wrappers/refuse.c:1.1.1.1 Tue May 4 21:56:04 1999
  121. +++ src/tcp_wrappers/refuse.c Tue May 4 21:58:36 1999
  122. @@ -25,7 +25,12 @@
  123. void refuse(request)
  124. struct request_info *request;
  125. {
  126. +#ifdef INET6
  127. + syslog(deny_severity, "refused connect from %s (%s)",
  128. + eval_client(request), eval_hostaddr(request->client));
  129. +#else
  130. syslog(deny_severity, "refused connect from %s", eval_client(request));
  131. +#endif
  132. clean_exit(request);
  133. /* NOTREACHED */
  134. }
  135. Index: src/tcp_wrappers/rfc931.c
  136. diff -u src/tcp_wrappers/rfc931.c:1.1.1.1 src/tcp_wrappers/rfc931.c:1.7
  137. --- src/tcp_wrappers/rfc931.c:1.1.1.1 Tue May 4 21:56:04 1999
  138. +++ src/tcp_wrappers/rfc931.c Mon Aug 23 01:32:43 1999
  139. @@ -68,20 +68,50 @@
  140. /* rfc931 - return remote user name, given socket structures */
  141. void rfc931(rmt_sin, our_sin, dest)
  142. +#ifdef INET6
  143. +struct sockaddr *rmt_sin;
  144. +struct sockaddr *our_sin;
  145. +#else
  146. struct sockaddr_in *rmt_sin;
  147. struct sockaddr_in *our_sin;
  148. +#endif
  149. char *dest;
  150. {
  151. unsigned rmt_port;
  152. unsigned our_port;
  153. +#ifdef INET6
  154. + struct sockaddr_storage rmt_query_sin;
  155. + struct sockaddr_storage our_query_sin;
  156. + int alen;
  157. +#else
  158. struct sockaddr_in rmt_query_sin;
  159. struct sockaddr_in our_query_sin;
  160. +#endif
  161. char user[256]; /* XXX */
  162. char buffer[512]; /* XXX */
  163. char *cp;
  164. char *result = unknown;
  165. FILE *fp;
  166. +#ifdef INET6
  167. + /* address family must be the same */
  168. + if (rmt_sin->sa_family != our_sin->sa_family) {
  169. + STRN_CPY(dest, result, STRING_LENGTH);
  170. + return;
  171. + }
  172. + switch (our_sin->sa_family) {
  173. + case AF_INET:
  174. + alen = sizeof(struct sockaddr_in);
  175. + break;
  176. + case AF_INET6:
  177. + alen = sizeof(struct sockaddr_in6);
  178. + break;
  179. + default:
  180. + STRN_CPY(dest, result, STRING_LENGTH);
  181. + return;
  182. + }
  183. +#endif
  184. +
  185. /*
  186. * Use one unbuffered stdio stream for writing to and for reading from
  187. * the RFC931 etc. server. This is done because of a bug in the SunOS
  188. @@ -92,7 +122,11 @@
  189. * sockets.
  190. */
  191. +#ifdef INET6
  192. + if ((fp = fsocket(our_sin->sa_family, SOCK_STREAM, 0)) != 0) {
  193. +#else
  194. if ((fp = fsocket(AF_INET, SOCK_STREAM, 0)) != 0) {
  195. +#endif
  196. setbuf(fp, (char *) 0);
  197. /*
  198. @@ -112,6 +146,25 @@
  199. * addresses from the query socket.
  200. */
  201. +#ifdef INET6
  202. + memcpy(&our_query_sin, our_sin, alen);
  203. + memcpy(&rmt_query_sin, rmt_sin, alen);
  204. + switch (our_sin->sa_family) {
  205. + case AF_INET:
  206. + ((struct sockaddr_in *)&our_query_sin)->sin_port = htons(ANY_PORT);
  207. + ((struct sockaddr_in *)&rmt_query_sin)->sin_port = htons(RFC931_PORT);
  208. + break;
  209. + case AF_INET6:
  210. + ((struct sockaddr_in6 *)&our_query_sin)->sin6_port = htons(ANY_PORT);
  211. + ((struct sockaddr_in6 *)&rmt_query_sin)->sin6_port = htons(RFC931_PORT);
  212. + break;
  213. + }
  214. +
  215. + if (bind(fileno(fp), (struct sockaddr *) & our_query_sin,
  216. + alen) >= 0 &&
  217. + connect(fileno(fp), (struct sockaddr *) & rmt_query_sin,
  218. + alen) >= 0) {
  219. +#else
  220. our_query_sin = *our_sin;
  221. our_query_sin.sin_port = htons(ANY_PORT);
  222. rmt_query_sin = *rmt_sin;
  223. @@ -121,6 +174,7 @@
  224. sizeof(our_query_sin)) >= 0 &&
  225. connect(fileno(fp), (struct sockaddr *) & rmt_query_sin,
  226. sizeof(rmt_query_sin)) >= 0) {
  227. +#endif
  228. /*
  229. * Send query to server. Neglect the risk that a 13-byte
  230. @@ -129,8 +183,13 @@
  231. */
  232. fprintf(fp, "%u,%u\r\n",
  233. +#ifdef INET6
  234. + ntohs(((struct sockaddr_in *)rmt_sin)->sin_port),
  235. + ntohs(((struct sockaddr_in *)our_sin)->sin_port));
  236. +#else
  237. ntohs(rmt_sin->sin_port),
  238. ntohs(our_sin->sin_port));
  239. +#endif
  240. fflush(fp);
  241. /*
  242. @@ -144,8 +203,13 @@
  243. && ferror(fp) == 0 && feof(fp) == 0
  244. && sscanf(buffer, "%u , %u : USERID :%*[^:]:%255s",
  245. &rmt_port, &our_port, user) == 3
  246. +#ifdef INET6
  247. + && ntohs(((struct sockaddr_in *)rmt_sin)->sin_port) == rmt_port
  248. + && ntohs(((struct sockaddr_in *)our_sin)->sin_port) == our_port) {
  249. +#else
  250. && ntohs(rmt_sin->sin_port) == rmt_port
  251. && ntohs(our_sin->sin_port) == our_port) {
  252. +#endif
  253. /*
  254. * Strip trailing carriage return. It is part of the
  255. Index: src/tcp_wrappers/scaffold.c
  256. diff -u src/tcp_wrappers/scaffold.c:1.1.1.1 src/tcp_wrappers/scaffold.c:1.12
  257. --- src/tcp_wrappers/scaffold.c:1.1.1.1 Tue May 4 21:56:04 1999
  258. +++ src/tcp_wrappers/scaffold.c Fri May 5 18:54:46 2000
  259. @@ -39,6 +41,7 @@
  260. int deny_severity = LOG_WARNING;
  261. int rfc931_timeout = RFC931_TIMEOUT;
  262. +#ifndef INET6
  263. /* dup_hostent - create hostent in one memory block */
  264. static struct hostent *dup_hostent(hp)
  265. @@ -73,9 +76,46 @@
  266. }
  267. return (&hb->host);
  268. }
  269. +#endif
  270. /* find_inet_addr - find all addresses for this host, result to free() */
  271. +#ifdef INET6
  272. +struct addrinfo *find_inet_addr(host)
  273. +char *host;
  274. +{
  275. + struct addrinfo hints, *res;
  276. +
  277. + memset(&hints, 0, sizeof(hints));
  278. + hints.ai_family = PF_UNSPEC;
  279. + hints.ai_socktype = SOCK_STREAM;
  280. + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
  281. + if (getaddrinfo(host, NULL, &hints, &res) == 0)
  282. + return (res);
  283. +
  284. + memset(&hints, 0, sizeof(hints));
  285. + hints.ai_family = PF_UNSPEC;
  286. + hints.ai_socktype = SOCK_STREAM;
  287. + hints.ai_flags = AI_PASSIVE | AI_CANONNAME;
  288. + if (getaddrinfo(host, NULL, &hints, &res) != 0) {
  289. + tcpd_warn("%s: host not found", host);
  290. + return (0);
  291. + }
  292. + if (res->ai_family != AF_INET6 && res->ai_family != AF_INET) {
  293. + tcpd_warn("%d: not an internet host", res->ai_family);
  294. + freeaddrinfo(res);
  295. + return (0);
  296. + }
  297. + if (!res->ai_canonname) {
  298. + tcpd_warn("%s: hostname alias", host);
  299. + tcpd_warn("(cannot obtain official name)", res->ai_canonname);
  300. + } else if (STR_NE(host, res->ai_canonname)) {
  301. + tcpd_warn("%s: hostname alias", host);
  302. + tcpd_warn("(official name: %.*s)", STRING_LENGTH, res->ai_canonname);
  303. + }
  304. + return (res);
  305. +}
  306. +#else
  307. struct hostent *find_inet_addr(host)
  308. char *host;
  309. {
  310. @@ -118,6 +158,7 @@
  311. }
  312. return (dup_hostent(hp));
  313. }
  314. +#endif
  315. /* check_dns - give each address thorough workout, return address count */
  316. @@ -125,8 +166,13 @@
  317. char *host;
  318. {
  319. struct request_info request;
  320. +#ifdef INET6
  321. + struct sockaddr_storage sin;
  322. + struct addrinfo *hp, *res;
  323. +#else
  324. struct sockaddr_in sin;
  325. struct hostent *hp;
  326. +#endif
  327. int count;
  328. char *addr;
  329. @@ -134,11 +180,18 @@
  330. return (0);
  331. request_init(&request, RQ_CLIENT_SIN, &sin, 0);
  332. sock_methods(&request);
  333. +#ifndef INET6
  334. memset((char *) &sin, 0, sizeof(sin));
  335. sin.sin_family = AF_INET;
  336. +#endif
  337. +#ifdef INET6
  338. + for (res = hp, count = 0; res; res = res->ai_next, count++) {
  339. + memcpy(&sin, res->ai_addr, res->ai_addrlen);
  340. +#else
  341. for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
  342. memcpy((char *) &sin.sin_addr, addr, sizeof(sin.sin_addr));
  343. +#endif
  344. /*
  345. * Force host name and address conversions. Use the request structure
  346. @@ -151,7 +204,11 @@
  347. tcpd_warn("host address %s->name lookup failed",
  348. eval_hostaddr(request.client));
  349. }
  350. +#ifdef INET6
  351. + freeaddrinfo(hp);
  352. +#else
  353. free((char *) hp);
  354. +#endif
  355. return (count);
  356. }
  357. Index: src/tcp_wrappers/scaffold.h
  358. diff -u src/tcp_wrappers/scaffold.h:1.1.1.1 src/tcp_wrappers/scaffold.h:1.2
  359. --- src/tcp_wrappers/scaffold.h:1.1.1.1 Tue May 4 21:56:04 1999
  360. +++ src/tcp_wrappers/scaffold.h Fri May 5 18:28:13 2000
  361. @@ -4,6 +4,10 @@
  362. * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
  363. */
  364. +#ifdef INET6
  365. +extern struct addrinfo *find_inet_addr();
  366. +#else
  367. extern struct hostent *find_inet_addr();
  368. +#endif
  369. extern int check_dns();
  370. extern int check_path();
  371. Index: src/tcp_wrappers/socket.c
  372. diff -u src/tcp_wrappers/socket.c:1.1.1.1 src/tcp_wrappers/socket.c:1.20
  373. --- src/tcp_wrappers/socket.c:1.1.1.1 Tue May 4 21:56:04 1999
  374. +++ src/tcp_wrappers/socket.c Thu Jul 5 05:26:07 2001
  375. @@ -24,13 +24,22 @@
  376. #include <sys/types.h>
  377. #include <sys/param.h>
  378. #include <sys/socket.h>
  379. +#ifdef INT32_T
  380. +typedef uint32_t u_int32_t;
  381. +#endif
  382. #include <netinet/in.h>
  383. #include <netdb.h>
  384. #include <stdio.h>
  385. #include <syslog.h>
  386. #include <string.h>
  387. +#ifdef INET6
  388. +#ifndef NI_WITHSCOPEID
  389. +#define NI_WITHSCOPEID 0
  390. +#endif
  391. +#else
  392. extern char *inet_ntoa();
  393. +#endif
  394. /* Local stuff. */
  395. @@ -74,8 +83,13 @@
  396. void sock_host(request)
  397. struct request_info *request;
  398. {
  399. +#ifdef INET6
  400. + static struct sockaddr_storage client;
  401. + static struct sockaddr_storage server;
  402. +#else
  403. static struct sockaddr_in client;
  404. static struct sockaddr_in server;
  405. +#endif
  406. int len;
  407. char buf[BUFSIZ];
  408. int fd = request->fd;
  409. @@ -104,7 +118,11 @@
  410. memset(buf, 0 sizeof(buf));
  411. #endif
  412. }
  413. +#ifdef INET6
  414. + request->client->sin = (struct sockaddr *)&client;
  415. +#else
  416. request->client->sin = &client;
  417. +#endif
  418. /*
  419. * Determine the server binding. This is used for client username
  420. @@ -117,7 +135,11 @@
  421. tcpd_warn("getsockname: %m");
  422. return;
  423. }
  424. +#ifdef INET6
  425. + request->server->sin = (struct sockaddr *)&server;
  426. +#else
  427. request->server->sin = &server;
  428. +#endif
  429. }
  430. /* sock_hostaddr - map endpoint address to printable form */
  431. @@ -125,10 +147,26 @@
  432. void sock_hostaddr(host)
  433. struct host_info *host;
  434. {
  435. +#ifdef INET6
  436. + struct sockaddr *sin = host->sin;
  437. + int salen;
  438. +
  439. + if (!sin)
  440. + return;
  441. +#ifdef SIN6_LEN
  442. + salen = sin->sa_len;
  443. +#else
  444. + salen = (sin->sa_family == AF_INET) ? sizeof(struct sockaddr_in)
  445. + : sizeof(struct sockaddr_in6);
  446. +#endif
  447. + getnameinfo(sin, salen, host->addr, sizeof(host->addr),
  448. + NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID);
  449. +#else
  450. struct sockaddr_in *sin = host->sin;
  451. if (sin != 0)
  452. STRN_CPY(host->addr, inet_ntoa(sin->sin_addr), sizeof(host->addr));
  453. +#endif
  454. }
  455. /* sock_hostname - map endpoint address to host name */
  456. @@ -136,6 +174,160 @@
  457. void sock_hostname(host)
  458. struct host_info *host;
  459. {
  460. +#ifdef INET6
  461. + struct sockaddr *sin = host->sin;
  462. + struct sockaddr_in sin4;
  463. + struct addrinfo hints, *res, *res0 = NULL;
  464. + int salen, alen, err = 1;
  465. + char *ap = NULL, *rap, hname[NI_MAXHOST];
  466. +
  467. + if (sin != NULL) {
  468. + if (sin->sa_family == AF_INET6) {
  469. + struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sin;
  470. +
  471. + if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
  472. + memset(&sin4, 0, sizeof(sin4));
  473. +#ifdef SIN6_LEN
  474. + sin4.sin_len = sizeof(sin4);
  475. +#endif
  476. + sin4.sin_family = AF_INET;
  477. + sin4.sin_port = sin6->sin6_port;
  478. + sin4.sin_addr.s_addr = *(u_int32_t *)&sin6->sin6_addr.s6_addr[12];
  479. + sin = (struct sockaddr *)&sin4;
  480. + }
  481. + }
  482. + switch (sin->sa_family) {
  483. + case AF_INET:
  484. + ap = (char *)&((struct sockaddr_in *)sin)->sin_addr;
  485. + alen = sizeof(struct in_addr);
  486. + salen = sizeof(struct sockaddr_in);
  487. + break;
  488. + case AF_INET6:
  489. + ap = (char *)&((struct sockaddr_in6 *)sin)->sin6_addr;
  490. + alen = sizeof(struct in6_addr);
  491. + salen = sizeof(struct sockaddr_in6);
  492. + break;
  493. + default:
  494. + break;
  495. + }
  496. + if (ap)
  497. + err = getnameinfo(sin, salen, hname, sizeof(hname),
  498. + NULL, 0, NI_WITHSCOPEID | NI_NAMEREQD);
  499. + }
  500. + if (!err) {
  501. +
  502. + STRN_CPY(host->name, hname, sizeof(host->name));
  503. +
  504. + /* reject numeric addresses */
  505. + memset(&hints, 0, sizeof(hints));
  506. + hints.ai_family = sin->sa_family;
  507. + hints.ai_socktype = SOCK_STREAM;
  508. + hints.ai_flags = AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST;
  509. + if ((err = getaddrinfo(host->name, NULL, &hints, &res0)) == 0) {
  510. + freeaddrinfo(res0);
  511. + res0 = NULL;
  512. + tcpd_warn("host name/name mismatch: "
  513. + "reverse lookup results in non-FQDN %s",
  514. + host->name);
  515. + strcpy(host->name, paranoid); /* name is bad, clobber it */
  516. + }
  517. + err = !err;
  518. + }
  519. + if (!err) {
  520. + /* we are now sure that this is non-numeric */
  521. +
  522. + /*
  523. + * Verify that the address is a member of the address list returned
  524. + * by gethostbyname(hostname).
  525. + *
  526. + * Verify also that gethostbyaddr() and gethostbyname() return the same
  527. + * hostname, or rshd and rlogind may still end up being spoofed.
  528. + *
  529. + * On some sites, gethostbyname("localhost") returns "localhost.domain".
  530. + * This is a DNS artefact. We treat it as a special case. When we
  531. + * can't believe the address list from gethostbyname("localhost")
  532. + * we're in big trouble anyway.
  533. + */
  534. +
  535. + memset(&hints, 0, sizeof(hints));
  536. + hints.ai_family = sin->sa_family;
  537. + hints.ai_socktype = SOCK_STREAM;
  538. + hints.ai_flags = AI_PASSIVE | AI_CANONNAME;
  539. + if (getaddrinfo(host->name, NULL, &hints, &res0) != 0) {
  540. +
  541. + /*
  542. + * Unable to verify that the host name matches the address. This
  543. + * may be a transient problem or a botched name server setup.
  544. + */
  545. +
  546. + tcpd_warn("can't verify hostname: getaddrinfo(%s, %s) failed",
  547. + host->name,
  548. + (sin->sa_family == AF_INET) ? "AF_INET" : "AF_INET6");
  549. +
  550. + } else if ((res0->ai_canonname == NULL
  551. + || STR_NE(host->name, res0->ai_canonname))
  552. + && STR_NE(host->name, "localhost")) {
  553. +
  554. + /*
  555. + * The gethostbyaddr() and gethostbyname() calls did not return
  556. + * the same hostname. This could be a nameserver configuration
  557. + * problem. It could also be that someone is trying to spoof us.
  558. + */
  559. +
  560. + tcpd_warn("host name/name mismatch: %s != %.*s",
  561. + host->name, STRING_LENGTH,
  562. + (res0->ai_canonname == NULL) ? "" : res0->ai_canonname);
  563. +
  564. + } else {
  565. +
  566. + /*
  567. + * The address should be a member of the address list returned by
  568. + * gethostbyname(). We should first verify that the h_addrtype
  569. + * field is AF_INET, but this program has already caused too much
  570. + * grief on systems with broken library code.
  571. + */
  572. +
  573. + for (res = res0; res; res = res->ai_next) {
  574. + if (res->ai_family != sin->sa_family)
  575. + continue;
  576. + switch (res->ai_family) {
  577. + case AF_INET:
  578. + rap = (char *)&((struct sockaddr_in *)res->ai_addr)->sin_addr;
  579. + break;
  580. + case AF_INET6:
  581. + /* need to check scope_id */
  582. + if (((struct sockaddr_in6 *)sin)->sin6_scope_id !=
  583. + ((struct sockaddr_in6 *)res->ai_addr)->sin6_scope_id) {
  584. + continue;
  585. + }
  586. + rap = (char *)&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
  587. + break;
  588. + default:
  589. + continue;
  590. + }
  591. + if (memcmp(rap, ap, alen) == 0) {
  592. + freeaddrinfo(res0);
  593. + return; /* name is good, keep it */
  594. + }
  595. + }
  596. +
  597. + /*
  598. + * The host name does not map to the initial address. Perhaps
  599. + * someone has messed up. Perhaps someone compromised a name
  600. + * server.
  601. + */
  602. +
  603. + getnameinfo(sin, salen, hname, sizeof(hname),
  604. + NULL, 0, NI_NUMERICHOST | NI_WITHSCOPEID);
  605. + tcpd_warn("host name/address mismatch: %s != %.*s",
  606. + hname, STRING_LENGTH,
  607. + (res0->ai_canonname == NULL) ? "" : res0->ai_canonname);
  608. + }
  609. + strcpy(host->name, paranoid); /* name is bad, clobber it */
  610. + if (res0)
  611. + freeaddrinfo(res0);
  612. + }
  613. +#else /* INET6 */
  614. struct sockaddr_in *sin = host->sin;
  615. struct hostent *hp;
  616. int i;
  617. @@ -215,6 +407,7 @@
  618. }
  619. strcpy(host->name, paranoid); /* name is bad, clobber it */
  620. }
  621. +#endif /* INET6 */
  622. }
  623. /* sock_sink - absorb unreceived IP datagram */
  624. @@ -223,7 +416,11 @@
  625. int fd;
  626. {
  627. char buf[BUFSIZ];
  628. +#ifdef INET6
  629. + struct sockaddr_storage sin;
  630. +#else
  631. struct sockaddr_in sin;
  632. +#endif
  633. int size = sizeof(sin);
  634. /*
  635. Index: src/tcp_wrappers/tcpd.c
  636. diff -u src/tcp_wrappers/tcpd.c:1.1.1.1 src/tcp_wrappers/tcpd.c:1.2
  637. --- src/tcp_wrappers/tcpd.c:1.1.1.1 Tue May 4 21:56:04 1999
  638. +++ src/tcp_wrappers/tcpd.c Tue May 4 21:58:36 1999
  639. @@ -120,7 +120,12 @@
  640. /* Report request and invoke the real daemon program. */
  641. +#ifdef INET6
  642. + syslog(allow_severity, "connect from %s (%s)",
  643. + eval_client(&request), eval_hostaddr(request.client));
  644. +#else
  645. syslog(allow_severity, "connect from %s", eval_client(&request));
  646. +#endif
  647. closelog();
  648. (void) execv(path, argv);
  649. syslog(LOG_ERR, "error: cannot execute %s: %m", path);
  650. Index: src/tcp_wrappers/tcpd.h
  651. diff -u src/tcp_wrappers/tcpd.h:1.1.1.1 src/tcp_wrappers/tcpd.h:1.7
  652. --- src/tcp_wrappers/tcpd.h:1.1.1.1 Tue May 4 21:56:04 1999
  653. +++ src/tcp_wrappers/tcpd.h Mon Aug 23 01:32:43 1999
  654. @@ -11,7 +11,11 @@
  655. struct host_info {
  656. char name[STRING_LENGTH]; /* access via eval_hostname(host) */
  657. char addr[STRING_LENGTH]; /* access via eval_hostaddr(host) */
  658. +#ifdef INET6
  659. + struct sockaddr *sin; /* socket address or 0 */
  660. +#else
  661. struct sockaddr_in *sin; /* socket address or 0 */
  662. +#endif
  663. struct t_unitdata *unit; /* TLI transport address or 0 */
  664. struct request_info *request; /* for shared information */
  665. };
  666. Index: src/tcp_wrappers/tcpdchk.c
  667. diff -u src/tcp_wrappers/tcpdchk.c:1.1.1.1 src/tcp_wrappers/tcpdchk.c:1.5
  668. --- src/tcp_wrappers/tcpdchk.c:1.1.1.1 Tue May 4 21:56:04 1999
  669. +++ src/tcp_wrappers/tcpdchk.c Fri May 5 18:28:13 2000
  670. @@ -22,6 +22,9 @@
  671. #include <sys/types.h>
  672. #include <sys/stat.h>
  673. +#ifdef INET6
  674. +#include <sys/socket.h>
  675. +#endif
  676. #include <netinet/in.h>
  677. #include <arpa/inet.h>
  678. #include <stdio.h>
  679. @@ -397,6 +400,31 @@
  680. }
  681. }
  682. +#ifdef INET6
  683. +static int is_inet6_addr(pat)
  684. + char *pat;
  685. +{
  686. + struct addrinfo hints, *res;
  687. + int len, ret;
  688. + char ch;
  689. +
  690. + if (*pat != '[')
  691. + return (0);
  692. + len = strlen(pat);
  693. + if ((ch = pat[len - 1]) != ']')
  694. + return (0);
  695. + pat[len - 1] = '\0';
  696. + memset(&hints, 0, sizeof(hints));
  697. + hints.ai_family = AF_INET6;
  698. + hints.ai_socktype = SOCK_STREAM;
  699. + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
  700. + if ((ret = getaddrinfo(pat + 1, NULL, &hints, &res)) == 0)
  701. + freeaddrinfo(res);
  702. + pat[len - 1] = ch;
  703. + return (ret == 0);
  704. +}
  705. +#endif
  706. +
  707. /* check_host - criticize host pattern */
  708. static int check_host(pat)
  709. @@ -423,14 +451,27 @@
  710. #endif
  711. #endif
  712. } else if (mask = split_at(pat, '/')) { /* network/netmask */
  713. +#ifdef INET6
  714. + int mask_len;
  715. +
  716. + if ((dot_quad_addr(pat) == INADDR_NONE
  717. + || dot_quad_addr(mask) == INADDR_NONE)
  718. + && (!is_inet6_addr(pat)
  719. + || ((mask_len = atoi(mask)) < 0 || mask_len > 128)))
  720. +#else
  721. if (dot_quad_addr(pat) == INADDR_NONE
  722. || dot_quad_addr(mask) == INADDR_NONE)
  723. +#endif
  724. tcpd_warn("%s/%s: bad net/mask pattern", pat, mask);
  725. } else if (STR_EQ(pat, "FAIL")) { /* obsolete */
  726. tcpd_warn("FAIL is no longer recognized");
  727. tcpd_warn("(use EXCEPT or DENY instead)");
  728. } else if (reserved_name(pat)) { /* other reserved */
  729. /* void */ ;
  730. +#ifdef INET6
  731. + } else if (is_inet6_addr(pat)) { /* IPv6 address */
  732. + addr_count = 1;
  733. +#endif
  734. } else if (NOT_INADDR(pat)) { /* internet name */
  735. if (pat[strlen(pat) - 1] == '.') {
  736. tcpd_warn("%s: domain or host name ends in dot", pat);
  737. Index: src/tcp_wrappers/tcpdmatch.c
  738. diff -u src/tcp_wrappers/tcpdmatch.c:1.1.1.1 src/tcp_wrappers/tcpdmatch.c:1.7
  739. --- src/tcp_wrappers/tcpdmatch.c:1.1.1.1 Tue May 4 21:56:04 1999
  740. +++ src/tcp_wrappers/tcpdmatch.c Fri May 5 19:06:40 2000
  741. @@ -57,7 +57,11 @@
  742. int argc;
  743. char **argv;
  744. {
  745. +#ifdef INET6
  746. + struct addrinfo hints, *hp, *res;
  747. +#else
  748. struct hostent *hp;
  749. +#endif
  750. char *myname = argv[0];
  751. char *client;
  752. char *server;
  753. @@ -68,8 +72,13 @@
  754. int ch;
  755. char *inetcf = 0;
  756. int count;
  757. +#ifdef INET6
  758. + struct sockaddr_storage server_sin;
  759. + struct sockaddr_storage client_sin;
  760. +#else
  761. struct sockaddr_in server_sin;
  762. struct sockaddr_in client_sin;
  763. +#endif
  764. struct stat st;
  765. /*
  766. @@ -172,13 +181,20 @@
  767. if (NOT_INADDR(server) == 0 || HOSTNAME_KNOWN(server)) {
  768. if ((hp = find_inet_addr(server)) == 0)
  769. exit(1);
  770. +#ifndef INET6
  771. memset((char *) &server_sin, 0, sizeof(server_sin));
  772. server_sin.sin_family = AF_INET;
  773. +#endif
  774. request_set(&request, RQ_SERVER_SIN, &server_sin, 0);
  775. +#ifdef INET6
  776. + for (res = hp, count = 0; res; res = res->ai_next, count++) {
  777. + memcpy(&server_sin, res->ai_addr, res->ai_addrlen);
  778. +#else
  779. for (count = 0; (addr = hp->h_addr_list[count]) != 0; count++) {
  780. memcpy((char *) &server_sin.sin_addr, addr,
  781. sizeof(server_sin.sin_addr));
  782. +#endif
  783. /*
  784. * Force evaluation of server host name and address. Host name
  785. @@ -194,7 +210,11 @@
  786. fprintf(stderr, "Please specify an address instead\n");
  787. exit(1);
  788. }
  789. +#ifdef INET6
  790. + freeaddrinfo(hp);
  791. +#else
  792. free((char *) hp);
  793. +#endif
  794. } else {
  795. request_set(&request, RQ_SERVER_NAME, server, 0);
  796. }
  797. @@ -208,6 +228,18 @@
  798. tcpdmatch(&request);
  799. exit(0);
  800. }
  801. +#ifdef INET6
  802. + memset(&hints, 0, sizeof(hints));
  803. + hints.ai_family = AF_INET6;
  804. + hints.ai_socktype = SOCK_STREAM;
  805. + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
  806. + if (getaddrinfo(client, NULL, &hints, &res) == 0) {
  807. + freeaddrinfo(res);
  808. + request_set(&request, RQ_CLIENT_ADDR, client, 0);
  809. + tcpdmatch(&request);
  810. + exit(0);
  811. + }
  812. +#endif
  813. /*
  814. * Perhaps they are testing special client hostname patterns that aren't
  815. @@ -229,6 +261,34 @@
  816. */
  817. if ((hp = find_inet_addr(client)) == 0)
  818. exit(1);
  819. +#ifdef INET6
  820. + request_set(&request, RQ_CLIENT_SIN, &client_sin, 0);
  821. +
  822. + for (res = hp, count = 0; res; res = res->ai_next, count++) {
  823. + memcpy(&client_sin, res->ai_addr, res->ai_addrlen);
  824. +
  825. + /*
  826. + * getnameinfo() doesn't do reverse lookup against link-local
  827. + * address. So, we pass through host name evaluation against
  828. + * such addresses.
  829. + */
  830. + if (res->ai_family != AF_INET6 ||
  831. + !IN6_IS_ADDR_LINKLOCAL(&((struct sockaddr_in6 *)res->ai_addr)->sin6_addr)) {
  832. + /*
  833. + * Force evaluation of client host name and address. Host name
  834. + * conflicts will be reported while eval_hostname() does its job.
  835. + */
  836. + request_set(&request, RQ_CLIENT_NAME, "", RQ_CLIENT_ADDR, "", 0);
  837. + if (STR_EQ(eval_hostname(request.client), unknown))
  838. + tcpd_warn("host address %s->name lookup failed",
  839. + eval_hostaddr(request.client));
  840. + }
  841. + tcpdmatch(&request);
  842. + if (res->ai_next)
  843. + printf("\n");
  844. + }
  845. + freeaddrinfo(hp);
  846. +#else
  847. memset((char *) &client_sin, 0, sizeof(client_sin));
  848. client_sin.sin_family = AF_INET;
  849. request_set(&request, RQ_CLIENT_SIN, &client_sin, 0);
  850. @@ -250,6 +310,7 @@
  851. printf("\n");
  852. }
  853. free((char *) hp);
  854. +#endif
  855. exit(0);
  856. }
  857. Index: src/tcp_wrappers/tli.c
  858. diff -u src/tcp_wrappers/tli.c:1.1.1.1 src/tcp_wrappers/tli.c:1.4
  859. --- src/tcp_wrappers/tli.c:1.1.1.1 Tue May 4 21:56:04 1999
  860. +++ src/tcp_wrappers/tli.c Fri May 5 19:15:09 2000
  861. @@ -65,8 +65,13 @@
  862. void tli_host(request)
  863. struct request_info *request;
  864. {
  865. +#ifdef INET6
  866. + static struct sockaddr_storage client;
  867. + static struct sockaddr_storage server;
  868. +#else
  869. static struct sockaddr_in client;
  870. static struct sockaddr_in server;
  871. +#endif
  872. /*
  873. * If we discover that we are using an IP transport, pretend we never
  874. @@ -76,14 +81,29 @@
  875. tli_endpoints(request);
  876. if ((request->config = tli_transport(request->fd)) != 0
  877. +#ifdef INET6
  878. + && (STR_EQ(request->config->nc_protofmly, "inet") ||
  879. + STR_EQ(request->config->nc_protofmly, "inet6"))) {
  880. +#else
  881. && STR_EQ(request->config->nc_protofmly, "inet")) {
  882. +#endif
  883. if (request->client->unit != 0) {
  884. +#ifdef INET6
  885. + client = *(struct sockaddr_storage *) request->client->unit->addr.buf;
  886. + request->client->sin = (struct sockaddr *) &client;
  887. +#else
  888. client = *(struct sockaddr_in *) request->client->unit->addr.buf;
  889. request->client->sin = &client;
  890. +#endif
  891. }
  892. if (request->server->unit != 0) {
  893. +#ifdef INET6
  894. + server = *(struct sockaddr_storage *) request->server->unit->addr.buf;
  895. + request->server->sin = (struct sockaddr *) &server;
  896. +#else
  897. server = *(struct sockaddr_in *) request->server->unit->addr.buf;
  898. request->server->sin = &server;
  899. +#endif
  900. }
  901. tli_cleanup(request);
  902. sock_methods(request);
  903. @@ -187,7 +207,15 @@
  904. }
  905. while (config = getnetconfig(handlep)) {
  906. if (stat(config->nc_device, &from_config) == 0) {
  907. +#ifdef NO_CLONE_DEVICE
  908. + /*
  909. + * If the network devices are not cloned (as is the case for
  910. + * Solaris 8 Beta), we must compare the major device numbers.
  911. + */
  912. + if (major(from_config.st_rdev) == major(from_client.st_rdev))
  913. +#else
  914. if (minor(from_config.st_rdev) == major(from_client.st_rdev))
  915. +#endif
  916. break;
  917. }
  918. }
  919. Index: src/tcp_wrappers/update.c
  920. diff -u src/tcp_wrappers/update.c:1.1.1.1 src/tcp_wrappers/update.c:1.3
  921. --- src/tcp_wrappers/update.c:1.1.1.1 Tue May 4 21:56:04 1999
  922. +++ src/tcp_wrappers/update.c Mon Aug 23 01:32:43 1999
  923. @@ -46,10 +46,18 @@
  924. request->fd = va_arg(ap, int);
  925. continue;
  926. case RQ_CLIENT_SIN:
  927. +#ifdef INET6
  928. + request->client->sin = va_arg(ap, struct sockaddr *);
  929. +#else
  930. request->client->sin = va_arg(ap, struct sockaddr_in *);
  931. +#endif
  932. continue;
  933. case RQ_SERVER_SIN:
  934. +#ifdef INET6
  935. + request->server->sin = va_arg(ap, struct sockaddr *);
  936. +#else
  937. request->server->sin = va_arg(ap, struct sockaddr_in *);
  938. +#endif
  939. continue;
  940. /*
  941. Index: src/tcp_wrappers/workarounds.c
  942. diff -u src/tcp_wrappers/workarounds.c:1.1.1.1 src/tcp_wrappers/workarounds.c:1.3
  943. --- src/tcp_wrappers/workarounds.c:1.1.1.1 Tue May 4 21:56:04 1999
  944. +++ src/tcp_wrappers/workarounds.c Mon Aug 23 01:32:43 1999
  945. @@ -166,11 +166,22 @@
  946. int *len;
  947. {
  948. int ret;
  949. +#ifdef INET6
  950. + struct sockaddr *sin = sa;
  951. +#else
  952. struct sockaddr_in *sin = (struct sockaddr_in *) sa;
  953. +#endif
  954. if ((ret = getpeername(sock, sa, len)) >= 0
  955. +#ifdef INET6
  956. + && ((sin->su_si.si_family == AF_INET6
  957. + && IN6_IS_ADDR_UNSPECIFIED(&sin->su_sin6.sin6_addr))
  958. + || (sin->su_si.si_family == AF_INET
  959. + && sin->su_sin.sin_addr.s_addr == 0))) {
  960. +#else
  961. && sa->sa_family == AF_INET
  962. && sin->sin_addr.s_addr == 0) {
  963. +#endif
  964. errno = ENOTCONN;
  965. return (-1);
  966. } else {
  967. --- src/tcp_wrappers/hosts_access.c 2003-08-04 21:36:20.000000000 +0000
  968. +++ src/tcp_wrappers/hosts_access.c 2003-08-04 21:45:59.000000000 +0000
  969. @@ -24,7 +24,13 @@
  970. /* System libraries. */
  971. #include <sys/types.h>
  972. +#ifdef INT32_T
  973. + typedef uint32_t u_int32_t;
  974. +#endif
  975. #include <sys/param.h>
  976. +#ifdef INET6
  977. +#include <sys/socket.h>
  978. +#endif
  979. #include <netinet/in.h>
  980. #include <arpa/inet.h>
  981. #include <stdio.h>
  982. @@ -33,6 +39,9 @@
  983. #include <errno.h>
  984. #include <setjmp.h>
  985. #include <string.h>
  986. +#ifdef INET6
  987. +#include <netdb.h>
  988. +#endif
  989. extern char *fgets();
  990. extern int errno;
  991. @@ -83,6 +92,10 @@
  992. static int host_match();
  993. static int string_match();
  994. static int masked_match();
  995. +#ifdef INET6
  996. +static int masked_match4();
  997. +static int masked_match6();
  998. +#endif
  999. /* Size of logical line buffer. */
  1000. @@ -312,6 +325,13 @@
  1001. {
  1002. int n;
  1003. +#ifdef INET6
  1004. + /* convert IPv4 mapped IPv6 address to IPv4 address */
  1005. + if (STRN_EQ(string, "::ffff:", 7)
  1006. + && dot_quad_addr(string + 7) != INADDR_NONE) {
  1007. + string += 7;
  1008. + }
  1009. +#endif
  1010. #ifndef DISABLE_WILDCARD_MATCHING
  1011. if (strchr(tok, '*') || strchr(tok,'?')) { /* contains '*' or '?' */
  1012. /* we must convert the both to lowercase as match_pattern_ylo is case-sensitive */
  1013. @@ -333,21 +353,72 @@
  1014. } else if (tok[(n = strlen(tok)) - 1] == '.') { /* prefix */
  1015. return (STRN_EQ(tok, string, n));
  1016. } else { /* exact match */
  1017. +#ifdef INET6
  1018. + struct addrinfo hints, *res;
  1019. + struct sockaddr_in6 pat, addr;
  1020. + int len, ret;
  1021. + char ch;
  1022. +
  1023. + len = strlen(tok);
  1024. + if (*tok == '[' && tok[len - 1] == ']') {
  1025. + ch = tok[len - 1];
  1026. + tok[len - 1] = '\0';
  1027. + memset(&hints, 0, sizeof(hints));
  1028. + hints.ai_family = AF_INET6;
  1029. + hints.ai_socktype = SOCK_STREAM;
  1030. + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
  1031. + if ((ret = getaddrinfo(tok + 1, NULL, &hints, &res)) == 0) {
  1032. + memcpy(&pat, res->ai_addr, sizeof(pat));
  1033. + freeaddrinfo(res);
  1034. + }
  1035. + tok[len - 1] = ch;
  1036. + if (ret != 0 || getaddrinfo(string, NULL, &hints, &res) != 0)
  1037. + return NO;
  1038. + memcpy(&addr, res->ai_addr, sizeof(addr));
  1039. + freeaddrinfo(res);
  1040. +#ifdef NI_WITHSCOPEID
  1041. + if (pat.sin6_scope_id != 0 &&
  1042. + addr.sin6_scope_id != pat.sin6_scope_id)
  1043. + return NO;
  1044. +#endif
  1045. + return (!memcmp(&pat.sin6_addr, &addr.sin6_addr,
  1046. + sizeof(struct in6_addr)));
  1047. + return (ret);
  1048. + }
  1049. +#endif
  1050. return (STR_EQ(tok, string));
  1051. }
  1052. }
  1053. /* masked_match - match address against netnumber/netmask */
  1054. +#ifdef INET6
  1055. static int masked_match(net_tok, mask_tok, string)
  1056. char *net_tok;
  1057. char *mask_tok;
  1058. char *string;
  1059. {
  1060. + return (masked_match4(net_tok, mask_tok, string) ||
  1061. + masked_match6(net_tok, mask_tok, string));
  1062. +}
  1063. +
  1064. +static int masked_match4(net_tok, mask_tok, string)
  1065. +#else
  1066. +static int masked_match(net_tok, mask_tok, string)
  1067. +#endif
  1068. +char *net_tok;
  1069. +char *mask_tok;
  1070. +char *string;
  1071. +{
  1072. +#ifdef INET6
  1073. + u_int32_t net;
  1074. + u_int32_t mask;
  1075. + u_int32_t addr;
  1076. +#else
  1077. unsigned long net;
  1078. unsigned long mask;
  1079. unsigned long addr;
  1080. -
  1081. +#endif
  1082. /*
  1083. * Disallow forms other than dotted quad: the treatment that inet_addr()
  1084. * gives to forms with less than four components is inconsistent with the
  1085. @@ -358,12 +429,81 @@
  1086. return (NO);
  1087. if ((net = dot_quad_addr(net_tok)) == INADDR_NONE
  1088. || (mask = dot_quad_addr(mask_tok)) == INADDR_NONE) {
  1089. +#ifndef INET6
  1090. tcpd_warn("bad net/mask expression: %s/%s", net_tok, mask_tok);
  1091. +#endif
  1092. return (NO); /* not tcpd_jump() */
  1093. }
  1094. return ((addr & mask) == net);
  1095. }
  1096. +#ifdef INET6
  1097. +static int masked_match6(net_tok, mask_tok, string)
  1098. +char *net_tok;
  1099. +char *mask_tok;
  1100. +char *string;
  1101. +{
  1102. + struct addrinfo hints, *res;
  1103. + struct sockaddr_in6 net, addr;
  1104. + u_int32_t mask;
  1105. + int len, mask_len, i = 0;
  1106. + char ch;
  1107. +
  1108. + /*
  1109. + * Behavior of getaddrinfo() against IPv4-mapped IPv6 address is
  1110. + * different between KAME and Solaris8. While KAME returns
  1111. + * AF_INET6, Solaris8 returns AF_INET. So, we avoid this here.
  1112. + */
  1113. + if (STRN_EQ(string, "::ffff:", 7)
  1114. + && dot_quad_addr(string + 7) != INADDR_NONE)
  1115. + return (masked_match4(net_tok, mask_tok, string + 7));
  1116. +
  1117. + memset(&hints, 0, sizeof(hints));
  1118. + hints.ai_family = AF_INET6;
  1119. + hints.ai_socktype = SOCK_STREAM;
  1120. + hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
  1121. + if (getaddrinfo(string, NULL, &hints, &res) != 0)
  1122. + return NO;
  1123. + memcpy(&addr, res->ai_addr, sizeof(addr));
  1124. + freeaddrinfo(res);
  1125. +
  1126. + /* match IPv6 address against netnumber/prefixlen */
  1127. + len = strlen(net_tok);
  1128. + if (*net_tok != '[' || net_tok[len - 1] != ']')
  1129. + return NO;
  1130. + ch = net_tok[len - 1];
  1131. + net_tok[len - 1] = '\0';
  1132. + if (getaddrinfo(net_tok + 1, NULL, &hints, &res) != 0) {
  1133. + net_tok[len - 1] = ch;
  1134. + return NO;
  1135. + }
  1136. + memcpy(&net, res->ai_addr, sizeof(net));
  1137. + freeaddrinfo(res);
  1138. + net_tok[len - 1] = ch;
  1139. + if ((mask_len = atoi(mask_tok)) < 0 || mask_len > 128)
  1140. + return NO;
  1141. +
  1142. +#ifdef NI_WITHSCOPEID
  1143. + if (net.sin6_scope_id != 0 && addr.sin6_scope_id != net.sin6_scope_id)
  1144. + return NO;
  1145. +#endif
  1146. + while (mask_len > 0) {
  1147. + if (mask_len < 32) {
  1148. + mask = htonl(~(0xffffffff >> mask_len));
  1149. + if ((*(u_int32_t *)&addr.sin6_addr.s6_addr[i] & mask) != (*(u_int32_t *)&net.sin6_addr.s6_addr[i] & mask))
  1150. + return NO;
  1151. + break;
  1152. + }
  1153. + if (*(u_int32_t *)&addr.sin6_addr.s6_addr[i] != *(u_int32_t *)&net.sin6_addr.s6_addr[i])
  1154. + return NO;
  1155. + i += 4;
  1156. + mask_len -= 32;
  1157. + }
  1158. + return YES;
  1159. +}
  1160. +#endif /* INET6 */
  1161. +
  1162. +
  1163. #ifndef DISABLE_WILDCARD_MATCHING
  1164. /* Note: this feature has been adapted in a pretty straightforward way
  1165. from Tatu Ylonen's last SSH version under free license by
  1166. --- src/tcp_wrappers/hosts_access.5 2003-08-04 21:52:29.000000000 +0000
  1167. +++ src/tcp_wrappers/hosts_access.5 2003-08-04 21:53:39.000000000 +0000
  1168. @@ -85,7 +85,7 @@
  1169. for daemon process names or for client user names.
  1170. .IP \(bu
  1171. An expression of the form `n.n.n.n/m.m.m.m\' is interpreted as a
  1172. -`net/mask\' pair. A host address is matched if `net\' is equal to the
  1173. +`net/mask\' pair. A IPv4 host address is matched if `net\' is equal to the
  1174. bitwise AND of the address and the `mask\'. For example, the net/mask
  1175. pattern `131.155.72.0/255.255.254.0\' matches every address in the
  1176. range `131.155.72.0\' through `131.155.73.255\'.
  1177. @@ -96,6 +96,13 @@
  1178. zero or more lines with zero or more host name or address patterns
  1179. separated by whitespace. A file name pattern can be used anywhere
  1180. a host name or address pattern can be used.
  1181. +.IP \(bu
  1182. +An expression of the form `[n:n:n:n:n:n:n:n]/m\' is interpreted as a
  1183. +`[net]/prefixlen\' pair. A IPv6 host address is matched if
  1184. +`prefixlen\' bits of `net\' is equal to the `prefixlen\' bits of the
  1185. +address. For example, the [net]/prefixlen pattern
  1186. +`[3ffe:505:2:1::]/64\' matches every address in the range
  1187. +`3ffe:505:2:1::\' through `3ffe:505:2:1:ffff:ffff:ffff:ffff\'.
  1188. .SH WILDCARDS
  1189. The access control language supports explicit wildcards:
  1190. .IP ALL