File net-tools-1.60-hostname-ipv6.patch of Package net-tools

--- hostname.c
+++ hostname.c	2010/07/20 12:25:42
@@ -79,6 +79,7 @@ static void setnname(char *nname)
             fprintf(stderr, _("%s: name too long\n"), program_name);
             break;
         default:
+	    break;
         }
 	exit(1);
     }
@@ -125,49 +126,171 @@ static void setdname(char *dname)
     };
 }
 
+struct alias_t {
+    char            name[NI_MAXHOST];
+    struct alias_t *next;
+};
+struct aliases_t {
+    struct alias_t *head;
+    struct alias_t *tail;
+};
+
+static void aliases_add(struct aliases_t *aliases, char *alias)
+{
+    struct alias_t *a;
+    int      f = 0;
+
+    if( !aliases || !alias || !*alias)
+	return;
+
+    for(a=aliases->head; !f && a; a=a->next) {
+	f = (strcasecmp(a->name, alias) == 0);
+    }
+    if(!f) {
+	a = calloc(1, sizeof(struct alias_t));
+	if( a) {
+	    strncat(a->name, alias, sizeof(a->name)-1);
+	    if (aliases->tail) {
+		aliases->tail->next = a;
+		aliases->tail = a;
+	    } else {
+		aliases->head = a;
+		aliases->tail = a;
+	    }
+	}
+    }
+}
+
 static void showhname(char *hname, int c)
 {
-    struct hostent *hp;
+    struct addrinfo hints;
+    struct addrinfo *res=NULL, *rp;
     register char *p, **alias;
-    struct in_addr **ip;
+    int    ret, retry=3;
+    size_t n;
 
     if (opt_v)
 	fprintf(stderr, _("Resolving `%s' ...\n"), hname);
-    if (!(hp = gethostbyname(hname))) {
-	herror(program_name);
+
+    memset(&hints, 0, sizeof(struct addrinfo));
+    hints.ai_family   = AF_UNSPEC;
+    hints.ai_flags    = AI_CANONNAME | AI_CANONIDN;
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_protocol = 0;
+    do {
+	ret = getaddrinfo(hname, NULL, &hints, &res);
+    } while(ret == EAI_AGAIN && retry-- > 0
+                             && usleep(50000) == 0);
+
+    if (ret != 0 || res == NULL) {
+	fprintf(stderr, _("%s: %s\n"),
+	    program_name, gai_strerror(ret));
 	exit(1);
     }
+
     if (opt_v) {
-	fprintf(stderr, _("Result: h_name=`%s'\n"),
-		hp->h_name);
+	for(n=0, rp=res; rp; rp=rp->ai_next, n++) {
+	    char        buf[INET6_ADDRSTRLEN] = {'\0'};
+	    const char *str = NULL;
+	    const char *typ = NULL;
+	    const void *adr = NULL;
+
+	    if(rp->ai_canonname)
+		fprintf(stderr, _("Result: ai_canonname[%zd]=`%s'\n"),
+		                n, rp->ai_canonname);
+
+	    switch(rp->ai_addr->sa_family) {
+	    case AF_INET:
+		typ = "ipv4";
+		adr = &(((struct sockaddr_in *)rp->ai_addr)->sin_addr);
+		break;
+	    case AF_INET6:
+		typ = "ipv6";
+		adr = &(((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr);
+		break;
+	    }
+	    if( !adr)
+		continue;
+
+	    if(opt_v > 1)
+		fprintf(stderr, _("Result: ai_addrtype[%zd]=`%s'\n"), n, typ);
 
-	alias = hp->h_aliases;
-	while (alias[0])
-	    fprintf(stderr, _("Result: h_aliases=`%s'\n"),
-		    *alias++);
-
-	ip = (struct in_addr **) hp->h_addr_list;
-	while (ip[0])
-	    fprintf(stderr, _("Result: h_addr_list=`%s'\n"),
-		    inet_ntoa(**ip++));
+	    str = inet_ntop(rp->ai_addr->sa_family,
+	                    adr, buf, sizeof(buf));
+	    if(str)
+		fprintf(stderr, _("Result: ai_addr[%zd]=`%s'\n"), n, str);
+	}
     }
-    if (!(p = strchr(hp->h_name, '.')) && (c == 'd'))
+    if (!(p = strchr(res->ai_canonname, '.')) && (c == 'd')) {
+	freeaddrinfo(res);
 	return;
+    }
 
     switch (c) {
-    case 'a':
-	while (hp->h_aliases[0]) {
-	    printf("%s", *hp->h_aliases++);
-	    if (hp->h_aliases[0])
-	        printf(" ");
+    case 'a': {
+	/*
+	** getaddrinfo / getnameinfo do not provide aliases,
+	** so we have to fetch them using gethostbyaddr ...
+	*/
+	struct aliases_t aliases = { NULL, NULL };
+	struct alias_t  *a;
+
+	for(n=0, rp=res; rp; rp=rp->ai_next, n++) {
+	    struct hostent *hp;
+	    const void     *adr = NULL;
+            socklen_t       len;
+
+	    switch(rp->ai_addr->sa_family) {
+	    case AF_INET:
+		adr = &(((struct sockaddr_in *)rp->ai_addr)->sin_addr);
+		len = sizeof(struct in_addr);
+		break;
+	    case AF_INET6:
+		adr = &(((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr);
+		len = sizeof(struct in6_addr);
+		break;
+	    }
+	    if( !adr)
+		continue;
+
+	    hp = gethostbyaddr(adr, len, rp->ai_addr->sa_family);
+	    if(hp) {
+		for(alias = hp->h_aliases; alias && *alias; alias++) {
+			if(opt_v)
+			    fprintf(stderr, _("Result: h_aliases[%zd]=`%s'\n"),
+			            n, *alias);
+			aliases_add(&aliases, *alias);
+		}
+	    }
+	}
+	while( (a=aliases.head)) {
+	    aliases.head = a->next;
+	    printf("%s%s", a->name, (a->next ? " " : ""));
+	    free(a);
 	}
 	printf("\n");
-	break;
+    }	break;
     case 'i':
-	while (hp->h_addr_list[0]) {
-	    printf("%s", inet_ntoa(*(struct in_addr *) *hp->h_addr_list++));
-	    if (hp->h_addr_list[0])
-	        printf(" ");
+	for(n=0, rp=res; rp; rp=rp->ai_next, n++) {
+	    char        buf[INET6_ADDRSTRLEN] = {'\0'};
+	    const char *str = NULL;
+	    const void *adr = NULL;
+
+	    switch(rp->ai_addr->sa_family) {
+	    case AF_INET:
+		adr = &(((struct sockaddr_in *)rp->ai_addr)->sin_addr);
+		break;
+	    case AF_INET6:
+		adr = &(((struct sockaddr_in6 *)rp->ai_addr)->sin6_addr);
+		break;
+	    }
+	    if( !adr)
+		continue;
+
+	    str = inet_ntop(rp->ai_addr->sa_family,
+	                    adr, buf, sizeof(buf));
+	    if(str)
+		printf("%s%s", str, (rp->ai_next ? " " : ""));
 	}
 	printf("\n");
 	break;
@@ -175,16 +298,17 @@ static void showhname(char *hname, int c
 	printf("%s\n", ++p);
 	break;
     case 'f':
-	printf("%s\n", hp->h_name);
+	printf("%s\n", res->ai_canonname);
 	break;
     case 's':
 	if (p != NULL)
 	    *p = '\0';
-	printf("%s\n", hp->h_name);
+	printf("%s\n", res->ai_canonname);
 	break;
     default:
-	return;
+	break;
     }
+    freeaddrinfo(res);
 }
 
 static void setfilename(char *name, int what)
@@ -336,11 +460,12 @@ int main(int argc, char **argv)
 	    break;
 	case 'V':
 	    version();
+	    break; // not reached
 	case '?':
 	case 'h':
 	default:
 	    usage();
-
+	    break; // not reached
 	};
 
 
openSUSE Build Service is sponsored by