idmap_autorid: add idmap_autorid_iterate_domain_ranges[_read]()
authorMichael Adam <obnox@samba.org>
Tue, 17 Sep 2013 23:54:58 +0000 (01:54 +0200)
committerMichael Adam <obnox@samba.org>
Tue, 1 Oct 2013 08:49:25 +0000 (10:49 +0200)
Functions to perform an action on all domain range mappings for
a given domain, specified by the domain sid.

Inspired by a previous patch by Atul Kulkarni <atul.kulkarni@in.ibm.com>.

Signed-off-by: Michael Adam <obnox@samba.org>
source3/include/idmap_autorid.h
source3/winbindd/idmap_autorid_tdb.c

index 61cf2385e856e858b29ec824d643815ff6917f4b..512453c9c423d80cf185e43c5bbef61b56223529 100644 (file)
@@ -157,4 +157,35 @@ bool idmap_autorid_parse_configstr(const char *configstr,
 NTSTATUS idmap_autorid_saveconfigstr(struct db_context *db,
                                     const char *configstr);
 
+
+/**
+ * idmap_autorid_iterate_domain_ranges:
+ * perform an action on all domain range mappings for a given domain
+ * specified by domain sid.
+ */
+NTSTATUS idmap_autorid_iterate_domain_ranges(struct db_context *db,
+                                       const char *domsid,
+                                       NTSTATUS (*fn)(struct db_context *db,
+                                                      const char *domsid,
+                                                      uint32_t index,
+                                                      uint32_t rangenum,
+                                                      void *private_data),
+                                       void *private_data,
+                                       int *count);
+
+/**
+ * idmap_autorid_iterate_domain_ranges_read:
+ * perform a read only action on all domain range mappings for a given domain
+ * specified by domain sid.
+ */
+NTSTATUS idmap_autorid_iterate_domain_ranges_read(struct db_context *db,
+                                       const char *domsid,
+                                       NTSTATUS (*fn)(struct db_context *db,
+                                                      const char *domsid,
+                                                      uint32_t index,
+                                                      uint32_t rangenum,
+                                                      void *private_data),
+                                       void *private_data,
+                                       int *count);
+
 #endif /* _IDMAP_AUTORID_H_ */
index b40e527e5960ad246faacc1e63275bf0e463b30e..d5c5cc4e92913f9d7d88bb38a6cf21b087e46b82 100644 (file)
@@ -977,3 +977,194 @@ NTSTATUS idmap_autorid_saveconfigstr(struct db_context *db,
        status = idmap_autorid_saveconfig(db, &cfg);
        return status;
 }
+
+
+/*
+ * iteration: Work on all range mappings for a given domain
+ */
+
+struct domain_range_visitor_ctx {
+       const char *domsid;
+       NTSTATUS (*fn)(struct db_context *db,
+                      const char *domsid,
+                      uint32_t index,
+                      uint32_t rangenum,
+                      void *private_data);
+       void *private_data;
+       int count; /* number of records worked on */
+};
+
+static int idmap_autorid_visit_domain_range(struct db_record *rec,
+                                           void *private_data)
+{
+       struct domain_range_visitor_ctx *vi;
+       char *domsid;
+       char *sep;
+       uint32_t range_index = 0;
+       uint32_t rangenum = 0;
+       TDB_DATA key, value;
+       NTSTATUS status;
+       int ret = 0;
+       struct db_context *db;
+
+       vi = talloc_get_type_abort(private_data,
+                                  struct domain_range_visitor_ctx);
+
+       if (vi->domsid == NULL) {
+               DEBUG(1, ("Error: no domain sid provided\n"));
+               return -1;
+       }
+
+       if (vi->fn == NULL) {
+               DEBUG(1, ("Error: missing visitor callback\n"));
+               return -1;
+       }
+
+       key = dbwrap_record_get_key(rec);
+
+       /*
+        * split string "<sid>[#<index>]" into sid string and index number
+        */
+
+       domsid = (char *)key.dptr;
+
+       DEBUG(10, ("idmap_autorid_visit_domain_range: visiting key '%s'\n", domsid));
+
+       sep = strrchr(domsid, '#');
+       if (sep != NULL) {
+               char *index_str;
+               *sep = '\0';
+               index_str = sep+1;
+               if (sscanf(index_str, "%"SCNu32, &range_index) != 1) {
+                       DEBUG(3, ("Error parsing domain range index part of "
+                                 "record\n"));
+                       goto done;
+               }
+       }
+
+       if (!idmap_autorid_validate_sid(domsid)) {
+               DEBUG(3, ("Invalid sid string found in record\n"));
+               goto done;
+       }
+
+       if (strcmp(domsid, vi->domsid) != 0) {
+               DEBUG(10, ("key sid '%s' does not match requested sid '%s'\n",
+                          domsid, vi->domsid));
+               goto done;
+       }
+
+       value = dbwrap_record_get_value(rec);
+       rangenum = IVAL(value.dptr, 0);
+
+       db = dbwrap_record_get_db(rec);
+
+       status = vi->fn(db, domsid, range_index, rangenum, vi->private_data);
+       if (!NT_STATUS_IS_OK(status)) {
+               ret = -1;
+               goto done;
+       }
+
+       vi->count++;
+       ret = 0;
+
+done:
+       return ret;
+}
+
+static NTSTATUS idmap_autorid_iterate_domain_ranges_int(struct db_context *db,
+                               const char *domsid,
+                               NTSTATUS (*fn)(struct db_context *db,
+                                              const char *domsid,
+                                              uint32_t index,
+                                              uint32_t rangnum,
+                                              void *private_data),
+                               void *private_data,
+                               int *count,
+                               NTSTATUS (*traverse)(struct db_context *db,
+                                         int (*f)(struct db_record *, void *),
+                                         void *private_data,
+                                         int *count))
+{
+       NTSTATUS status;
+       struct domain_range_visitor_ctx *vi;
+       TALLOC_CTX *frame = talloc_stackframe();
+
+       vi = talloc_zero(frame, struct domain_range_visitor_ctx);
+       if (vi == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
+
+       if (domsid == NULL) {
+               DEBUG(1, ("Error: no domain sid provided\n"));
+               status = NT_STATUS_INVALID_PARAMETER;
+               goto done;
+       }
+
+       vi->domsid = talloc_strdup(vi, domsid);
+       if (vi->domsid == NULL) {
+               status = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
+
+       vi->fn = fn;
+       vi->private_data = private_data;
+
+       status = traverse(db, idmap_autorid_visit_domain_range, vi, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               goto done;
+       }
+
+       if (count != NULL) {
+               *count = vi->count;
+       }
+
+done:
+       talloc_free(frame);
+       return status;
+}
+
+NTSTATUS idmap_autorid_iterate_domain_ranges(struct db_context *db,
+                                       const char *domsid,
+                                       NTSTATUS (*fn)(struct db_context *db,
+                                                      const char *domsid,
+                                                      uint32_t index,
+                                                      uint32_t rangenum,
+                                                      void *private_data),
+                                       void *private_data,
+                                       int *count)
+{
+       NTSTATUS status;
+
+       status = idmap_autorid_iterate_domain_ranges_int(db,
+                                                        domsid,
+                                                        fn,
+                                                        private_data,
+                                                        count,
+                                                        dbwrap_traverse);
+
+       return status;
+}
+
+
+NTSTATUS idmap_autorid_iterate_domain_ranges_read(struct db_context *db,
+                                       const char *domsid,
+                                       NTSTATUS (*fn)(struct db_context *db,
+                                                      const char *domsid,
+                                                      uint32_t index,
+                                                      uint32_t rangenum,
+                                                      void *count),
+                                       void *private_data,
+                                       int *count)
+{
+       NTSTATUS status;
+
+       status = idmap_autorid_iterate_domain_ranges_int(db,
+                                                        domsid,
+                                                        fn,
+                                                        private_data,
+                                                        count,
+                                                        dbwrap_traverse_read);
+
+       return status;
+}