Update nsstest to cope with wins NSS module as well as winbind NSS
[kai/samba.git] / source3 / torture / nsstest.c
index a82fa05203e270ab3d850f1a45d18881f4b0978e..d23ac82f3292970da0ed838d7f2ba002b5e289cd 100644 (file)
@@ -2,6 +2,7 @@
    Unix SMB/CIFS implementation.
    nss tester for winbindd
    Copyright (C) Andrew Tridgell 2001
+   Copyright (C) Tim Potter 2003
    
    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
@@ -44,6 +45,7 @@ static void *find_fn(const char *name)
        res = sys_dlsym(h, s);
        if (!res) {
                printf("Can't find function %s\n", s);
+               total_errors++;
                return NULL;
        }
        return res;
@@ -65,6 +67,9 @@ static struct passwd *nss_getpwent(void)
        static char buf[1000];
        NSS_STATUS status;
 
+       if (!_nss_getpwent_r)
+               return NULL;
+
        status = _nss_getpwent_r(&pwd, buf, sizeof(buf), &nss_errno);
        if (status == NSS_STATUS_NOTFOUND) {
                return NULL;
@@ -83,6 +88,9 @@ static struct passwd *nss_getpwnam(const char *name)
        static struct passwd pwd;
        static char buf[1000];
        NSS_STATUS status;
+
+       if (!_nss_getpwnam_r)
+               return NULL;
        
        status = _nss_getpwnam_r(name, &pwd, buf, sizeof(buf), &nss_errno);
        if (status == NSS_STATUS_NOTFOUND) {
@@ -102,6 +110,9 @@ static struct passwd *nss_getpwuid(uid_t uid)
        static struct passwd pwd;
        static char buf[1000];
        NSS_STATUS status;
+
+       if (!_nss_getpwuid_r)
+               return NULL;
        
        status = _nss_getpwuid_r(uid, &pwd, buf, sizeof(buf), &nss_errno);
        if (status == NSS_STATUS_NOTFOUND) {
@@ -118,6 +129,10 @@ static void nss_setpwent(void)
 {
        NSS_STATUS (*_nss_setpwent)(void) = find_fn("setpwent");
        NSS_STATUS status;
+       
+       if (!_nss_setpwent)
+               return;
+
        status = _nss_setpwent();
        if (status != NSS_STATUS_SUCCESS) {
                report_nss_error("setpwent", status);
@@ -128,6 +143,10 @@ static void nss_endpwent(void)
 {
        NSS_STATUS (*_nss_endpwent)(void) = find_fn("endpwent");
        NSS_STATUS status;
+
+       if (!_nss_endpwent)
+               return;
+
        status = _nss_endpwent();
        if (status != NSS_STATUS_SUCCESS) {
                report_nss_error("endpwent", status);
@@ -144,7 +163,11 @@ static struct group *nss_getgrent(void)
        static int buflen = 1024;
        NSS_STATUS status;
 
-       if (!buf) buf = malloc(buflen);
+       if (!_nss_getgrent_r)
+               return NULL;
+
+       if (!buf) 
+               buf = malloc(buflen);
 
 again: 
        status = _nss_getgrent_r(&grp, buf, buflen, &nss_errno);
@@ -172,7 +195,11 @@ static struct group *nss_getgrnam(const char *name)
        static int buflen = 1000;
        NSS_STATUS status;
 
-       if (!buf) buf = malloc(buflen);
+       if (!_nss_getgrnam_r)
+               return NULL;
+
+       if (!buf) 
+               buf = malloc(buflen);
 again: 
        status = _nss_getgrnam_r(name, &grp, buf, buflen, &nss_errno);
        if (status == NSS_STATUS_TRYAGAIN) {
@@ -199,7 +226,12 @@ static struct group *nss_getgrgid(gid_t gid)
        static int buflen = 1000;
        NSS_STATUS status;
        
-       if (!buf) buf = malloc(buflen);
+       if (!_nss_getgrgid_r)
+               return NULL;
+
+       if (!buf) 
+               buf = malloc(buflen);
+
 again: 
        status = _nss_getgrgid_r(gid, &grp, buf, buflen, &nss_errno);
        if (status == NSS_STATUS_TRYAGAIN) {
@@ -221,6 +253,10 @@ static void nss_setgrent(void)
 {
        NSS_STATUS (*_nss_setgrent)(void) = find_fn("setgrent");
        NSS_STATUS status;
+
+       if (!_nss_setgrent)
+               return;
+
        status = _nss_setgrent();
        if (status != NSS_STATUS_SUCCESS) {
                report_nss_error("setgrent", status);
@@ -231,6 +267,10 @@ static void nss_endgrent(void)
 {
        NSS_STATUS (*_nss_endgrent)(void) = find_fn("endgrent");
        NSS_STATUS status;
+
+       if (!_nss_endgrent)
+               return;
+
        status = _nss_endgrent();
        if (status != NSS_STATUS_SUCCESS) {
                report_nss_error("endgrent", status);
@@ -244,7 +284,8 @@ static int nss_initgroups(char *user, gid_t group, gid_t **groups, long int *sta
                find_fn("initgroups_dyn");
        NSS_STATUS status;
 
-       if (!_nss_initgroups) return NSS_STATUS_UNAVAIL;
+       if (!_nss_initgroups) 
+               return NSS_STATUS_UNAVAIL;
 
        status = _nss_initgroups(user, group, start, size, groups, 0, &nss_errno);
        if (status != NSS_STATUS_SUCCESS) {
@@ -284,7 +325,7 @@ static void print_group(struct group *grp)
        printf("%s\n", grp->gr_mem[i]);
 }
 
-static void nss_test_initgroups(char *name, gid_t gid)
+static void nss_test_winbind_initgroups(char *name, gid_t gid)
 {
        long int size = 16;
        long int start = 1;
@@ -308,7 +349,7 @@ static void nss_test_initgroups(char *name, gid_t gid)
 }
 
 
-static void nss_test_users(void)
+static void nss_test_winbind_users(void)
 {
        struct passwd *pwd;
 
@@ -331,13 +372,13 @@ static void nss_test_users(void)
                        continue;
                }
                printf("getpwnam:   "); print_passwd(pwd);
-               printf("initgroups: "); nss_test_initgroups(pwd->pw_name, pwd->pw_gid);
+               printf("initgroups: "); nss_test_winbind_initgroups(pwd->pw_name, pwd->pw_gid);
                printf("\n");
        }
        nss_endpwent();
 }
 
-static void nss_test_groups(void)
+static void nss_test_winbind_groups(void)
 {
        struct group *grp;
 
@@ -365,7 +406,7 @@ static void nss_test_groups(void)
        nss_endgrent();
 }
 
-static void nss_test_errors(void)
+static void nss_test_winbind_errors(void)
 {
        struct passwd *pwd;
        struct group *grp;
@@ -395,15 +436,145 @@ static void nss_test_errors(void)
        }
 }
 
+static struct hostent *nss_gethostbyname(const char *name)
+{
+       NSS_STATUS (*_nss_gethostbyname_r)(const char *, struct hostent *,
+                                          char *, size_t, int *, int *) = 
+               find_fn("gethostbyname_r");
+       NSS_STATUS status;
+       static struct hostent he;
+       static char *buf;
+       static int buflen = 1000;
+       int h_nss_errnop;       /* "Other" error information stored here */
+
+       if (!_nss_gethostbyname_r)
+               return NULL;
+
+       if (!buf)
+               buf = malloc(buflen);
+
+again:
+       status = _nss_gethostbyname_r(
+               name, &he, buf, buflen, &nss_errno, &h_nss_errnop) ;
+
+       if (status == NSS_STATUS_TRYAGAIN) {
+               buflen *= 2;
+               buf = realloc(buf, buflen);
+               goto again;
+       }
+
+       if (status == NSS_STATUS_NOTFOUND) 
+               return NULL;
+
+
+       if (status != NSS_STATUS_SUCCESS) {
+               report_nss_error("gethostbyname", status);
+               return NULL;
+       }
+
+       return &he;
+}
+
+static struct hostent *nss_gethostbyname2(const char *name, int af)
+{
+       NSS_STATUS (*_nss_gethostbyname2_r)(const char *, int, 
+                                           struct hostent *, char *, size_t, 
+                                           int *, int *) = 
+               find_fn("gethostbyname2_r");
+       NSS_STATUS status;
+       static struct hostent he;
+       static char *buf;
+       static int buflen = 1000;
+       int h_nss_errnop;       /* "Other" error information stored here */
+
+       if (!_nss_gethostbyname2_r)
+               return NULL;
+
+       if (!buf)
+               buf = malloc(buflen);
+
+again:
+       status = _nss_gethostbyname2_r(
+               name, af, &he, buf, buflen, &nss_errno, &h_nss_errnop) ;
+
+       if (status == NSS_STATUS_TRYAGAIN) {
+               buflen *= 2;
+               buf = realloc(buf, buflen);
+               goto again;
+       }
+
+       if (status == NSS_STATUS_NOTFOUND) 
+               return NULL;
+
+
+       if (status != NSS_STATUS_SUCCESS) {
+               report_nss_error("gethostbyname2", status);
+               return NULL;
+       }
+
+       return &he;
+}
+
+static void nss_test_wins(void)
+{
+       fstring myname;
+       struct hostent *he;
+
+       /* Try testing with our hostname.  This will probably work if
+           Samba is/was running on the local machine. */
+
+       memset(myname, 0, sizeof(myname));
+       if (gethostname(myname, sizeof(myname) - 1) == -1) {
+               printf("gethostname() failed!");
+               total_errors++;
+               return;
+       }
+
+       /* Test gethostbyname */
+
+       if ((he = nss_gethostbyname(myname))) {
+               struct in_addr **ip_list = (struct in_addr **)he->h_addr_list;
+
+               while (*ip_list) {
+                       printf("gethostbyname: %s has ip %s\n", myname, 
+                              inet_ntoa(**ip_list));
+                       *ip_list++;
+               }
+       } else
+               printf("hostname %s not found with gethostbyname\n", myname);
+
+       /* Test gethostbyname2 */
+
+       if ((he = nss_gethostbyname2(myname, AF_INET))) {
+               struct in_addr **ip_list = (struct in_addr **)he->h_addr_list;
+
+               while (*ip_list) {
+                       printf("gethostbyname2: %s has ip %s\n", myname, 
+                              inet_ntoa(**ip_list));
+                       *ip_list++;
+               }
+       } else
+               printf("hostname %s not found with gethostbyname2\n", myname);
+}
+
  int main(int argc, char *argv[])
 {      
        if (argc > 1) so_path = argv[1];
        if (argc > 2) nss_name = argv[2];
 
-       nss_test_users();
-       nss_test_groups();
-       nss_test_errors();
+       if (strequal(nss_name, "winbind")) {
+               nss_test_winbind_users();
+               nss_test_winbind_groups();
+               nss_test_winbind_errors();
+               goto done;
+       }
 
+       if (strequal(nss_name, "wins")) {
+               nss_test_wins();
+               goto done;
+       }
+               
+done:
        printf("total_errors=%d\n", total_errors);
 
        return total_errors;