r23779: Change from v2 or later to v3 or later.
[samba.git] / source3 / lib / wins_srv.c
index adf405ae7e247b55b1f5e339e26e6cdab8129c90..bbde3f85b8c492a9761a81fde38c588744c41549 100644 (file)
@@ -3,10 +3,11 @@
    Samba wins server helper functions
    Copyright (C) Andrew Tridgell 1992-2002
    Copyright (C) Christopher R. Hertel 2000
+   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
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
 
 #include "includes.h"
 
+extern struct in_addr loopback_ip;
+
 /*
-  this is pretty much a complete rewrite of the earlier code. The main
+  This is pretty much a complete rewrite of the earlier code. The main
   aim of the rewrite is to add support for having multiple wins server
   lists, so Samba can register with multiple groups of wins servers
   and each group has a failover list of wins servers.
   confused yet? (tridge)
 */
 
-
 /* how long a server is marked dead for */
 #define DEATH_TIME 600
 
-/* a list of wins server that are marked dead from the point of view
-   of a given source address. We keep a separate dead list for each src address
-   to cope with multiple interfaces that are not routable to each other
+/* The list of dead wins servers is stored in gencache.tdb.  Each server is
+   marked dead from the point of view of a given source address. We keep a 
+   separate dead list for each src address to cope with multiple interfaces 
+   that are not routable to each other.
   */
-static struct wins_dead {
-       struct in_addr dest_ip;
-       struct in_addr src_ip;
-       time_t revival; /* when it will be revived */
-       struct wins_dead *next, *prev;
-} *dead_servers;
 
-/* an internal convenience structure for an IP with a short string tag
-   attached */
-struct tagged_ip {
-       fstring tag;
-       struct in_addr ip;
-};
+#define WINS_SRV_FMT "WINS_SRV_DEAD/%s,%s" /* wins_ip,src_ip */
+
+static char *wins_srv_keystr(struct in_addr wins_ip, struct in_addr src_ip)
+{
+       char *keystr = NULL, *wins_ip_addr = NULL, *src_ip_addr = NULL;
+
+       wins_ip_addr = SMB_STRDUP(inet_ntoa(wins_ip));
+       src_ip_addr = SMB_STRDUP(inet_ntoa(src_ip));
+
+       if ( !wins_ip_addr || !src_ip_addr ) {
+               DEBUG(0,("wins_srv_keystr: malloc error\n"));
+               goto done;
+       }
+
+       if (asprintf(&keystr, WINS_SRV_FMT, wins_ip_addr, src_ip_addr) == -1) {
+               DEBUG(0, (": ns_srv_keystr: malloc error for key string\n"));
+       }
+
+done:
+       SAFE_FREE(wins_ip_addr);
+       SAFE_FREE(src_ip_addr);
+
+       return keystr;
+}
 
 /*
   see if an ip is on the dead list
 */
+
 BOOL wins_srv_is_dead(struct in_addr wins_ip, struct in_addr src_ip)
 {
-       struct wins_dead *d;
-       for (d=dead_servers; d; d=d->next) {
-               if (ip_equal(wins_ip, d->dest_ip) && ip_equal(src_ip, d->src_ip)) {
-                       /* it might be due for revival */
-                       if (d->revival <= time(NULL)) {
-                               fstring src_name;
-                               fstrcpy(src_name, inet_ntoa(src_ip));
-                               DEBUG(4,("Reviving wins server %s for source %s\n", 
-                                        inet_ntoa(wins_ip), src_name));
-                               DLIST_REMOVE(dead_servers, d);
-                               free(d);
-                               return False;
-                       }
-                       return True;
-               }
-       }
-       return False;
+       char *keystr = wins_srv_keystr(wins_ip, src_ip);
+       BOOL result;
+
+       /* If the key exists then the WINS server has been marked as dead */
+
+       result = gencache_get(keystr, NULL, NULL);
+       SAFE_FREE(keystr);
+
+       DEBUG(4, ("wins_srv_is_dead: %s is %s\n", inet_ntoa(wins_ip),
+                 result ? "dead" : "alive"));
+
+       return result;
 }
 
 
@@ -108,45 +119,33 @@ BOOL wins_srv_is_dead(struct in_addr wins_ip, struct in_addr src_ip)
 */
 void wins_srv_alive(struct in_addr wins_ip, struct in_addr src_ip)
 {
-       struct wins_dead *d;
-       for (d=dead_servers; d; d=d->next) {
-               if (ip_equal(wins_ip, d->dest_ip) && ip_equal(src_ip, d->src_ip)) {
-                       fstring src_name;
-                       fstrcpy(src_name, inet_ntoa(src_ip));
-                       DEBUG(4,("Reviving wins server %s for source %s\n", 
-                                inet_ntoa(wins_ip), src_name));
-                       DLIST_REMOVE(dead_servers, d);
-                       return;
-               }
-       }
-}
+       char *keystr = wins_srv_keystr(wins_ip, src_ip);
 
