Bug 4606 - wins nsswitch reverse lookup
wins nsswitch reverse lookup
Status: NEW
Product: Samba 3.0
Classification: Unclassified
Component: winbind
3.0.24
x86 Linux
: P3 minor
: none
Assigned To: Samba Bugzilla Account
Samba QA Contact
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2007-05-10 03:05 UTC by Peter Eser
Modified: 2009-04-04 08:02 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Peter Eser 2007-05-10 03:05:20 UTC
reverse name lookup (gethostbyaddr) seems not to function with wins in host entry in nsswitch.conf.
Is this feature not implemented?
We solved the issue for us with patching nsswitch/wins.c
Found an old solaris patch (sorry, lost the name originator) and 
modified it to run with 3.0.24 for our purposes.

I don't think the patch is fully ok for general purpose use!!!
The if:   (status[i].flags & 0x80 || !(status[i].type == 0x20 ||
status[i].type = 0x00 ) )
is modified for our purposes by try and error, I don't know what flags and
type would be the correct ones (I think they come from windows (e.g. NetBios
Client type)?).

Here's the patch, mainly the new function  _nss_wins_gethostbyaddr_r against
3.0.24:

*** nsswitch/wins.c.org 2007-05-08 08:51:30.000000000 +0200
+++ nsswitch/wins.c 2007-05-08 11:42:14.000000000 +0200
@@ -125,8 +125,6 @@
  return ret;
 }

-#ifdef HAVE_NS_API_H
-
 static NODE_STATUS_STRUCT *lookup_byaddr_backend(char *addr, int *count)
 {
  int fd;
@@ -150,6 +148,8 @@
  return status;
 }

+#ifdef HAVE_NS_API_H
+
 /* IRIX version */

 int init(void)
@@ -375,4 +375,105 @@
  return _nss_wins_gethostbyname_r(
   name, he, buffer, buflen, h_errnop);
 }
+
+
/***************************************************************************
*
+  gethostbyaddr()
+
**************************************************************************/
+  NSS_STATUS
+  _nss_wins_gethostbyaddr_r(const char *addr, int length, int type,
+       struct hostent *he, char *buffer, size_t buflen,
+       int *errnop, int *h_errnop)
+  {
+   enum { AddressStringSize = 16 };
+   char **host_addresses, **host_aliases;
+   char address_string[AddressStringSize];
+   NODE_STATUS_STRUCT *status;
+   int i, rc, count, true_count;
+   size_t namelen;
+
+   memset(he, '\0', sizeof(*he));
+
+   /* I don't think you can do WINS over IPV6 - fv */
+   if (length != INADDRSZ || type != AF_INET) {
+    return NSS_STATUS_NOTFOUND;
+   }
+
+   rc = snprintf(address_string, AddressStringSize, "%d.%d.%d.%d",
+    (uchar) addr[0], (uchar) addr[1], (uchar) addr[2],
+    (uchar) addr[3]);
+   if (rc < 0 || rc > AddressStringSize) {
+    return NSS_STATUS_NOTFOUND;
+   }
+
+   status = lookup_byaddr_backend(address_string, &count);
+   if (!status) {
+    return NSS_STATUS_NOTFOUND;
+   }
+
+   true_count = 0;
+   for (i=0;i<count;i++) {
+    /* ignore group names */
+    if (status[i].flags & 0x80 || !(status[i].type == 0x20 ||
status[i].type == 0x00 ) ) continue;
+    ++true_count;
+   }
+
+   if (true_count < 1) {
+    return NSS_STATUS_NOTFOUND;
+   }
+   if (buflen < (true_count+3)*INADDRSZ) {
+    /* no ENOMEM error type?! */
+    return NSS_STATUS_NOTFOUND;
+   }
+   host_addresses = (char **)buffer;
+   he->h_addr_list = host_addresses;
+   buffer += 2 * INADDRSZ;
+   buflen -= 2 * INADDRSZ;
+   host_addresses[0] = buffer;
+   host_addresses[1] = NULL;
+   memcpy(buffer, addr, INADDRSZ);
+   buffer += INADDRSZ;
+   buflen -= INADDRSZ;
+   he->h_addrtype = AF_INET;
+   he->h_length = INADDRSZ;
+
+   if (true_count == 1) {
+    he->h_aliases = host_addresses + 1;
+   } else {
+    host_aliases = (char **)buffer;
+    he->h_aliases = host_aliases;
+    host_aliases[true_count-1] = NULL;
+    buffer += true_count * INADDRSZ;
+    buflen -= true_count * INADDRSZ;
+   }
+
+   true_count = 0;
+   for (i=0;i<count;i++) {
+    /* ignore group names */
+    if (status[i].flags & 0x80 || !(status[i].type == 0x20 ||
status[i].type == 0x00 ) ) continue;
+    /* assume first name is 'canonical' name */
+    if (true_count == 0) {
+     he->h_name = buffer;
+    } else {
+     *host_aliases = buffer;
+     host_aliases++;
+    }
+    namelen = strlen(status[i].name);
+    if (buflen < namelen + 1) {
+     /* no ENOMEM error type?! */
+     return NSS_STATUS_NOTFOUND;
+    }
+    memcpy(buffer, &status[i].name, namelen);
+    buffer += namelen;
+    *buffer = '\0';
+    buffer++;
+    buflen -= namelen + 1;
+    true_count++;
+   }
+
+   if (status)
+    free(status);
+
+   return NSS_STATUS_SUCCESS;
+  }
+
 #endif
Comment 1 Gerald (Jerry) Carter 2007-05-10 07:19:34 UTC
please include the patch as an attachment and not an inline comment.  Thanks.