+ ocs = ldb_msg_find_element(mp, "objectClass");
+ if (ocs->num_values == 1) { /* Only top */
+ ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_map_add: Added fallback record");
+ return ldb_next_add_record(module, msg);
+ }
+
+ /*
+ * - try to map as much attributes as possible where allowed and add them to mp_msg
+ * - add other attributes to fb_msg
+ */
+ for (i = 0; i < msg->num_elements; i++) {
+ const struct ldb_map_attribute *attr;
+ struct ldb_message_element *elm;
+ enum ldb_map_attr_type map_type;
+ int j;
+ int mapped = 0;
+
+ if (ldb_attr_cmp(msg->elements[i].name, "objectClass") == 0)
+ continue;
+
+ attr = map_find_attr_local(privdat, msg->elements[i].name);
+
+ if (!attr) {
+ ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Undefined local attribute '%s', ignoring\n", msg->elements[i].name);
+ map_type = MAP_IGNORE;
+ } else map_type = attr->type;
+
+ /* Decide whether or not we need to map or fallback */
+ switch (map_type) {
+ case MAP_GENERATE:
+ attr->u.generate.generate_remote(module, attr->local_name, msg, mp, fb);
+ continue;
+ case MAP_KEEP:
+ mapped = map_msg_valid_attr(module, mp, attr->local_name);
+ case MAP_IGNORE: mapped = 0; break;
+ case MAP_CONVERT:
+ case MAP_RENAME: mapped = map_msg_valid_attr(module, mp, attr->u.rename.remote_name);
+ break;
+ }
+
+ if (mapped) {
+ switch (map_type) {
+ case MAP_KEEP:
+ elm = talloc(fb, struct ldb_message_element);
+
+ elm->num_values = msg->elements[i].num_values;
+ elm->values = talloc_reference(elm, msg->elements[i].values);
+ elm->name = talloc_strdup(elm, msg->elements[i].name);
+ break;
+
+ case MAP_RENAME:
+ elm = talloc(mp, struct ldb_message_element);
+
+ elm->name = talloc_strdup(elm, attr->u.rename.remote_name);
+ elm->num_values = msg->elements[i].num_values;
+ elm->values = talloc_reference(elm, msg->elements[i].values);
+ break;
+
+ case MAP_CONVERT:
+ elm = talloc(mp, struct ldb_message_element);
+
+ elm->name = talloc_strdup(elm, attr->u.rename.remote_name);
+ elm->num_values = msg->elements[i].num_values;
+ elm->values = talloc_array(elm, struct ldb_val, elm->num_values);
+
+ for (j = 0; j < elm->num_values; j++) {
+ elm->values[j] = attr->u.convert.convert_local(module, mp, &msg->elements[i].values[j]);
+ }
+
+ mapped = map_msg_valid_attr(module, mp, attr->u.convert.remote_name);
+
+ break;
+
+ case MAP_GENERATE:
+ case MAP_IGNORE:
+ ldb_debug(module->ldb, LDB_DEBUG_FATAL, "This line should never be reached");
+ break;
+ }
+ ldb_msg_add(module->ldb, mp, elm, 0);
+ } else {
+ elm = talloc(fb, struct ldb_message_element);
+
+ elm->num_values = msg->elements[i].num_values;
+ elm->values = talloc_reference(elm, msg->elements[i].values);
+ elm->name = talloc_strdup(elm, msg->elements[i].name);
+
+ ldb_msg_add(module->ldb, fb, elm, 0);
+ }
+ }
+
+ ret = ldb_add(privdat->mapped_ldb, mp);
+ if (ret == -1) {
+ ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Adding mapped record failed: %s", ldb_errstring(privdat->mapped_ldb));
+ return -1;
+ }
+
+ ldb_debug(module->ldb, LDB_DEBUG_TRACE, "ldb_map_add: Added mapped record");
+
+ ldb_msg_add_string(module->ldb, fb, "isMapped", "TRUE");
+ ret = ldb_next_add_record(module, fb);
+ if (ret == -1) {
+ ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Adding fallback record failed: %s", ldb_next_errstring(module));
+ return -1;
+ }
+
+ talloc_free(fb);