+       gencache_del(keystr);
+       SAFE_FREE(keystr);
+
+       DEBUG(4, ("wins_srv_alive: marking wins server %s alive\n", 
+                 inet_ntoa(wins_ip)));
+}
 
 /*
   mark a wins server as temporarily dead
 */
 void wins_srv_died(struct in_addr wins_ip, struct in_addr src_ip)
 {
-       struct wins_dead *d;
-       fstring src_name;
+       char *keystr;
 
-       if (is_zero_ip(wins_ip) || wins_srv_is_dead(wins_ip, src_ip)) {
+       if (is_zero_ip(wins_ip) || wins_srv_is_dead(wins_ip, src_ip))
                return;
-       }
-
-       d = (struct wins_dead *)malloc(sizeof(*d));
-       if (!d) return;
 
-       d->dest_ip = wins_ip;
-       d->src_ip = src_ip;
-       d->revival = time(NULL) + DEATH_TIME;
+       keystr = wins_srv_keystr(wins_ip, src_ip);
 
-       fstrcpy(src_name, inet_ntoa(src_ip));
+       gencache_set(keystr, "DOWN", time(NULL) + DEATH_TIME);
 
-       DEBUG(4,("Marking wins server %s dead for %u seconds from source %s\n", 
-                inet_ntoa(wins_ip), DEATH_TIME, src_name));
+       SAFE_FREE(keystr);
 
-       DLIST_ADD(dead_servers, d);
+       DEBUG(4,("Marking wins server %s dead for %u seconds from source %s\n",
+                inet_ntoa(wins_ip), DEATH_TIME, inet_ntoa(src_ip)));
 }
 
 /*
@@ -154,7 +153,7 @@ void wins_srv_died(struct in_addr wins_ip, struct in_addr src_ip)
 */
 unsigned wins_srv_count(void)
 {
-       char **list;
+       const char **list;
        int count = 0;
 
        if (lp_wins_support()) {
@@ -163,11 +162,19 @@ unsigned wins_srv_count(void)
        }
 
        list = lp_wins_server_list();
-       for (count=0; list && list[count]; count++) /* nop */ ;
+       for (count=0; list && list[count]; count++)
+               /* nop */ ;
 
        return count;
 }
 
+/* an internal convenience structure for an IP with a short string tag
+   attached */
+struct tagged_ip {
+       fstring tag;
+       struct in_addr ip;
+};
+
 /*
   parse an IP string that might be in tagged format
   the result is a tagged_ip structure containing the tag
@@ -202,20 +209,21 @@ char **wins_srv_tags(void)
 {
        char **ret = NULL;
        int count=0, i, j;
-       char **list;
+       const char **list;
 
        if (lp_wins_support()) {
                /* give the caller something to chew on. This makes
                   the rest of the logic simpler (ie. less special cases) */
-               ret = (char **)malloc(sizeof(char *)*2);
+               ret = SMB_MALLOC_ARRAY(char *, 2);
                if (!ret) return NULL;
-               ret[0] = strdup("*");
+               ret[0] = SMB_STRDUP("*");
                ret[1] = NULL;
                return ret;
        }
 
        list = lp_wins_server_list();
-       if (!list) return NULL;
+       if (!list)
+               return NULL;
 
        /* yes, this is O(n^2) but n is very small */
        for (i=0;list[i];i++) {
@@ -236,8 +244,11 @@ char **wins_srv_tags(void)
                }
 
                /* add it to the list */
-               ret = (char **)Realloc(ret, (count+1) * sizeof(char *));
-               ret[count] = strdup(t_ip.tag);
+               ret = SMB_REALLOC_ARRAY(ret, char *, count+2);
+               if (!ret) {
+                       return NULL;
+               }
+               ret[count] = SMB_STRDUP(t_ip.tag);
                if (!ret[count]) break;
                count++;
        }
@@ -268,13 +279,12 @@ void wins_srv_tags_free(char **list)
 */
 struct in_addr wins_srv_ip_tag(const char *tag, struct in_addr src_ip)
 {
-       char **list;
+       const char **list;
        int i;
        struct tagged_ip t_ip;
 
        /* if we are a wins server then we always just talk to ourselves */
        if (lp_wins_support()) {
-               extern struct in_addr loopback_ip;
                return loopback_ip;
        }
 
@@ -324,7 +334,7 @@ struct in_addr wins_srv_ip_tag(const char *tag, struct in_addr src_ip)
 */
 unsigned wins_srv_count_tag(const char *tag)
 {
-       char **list;
+       const char **list;
        int i, count=0;
 
        /* if we are a wins server then we always just talk to ourselves */