10_usagi-ipv6 34 KB

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