Re: ipv6


Arkadiusz Mi¶kiewicz (misiek@misiek.eu.org)
Wed, 18 Aug 1999 15:05:25 +0200


On Mon, 16 Aug 1999, Martin Schulze wrote:

> Arkadiusz Mi?kiewicz wrote:
> > Someone is working on IPv6 support in cfingerd ?
>
> Please take a look at http://www.Infodrom.North.DE/cfingerd/list/1999/0029.html
> Maybe you can work together.
Maybe but I don't have answer from Brewer Carl, yet ...

But I wroted already IPv6 patch for cfingerd yesterday.
It can handle both IPv4 and IPv6 connections.

To use this patch you must have system with working getaddrinfo(),
getnameinfo(), inet_ntop() and defined struct sockaddr_storage.

I tested this patch on my IPv6 Linux with glibc 2.1.1 (+ getaddrinfo
patch - check my page for it http://www.misiek.eu.org/ipv6/).

rfc1413 connections via IPv6 are supported but not tested by me
since my pidentd+ipv6 doesn't work properly, yet.

Also IPv4-mapped IPv6 addresses are converted to clean IPv4.

And one more thing ... we don't bind to local address in get_rfc1413_data().
What for was that binding ???

ps. my patch removes old network code so patched cfinged will not work
on machines where getnameinfo(), getaddrinfo() .... are missing.
If you want add #ifdef INET6 #else or something ...

>
> Regards,
>
> Joey

-- 
   arkadiusz mi¶kiewicz        [misiek@misiek.eu.org]
PLD/Linux with IPv6 support   http://www.misiek.eu.org/
http://www.ipv6.pld.org.pl/    http://www.pld.org.pl/

; ; IPv6 patch for cfingerd 1.4.0 daemon. ; System with working getaddrinfo(), getnameinfo(), inet_ntop() ; functions and defined struct sockaddr_storage required ; (ie. Linux 2.2.x with glibc 2.1.1) ; ; Arkadiusz Mi¶kiewicz <misiek@pld.org.pl>, PLD/Linux ; Index: cfingerd/CHANGES diff -u cfingerd/CHANGES:1.1.1.1 cfingerd/CHANGES:1.2 --- cfingerd/CHANGES:1.1.1.1 Tue Aug 17 23:11:12 1999 +++ cfingerd/CHANGES Wed Aug 18 12:00:16 1999 @@ -1,3 +1,6 @@ +CFINGERD 1.4.1 ??/??/?? + - IPv6 support + CFINGERD 1.4.0 07/26/99 - New source maintainer - Several bugfixes Index: cfingerd/src/cfingerd.h diff -u cfingerd/src/cfingerd.h:1.1.1.1 cfingerd/src/cfingerd.h:1.2 --- cfingerd/src/cfingerd.h:1.1.1.1 Tue Aug 17 23:11:12 1999 +++ cfingerd/src/cfingerd.h Wed Aug 18 00:32:08 1999 @@ -276,7 +276,9 @@ extern CONFIG prog_config; extern ECRUFT errors[]; -extern char *remote_addr, *localhost, *ident_user, *ip_address; +extern char *localhost, *ident_user; +extern char remote_addr[100]; +extern char ip_address[100]; extern int trusted_host_num, rejected_host_num, forward_host_num, fakeuser_num, num_finger_sites, num_headers, local_port, remote_port, can_log; Index: cfingerd/src/main.c diff -u cfingerd/src/main.c:1.1.1.1 cfingerd/src/main.c:1.5 --- cfingerd/src/main.c:1.1.1.1 Tue Aug 17 23:11:12 1999 +++ cfingerd/src/main.c Wed Aug 18 12:05:30 1999 @@ -1,6 +1,7 @@ /* * CFINGERD * Main Routine + * IPv6 code Copyright (C) 1999 Arkadiusz Mi¶kiewicz <misiek@pld.org.pl> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -20,7 +21,9 @@ #include "privs.h" CONFIG prog_config; -char *remote_addr, *localhost, *ident_user, *ip_address; +char *localhost, *ident_user; +char remote_addr[100]; +char ip_address[100]; FILE *top_display, *bottom_display, *noname_display, *nouser_display, *rejected_display, *identd_display; BOOL local_finger, emulated; @@ -62,15 +65,8 @@ char line[100], username[80], syslog_str[200]; int un_type; char *cp; - struct sockaddr_in local_addr; - struct servent *serv; + struct sockaddr_storage local_addr; - if ((serv = getservbyname("finger","tcp")) != NULL) - listen_port = serv->s_port; - else - listen_port = htons(79); - listen_addr = htonl(INADDR_ANY); - /* Initialize CFINGERD */ start_handler(); start_cfingerd(); @@ -147,8 +143,7 @@ /* If we're not doing emulated stuff, we can assume that we are running either as a daemon, or under INETD. In that case... */ if (!emulated) { - struct sockaddr_in socket_addr; - struct hostent *host_ent; + struct sockaddr_storage socket_addr; int psize = 0; /* Can't run from command line (but this should already be checked) */ @@ -157,8 +152,17 @@ if (getsockname(0, (struct sockaddr *) &local_addr, &psize)) { syslog(LOG_WARNING, "getsockname: %s", strerror(errno)); local_port = 0; - } else - local_port = ntohs(local_addr.sin_port); + } else { + switch(local_addr.__ss_family) { + case AF_INET: + local_port = ntohs(((struct sockaddr_in *)&local_addr)->sin_port); + break; + case AF_INET6: + local_port = ntohs(((struct sockaddr_in6 *)&local_addr)->sin6_port); + break; + default: + } + } if (getpeername(0, (struct sockaddr *) &socket_addr, &psize)) { printf("Internal error - not running as either a daemon or under INETD.\n"); @@ -166,14 +170,19 @@ closelog(); log(LOG_ERROR, "getpeername: ", strerror(errno)); exit(PROGRAM_BUG); - } else - remote_port = ntohs(socket_addr.sin_port); - - ip_address = inet_ntoa (socket_addr.sin_addr); - - /* Get our host entry */ - host_ent = (struct hostent *) gethostbyaddr((char *) &socket_addr.sin_addr, - sizeof(socket_addr.sin_addr), AF_INET); + } else { + switch(socket_addr.__ss_family) { + case AF_INET: + remote_port = ntohs(((struct sockaddr_in *)&socket_addr)->sin_port); + inet_ntop(AF_INET, &((struct sockaddr_in *)&socket_addr)->sin_addr, ip_address, sizeof(ip_address)); + break; + case AF_INET6: + remote_port = ntohs(((struct sockaddr_in6 *)&socket_addr)->sin6_port); + inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&socket_addr)->sin6_addr, ip_address, sizeof(ip_address)); + break; + default: + } + } /* And get our local-host name */ #ifndef ACTUAL_HOSTNAME @@ -182,16 +191,16 @@ localhost = ACTUAL_HOSTNAME; #endif - /* Make sure we can get the remote host's address name */ - if (host_ent == NULL) { - remote_addr = inettos(socket_addr.sin_addr.s_addr); - syslog(LOG_WARNING, "%s %s", + /* Get our host entry and make sure we can get the remote host's address name */ + if (getnameinfo((struct sockaddr *)&socket_addr, SA_LEN((struct sockaddr *)&socket_addr), + remote_addr, sizeof(remote_addr), NULL, 0, 0) != 0) { + getnameinfo((struct sockaddr *)&socket_addr, SA_LEN((struct sockaddr *)&socket_addr),remote_addr, sizeof(remote_addr), NULL, 0, NI_NUMERICHOST); + syslog(LOG_WARNING, "%s %s", prog_config.p_strings[D_IP_NO_MATCH], remote_addr); if (!(prog_config.config_bits2 & SHOW_IP_MATCH)) CF_ERROR(E_NOIP); - } else - remote_addr = (char *) host_ent->h_name; + } /* Convert any uppercase letters in the hostname to lowercase */ for (cp = remote_addr; *cp; cp++) @@ -202,6 +211,7 @@ if (!strncasecmp(remote_addr, "127.0.0.1", 9) || !strncasecmp(remote_addr, "localhost", 9) || !strncasecmp(remote_addr, "127.0.0.0", 9) || /* KTH 07/26/96 */ + !strncasecmp(remote_addr, "::1", 3) || !strncasecmp(remote_addr, localhost, strlen(localhost))) local_finger = TRUE; else @@ -220,11 +230,14 @@ memset (ident_user, 0, sizeof (ident_user)); strcpy (ident_user, "emulated"); #ifndef ACTUAL_LOOPBACK - remote_addr = "127.0.0.1"; + sprintf(remote_addr, "127.0.0.1"); #else - remote_addr = ACTUAL_LOOPBACK; + sprintf(remote_addr, ACTUAL_LOOPBACK); #endif } + /* If IPv4-mapped IPv6 address convert it to clean IPv4 */ + if (strncmp(remote_addr, "::ffff:", 7) == 0) + strncpy(remote_addr, remote_addr + 7, sizeof(remote_addr)); /* Now, let's check to make sure this site is trusted */ if ((!local_finger) && !emulated) Index: cfingerd/src/options.c diff -u cfingerd/src/options.c:1.1.1.1 cfingerd/src/options.c:1.9 --- cfingerd/src/options.c:1.1.1.1 Tue Aug 17 23:11:12 1999 +++ cfingerd/src/options.c Wed Aug 18 12:27:10 1999 @@ -1,6 +1,7 @@ /* * CFINGERD * Starting option routines + * IPv6 code Copyright (C) 1999 Arkadiusz Mi¶kiewicz <misiek@pld.org.pl> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -28,10 +29,10 @@ { #ifdef DAEMON_MODE pid_t pid; - int i, lsock, fd, clen; + int i, lsock, fd, clen, err = -1; int oval = 1; - struct sockaddr caddr; - struct sockaddr_in laddr; + struct sockaddr_storage caddr; + struct addrinfo hints, *res, *res0; if ((lsock = socket (AF_INET, SOCK_STREAM, 0)) < 0) { syslog (LOG_ERR,"can't open socket: %m"); @@ -43,15 +44,31 @@ exit (1); } - laddr.sin_family = AF_INET; - laddr.sin_addr.s_addr = listen_addr; - laddr.sin_port = listen_port; - - if (bind (lsock, (struct sockaddr *) &laddr, sizeof(laddr)) < 0) { - syslog (LOG_ERR,"can't bind: %m"); - exit (1); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + if(getaddrinfo(NULL, "79", &hints, &res0) < 0) { + syslog(LOG_ERR, "getaddrinfo() failed"); + exit(1); + } else { + for (res = res0; res; res = res->ai_next) { + if (res->ai_family == AF_UNIX) + continue; + if ((lsock = socket (res->ai_family, res->ai_socktype, res->ai_protocol)) < 0) + continue; + if (bind (lsock, res->ai_addr, res->ai_addrlen) == 0) { + err = 0; + break; + } + } + freeaddrinfo(res0); + if (err < 0) { + syslog (LOG_ERR,"can't create socket or bind: %m"); + exit (1); + } } - + if ((pid = fork()) < 0) { syslog (LOG_ERR, "can't fork(): %m"); exit (1); @@ -77,16 +94,43 @@ while (1) { - fd = accept (lsock, &caddr, &clen); + fd = accept (lsock, (struct sockaddr *)&caddr, &clen); if (fd < 0) { if (errno == EPROTO) { - remote_addr = inet_ntoa (((struct sockaddr_in *)&caddr)->sin_addr); + switch(caddr.__ss_family) { + case AF_INET: + inet_ntop(AF_INET, &((struct sockaddr_in *)&caddr)->sin_addr, + remote_addr, sizeof(remote_addr)); + break; + case AF_INET6: + inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&caddr)->sin6_addr, + remote_addr, sizeof(remote_addr)); + /* If IPv4-mapped IPv6 address convert it to clean IPv4 */ + if (strncmp(remote_addr, "::ffff:", 7) == 0) + strncpy(remote_addr, remote_addr + 7, + sizeof(remote_addr)); + break; + default: + } syslog(LOG_ERR,"failed connect (possible port scan) from %s: %m", remote_addr); } continue; + } + switch(caddr.__ss_family) { + case AF_INET: + inet_ntop(AF_INET, &((struct sockaddr_in *)&caddr)->sin_addr, + remote_addr, sizeof(remote_addr)); + break; + case AF_INET6: + inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&caddr)->sin6_addr, + remote_addr, sizeof(remote_addr)); + /* If IPv4-mapped IPv6 address convert it to clean IPv4 */ + if (strncmp(remote_addr, "::ffff:", 7) == 0) + strncpy(remote_addr, remote_addr + 7, sizeof(remote_addr)); + break; + default: } - remote_addr = inet_ntoa (((struct sockaddr_in *)&caddr)->sin_addr); /* * FIXME: Support for tcp wrapper via hosts.allow and .deny is missing Index: cfingerd/src/proto.h diff -u cfingerd/src/proto.h:1.1.1.1 cfingerd/src/proto.h:1.2 --- cfingerd/src/proto.h:1.1.1.1 Tue Aug 17 23:11:12 1999 +++ cfingerd/src/proto.h Wed Aug 18 00:32:09 1999 @@ -45,7 +45,7 @@ void become_nobody(void); void become_user(char *); int wildmat(char *, char *); -char *get_rfc1413_data(struct sockaddr_in ); +char *get_rfc1413_data(struct sockaddr_storage ); void check_unknown(char *); void log(int, char *, char *); void userlog(uid_t, gid_t, char *, char *); Index: cfingerd/src/rfc1413.c diff -u cfingerd/src/rfc1413.c:1.1.1.1 cfingerd/src/rfc1413.c:1.8 --- cfingerd/src/rfc1413.c:1.1.1.1 Tue Aug 17 23:11:12 1999 +++ cfingerd/src/rfc1413.c Wed Aug 18 12:26:19 1999 @@ -1,6 +1,7 @@ /* * CFINGERD * RFC1413 implementation + * IPv6 code Copyright (C) 1999 Arkadiusz Mi¶kiewicz <misiek@pld.org.pl> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,50 +27,43 @@ * contained in a single program. Simple, easy to use. */ #define BUFLEN 256 -char *get_rfc1413_data( struct sockaddr_in local_addr ) +char *get_rfc1413_data( struct sockaddr_storage local_addr ) { - int i, j; - struct sockaddr_in sin; + int j, err, errcon = -1; char buffer[1024], buf[BUFLEN], uname[64], *bleah; char *cp, *xp; - struct servent *serv; + struct addrinfo hints, *res, *res0; bleah = (char *) malloc(BUFLEN); memset(bleah, 0, BUFLEN); - j = socket(AF_INET, SOCK_STREAM, 0); - if (j < 2) { - snprintf(bleah, BUFLEN, "unknown@%s", remote_addr); - syslog(LOG_ERR, "rfc1413-socket: %s", strerror(errno)); - return(bleah); - } - - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = local_addr.sin_addr.s_addr; - i = bind(j, (struct sockaddr *) &sin, sizeof(sin)); - if (i < 0) { - snprintf(bleah, BUFLEN, "unknown@%s", remote_addr); - syslog(LOG_ERR, "rfc1413-socket: %s", strerror(errno)); - return(bleah); - } - - sin.sin_family = AF_INET; - if ((serv = getservbyname("auth","tcp")) != NULL) - sin.sin_port = serv->s_port; + memset(&hints, 0, sizeof(hints)); + /* If IPv4-mapped IPv6 address use AF_INET family */ + if ((local_addr.__ss_family == AF_INET6) && IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&local_addr)->sin6_addr)) + hints.ai_family = AF_INET; else - sin.sin_port = htons(113); - sin.sin_addr.s_addr = inet_addr(ip_address); + hints.ai_family = local_addr.__ss_family; + hints.ai_socktype = SOCK_STREAM; + if((err = getaddrinfo(remote_addr, "113", &hints, &res0)) < 0) { + syslog(LOG_ERR, "rfc1413-getaddrinfo: %s", gai_strerror(err)); + snprintf(bleah, BUFLEN, "unknown@%s", remote_addr); + alarm(0); + return(bleah); + } signal(SIGALRM, rfc1413_alarm); alarm(5); - i = connect(j, (struct sockaddr *) &sin, sizeof(sin)); - if (i < 0) { - syslog(LOG_ERR, "rfc1413-connect: %s", strerror(errno)); - close(j); - snprintf(bleah, BUFLEN, "unknown@%s", remote_addr); - alarm(0); - return(bleah); + for (res = res0; res; res = res->ai_next) { + if ((j = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0) + continue; + if (connect(j, res->ai_addr, res->ai_addrlen) < 0) + close(j); + else { + errcon = 0; + break; + } } + freeaddrinfo(res0); snprintf(buffer, sizeof(buffer), "%d,%d\n", remote_port, local_port); write(j, buffer, strlen(buffer));

--M9NhX3UHpAaciwkO--



This archive was generated by hypermail 2.0b3 on Wed Aug 18 1999 - 15:46:57 CEST