diff --git a/CHANGES.txt b/CHANGES.txt
index d6c85480fdc36e304e07301fa411146320add1c0..dd140addb49479697308018647561d1a0535d428 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -95,6 +95,9 @@ to sigfind.
 
 7/13/09: Bug Fix: Fixed issue  2821031 re: missing fls -m fields.
 
+7/21/09: Update: Resolved Feature request 2206331 re: indirect blocks
+in UFS/Ext2.
+
 
 ---------------- VERSION 3.0.1 -------------- 
 11/11/08: Bug Fix: Fixed crashing bug in ifind on FAT file system.
diff --git a/tsk3/fs/ext2fs.c b/tsk3/fs/ext2fs.c
index e2e9634c9c9094d2c32f3c2424ebcd4e299fd7e2..2a341f5b6f877be0f066271349dcee8539cfd627 100644
--- a/tsk3/fs/ext2fs.c
+++ b/tsk3/fs/ext2fs.c
@@ -111,8 +111,7 @@ ext2fs_group_load(EXT2FS_INFO * ext2fs, EXT2_GRPNUM_T grp_num)
         tsk_fprintf(stderr,
             "\tgroup %" PRI_EXT2GRP ": %" PRIu16 "/%" PRIu16
             " free blocks/inodes\n", grp_num, tsk_getu16(fs->endian,
-                gd->
-                bg_free_blocks_count),
+                gd->bg_free_blocks_count),
             tsk_getu16(fs->endian, gd->bg_free_inodes_count));
     }
 
@@ -1375,8 +1374,7 @@ ext2fs_fsstat(TSK_FS_INFO * fs, FILE * hFile)
                 (cg_base != tsk_getu32(fs->endian,
                         ext2fs->grp_buf->bg_block_bitmap)))
             || ((tsk_getu32(fs->endian,
-                        ext2fs->fs->
-                        s_feature_ro_compat) &
+                        ext2fs->fs->s_feature_ro_compat) &
                     EXT2FS_FEATURE_RO_COMPAT_SPARSE_SUPER) == 0)) {
 
             TSK_OFF_T boff;
@@ -1597,6 +1595,7 @@ ext2fs_istat(TSK_FS_INFO * fs, FILE * hFile, TSK_INUM_T inum,
     TSK_FS_FILE *fs_file;
     char ls[12];
     EXT2FS_PRINT_ADDR print;
+    const TSK_FS_ATTR *fs_attr_indir;
 
     // clean up any error messages that are lying around
     tsk_error_reset();
@@ -1958,6 +1957,24 @@ ext2fs_istat(TSK_FS_INFO * fs, FILE * hFile, TSK_INUM_T inum,
         tsk_fprintf(hFile, "\n");
     }
 
+    fs_attr_indir = tsk_fs_file_attr_get_type(fs_file,
+        TSK_FS_ATTR_TYPE_UNIX_INDIR, 0, 0);
+    if (fs_attr_indir) {
+        tsk_fprintf(hFile, "\nIndirect Blocks:\n");
+
+        print.idx = 0;
+
+        if (tsk_fs_attr_walk(fs_attr_indir, TSK_FS_FILE_WALK_FLAG_AONLY,
+                print_addr_act, (void *) &print)) {
+            tsk_fprintf(hFile, "\nError reading indirect attribute:  ");
+            tsk_error_print(hFile);
+            tsk_error_reset();
+        }
+        else if (print.idx != 0) {
+            tsk_fprintf(hFile, "\n");
+        }
+    }
+
     tsk_fs_file_close(fs_file);
     return 0;
 }
@@ -2230,8 +2247,7 @@ ext2fs_open(TSK_IMG_INFO * img_info, TSK_OFF_T offset,
         tsk_fprintf(stderr,
             "inodes %" PRIu32 " root ino %" PRIuINUM " blocks %" PRIu32
             " blocks/group %" PRIu32 "\n", tsk_getu32(fs->endian,
-                ext2fs->fs->
-                s_inodes_count),
+                ext2fs->fs->s_inodes_count),
             fs->root_inum, tsk_getu32(fs->endian,
                 ext2fs->fs->s_blocks_count), tsk_getu32(fs->endian,
                 ext2fs->fs->s_blocks_per_group));
diff --git a/tsk3/fs/ffs.c b/tsk3/fs/ffs.c
index 6df6df319651ba7870b505826464c7f32aaa9bdd..3887cfa4254ab68c004829cdfd03d5b6cabe7a50 100644
--- a/tsk3/fs/ffs.c
+++ b/tsk3/fs/ffs.c
@@ -1642,6 +1642,7 @@ ffs_istat(TSK_FS_INFO * fs, FILE * hFile, TSK_INUM_T inum,
     TSK_FS_FILE *fs_file;
     char ls[12];
     FFS_PRINT_ADDR print;
+    const TSK_FS_ATTR *fs_attr_indir;
 
     // clean up any error messages that are lying around
     tsk_error_reset();
@@ -1825,6 +1826,24 @@ ffs_istat(TSK_FS_INFO * fs, FILE * hFile, TSK_INUM_T inum,
     if (print.idx != 0)
         tsk_fprintf(hFile, "\n");
 
+    fs_attr_indir = tsk_fs_file_attr_get_type(fs_file,
+        TSK_FS_ATTR_TYPE_UNIX_INDIR, 0, 0);
+    if (fs_attr_indir) {
+        tsk_fprintf(hFile, "\nIndirect Blocks:\n");
+
+        print.idx = 0;
+
+        if (tsk_fs_attr_walk(fs_attr_indir, TSK_FS_FILE_WALK_FLAG_AONLY,
+                print_addr_act, (void *) &print)) {
+            tsk_fprintf(hFile, "\nError reading indirect attribute:  ");
+            tsk_error_print(hFile);
+            tsk_error_reset();
+        }
+        else if (print.idx != 0) {
+            tsk_fprintf(hFile, "\n");
+        }
+    }
+
     tsk_fs_file_close(fs_file);
     return 0;
 }
diff --git a/tsk3/fs/fs_attrlist.c b/tsk3/fs/fs_attrlist.c
index a31e9548d32118909fa205a88c011f4582330273..7dc2106afae14e1c4bb1ae33990b81b0d53b0b46 100644
--- a/tsk3/fs/fs_attrlist.c
+++ b/tsk3/fs/fs_attrlist.c
@@ -167,7 +167,8 @@ tsk_fs_attrlist_getnew(TSK_FS_ATTRLIST * a_fs_attrlist,
                 return NULL;
 
             // add it to the list
-            tsk_fs_attrlist_add(a_fs_attrlist, fs_attr_cur);
+            if (tsk_fs_attrlist_add(a_fs_attrlist, fs_attr_cur))
+                return NULL;
         }
     }
 
diff --git a/tsk3/fs/ifind_lib.c b/tsk3/fs/ifind_lib.c
index bbfadbaec51ed8f09a320c8ef9c14923645f5257..e0e75ebe3f684ef272d13a0c7e685614643532b1 100644
--- a/tsk3/fs/ifind_lib.c
+++ b/tsk3/fs/ifind_lib.c
@@ -552,13 +552,12 @@ ifind_data_act(TSK_FS_FILE * fs_file, void *ptr)
             data->curtype = fs_attr->type;
             data->curid = fs_attr->id;
             if (fs_attr->flags & TSK_FS_ATTR_NONRES) {
-                if (tsk_fs_file_walk_type(fs_file, fs_attr->type,
-                        fs_attr->id, file_flags, ifind_data_file_ntfs_act,
-                        ptr)) {
+                if (tsk_fs_attr_walk(fs_attr,
+                        file_flags, ifind_data_file_ntfs_act, ptr)) {
                     if (tsk_verbose)
                         tsk_fprintf(stderr,
-                            "Error walking file %" PRIuINUM,
-                            fs_file->meta->addr);
+                            "Error walking file %" PRIuINUM
+                            " Attribute: %i", fs_file->meta->addr, i);
 
                     /* Ignore these errors */
                     tsk_error_reset();
@@ -584,7 +583,8 @@ ifind_data_act(TSK_FS_FILE * fs_file, void *ptr)
      * correlated with the incorrect inode
      */
     else {
-        // @@@ Need to add handling back in here to find indirect blocks (once a soln is found)
+        const TSK_FS_ATTR *fs_attr;
+
         if (tsk_fs_file_walk(fs_file, file_flags,
                 ifind_data_file_act, ptr)) {
             if (tsk_verbose)
@@ -594,6 +594,25 @@ ifind_data_act(TSK_FS_FILE * fs_file, void *ptr)
             /* Ignore these errors */
             tsk_error_reset();
         }
+
+
+        // try the indirect blocks
+        fs_attr = tsk_fs_file_attr_get_type(fs_file,
+            TSK_FS_ATTR_TYPE_UNIX_INDIR, 0, 0);
+        if (fs_attr) {
+            data->curtype = fs_attr->type;
+            data->curid = fs_attr->id;
+
+            if (tsk_fs_attr_walk(fs_attr,
+                    file_flags, ifind_data_file_act, ptr)) {
+                if (tsk_verbose)
+                    tsk_fprintf(stderr,
+                        "Error walking file %" PRIuINUM
+                        " Indirect Attribute", fs_file->meta->addr);
+                /* Ignore these errors */
+                tsk_error_reset();
+            }
+        }
     }
 
     return TSK_WALK_CONT;
diff --git a/tsk3/fs/tsk_fs.h b/tsk3/fs/tsk_fs.h
index c6f8a0ffd98c516d0b873739ec67d47ada2badf6..160d1f97a166d9c3c20664f8f9608c5ebcae7b36 100644
--- a/tsk3/fs/tsk_fs.h
+++ b/tsk3/fs/tsk_fs.h
@@ -201,7 +201,7 @@ extern "C" {
      * These are based on the NTFS type values. 
      */
     typedef enum {
-        TSK_FS_ATTR_TYPE_DEFAULT = 0x0, // 16
+        TSK_FS_ATTR_TYPE_DEFAULT = 0x01,        // 1
         TSK_FS_ATTR_TYPE_NTFS_SI = 0x10,        // 16
         TSK_FS_ATTR_TYPE_NTFS_ATTRLIST = 0x20,  // 32
         TSK_FS_ATTR_TYPE_NTFS_FNAME = 0x30,     // 48
@@ -219,7 +219,8 @@ extern "C" {
         TSK_FS_ATTR_TYPE_NTFS_EAINFO = 0xD0,    // 208
         TSK_FS_ATTR_TYPE_NTFS_EA = 0xE0,        // 224
         TSK_FS_ATTR_TYPE_NTFS_PROP = 0xF0,      //  (NT)
-        TSK_FS_ATTR_TYPE_NTFS_LOG = 0x100       //  (2K)
+        TSK_FS_ATTR_TYPE_NTFS_LOG = 0x100,      //  (2K)
+        TSK_FS_ATTR_TYPE_UNIX_INDIR = 0x1001    //  Indirect blocks for UFS and ExtX file systems
     } TSK_FS_ATTR_TYPE_ENUM;
 
 #define TSK_FS_ATTR_ID_DEFAULT  0       ///< Default Data ID used if file system does not assign one.
diff --git a/tsk3/fs/unix_misc.c b/tsk3/fs/unix_misc.c
index cc5f94b03e1115de5a293c537e8196583facd6ec..24b26d9bf45f907d280d3d50ac085afcdd9ecdeb 100644
--- a/tsk3/fs/unix_misc.c
+++ b/tsk3/fs/unix_misc.c
@@ -109,6 +109,7 @@ unix_make_data_run_direct(TSK_FS_INFO * fs, TSK_FS_ATTR * fs_attr,
  *
  * @param fs File system to analyze
  * @param fs_attr Structure to save run data into
+ * @param fs_attr_indir Structure to save addresses of indirect block pointers in
  * @param buf Buffers to read block data into (0 is block sized, 1+ are DADDR_T arrays based on FS type)
  * @param level Indirection level that this will process at (1+)
  * @param addr Address of block to read
@@ -118,7 +119,8 @@ unix_make_data_run_direct(TSK_FS_INFO * fs, TSK_FS_ATTR * fs_attr,
  */
 static TSK_OFF_T
 unix_make_data_run_indirect(TSK_FS_INFO * fs, TSK_FS_ATTR * fs_attr,
-    char *buf[], int level, TSK_DADDR_T addr, TSK_OFF_T length)
+    TSK_FS_ATTR * fs_attr_indir, char *buf[], int level, TSK_DADDR_T addr,
+    TSK_OFF_T length)
 {
     char *myname = "unix_make_data_run_indirect";
     size_t addr_cnt = 0;
@@ -126,17 +128,21 @@ unix_make_data_run_indirect(TSK_FS_INFO * fs, TSK_FS_ATTR * fs_attr,
     TSK_OFF_T length_remain = length;
     TSK_OFF_T retval;
     size_t fs_bufsize;
+    size_t fs_blen;
+    TSK_FS_ATTR_RUN *data_run;
 
     if (tsk_verbose)
         tsk_fprintf(stderr, "%s: level %d block %" PRIuDADDR "\n", myname,
             level, addr);
 
+    // block_size is a fragment size in UFS, so we need to maintain length in fragments
     if (TSK_FS_TYPE_ISFFS(fs->ftype)) {
         FFS_INFO *ffs = (FFS_INFO *) fs;
-
+        fs_blen = ffs->ffsbsize_f;
         fs_bufsize = ffs->ffsbsize_b;
     }
     else {
+        fs_blen = 1;
         fs_bufsize = fs->block_size;
     }
 
@@ -149,12 +155,21 @@ unix_make_data_run_indirect(TSK_FS_INFO * fs, TSK_FS_ATTR * fs_attr,
         return -1;
     }
 
+    // make a non-resident run
+    data_run = tsk_fs_attr_run_alloc();
+    if (data_run == NULL)
+        return -1;
+
+    data_run->addr = addr;
+    data_run->len = fs_blen;
+
     /*
      * Read a block of disk addresses.
      */
     // sparse
     if (addr == 0) {
         memset(buf[0], 0, fs_bufsize);
+        data_run->flags = TSK_FS_ATTR_RUN_FLAG_SPARSE;
     }
     else {
         ssize_t cnt;
@@ -169,10 +184,11 @@ unix_make_data_run_indirect(TSK_FS_INFO * fs, TSK_FS_ATTR * fs_attr,
                 "unix_make_data_run_indir: Block %" PRIuDADDR, addr);
             return -1;
         }
-
-        // @@@ what do we do about META....
     }
 
+    // save the run
+    tsk_fs_attr_append_run(fs, fs_attr_indir, data_run);
+
     // convert the raw addresses to the correct endian ordering
     if ((fs->ftype == TSK_FS_TYPE_FFS1)
         || (fs->ftype == TSK_FS_TYPE_FFS1B)
@@ -207,8 +223,8 @@ unix_make_data_run_indirect(TSK_FS_INFO * fs, TSK_FS_ATTR * fs_attr,
         retval = 0;
         for (i = 0; i < addr_cnt && retval != -1; i++) {
             retval =
-                unix_make_data_run_indirect(fs, fs_attr, buf, level - 1,
-                myaddrs[i], length_remain);
+                unix_make_data_run_indirect(fs, fs_attr, fs_attr_indir,
+                buf, level - 1, myaddrs[i], length_remain);
             if (retval == -1) {
                 break;
             }
@@ -235,6 +251,7 @@ tsk_fs_unix_make_data_run(TSK_FS_FILE * fs_file)
     TSK_OFF_T length = 0;
     TSK_OFF_T read_b = 0;
     TSK_FS_ATTR *fs_attr;
+    TSK_FS_ATTR *fs_attr_indir;
     TSK_FS_META *fs_meta = fs_file->meta;
     TSK_FS_INFO *fs = fs_file->fs_info;
 
@@ -304,6 +321,12 @@ tsk_fs_unix_make_data_run(TSK_FS_FILE * fs_file)
         char **buf;
         size_t fs_bufsize0;
         size_t fs_bufsize1;
+        int ptrsperblock;
+        int numBlocks = 0;
+        int numSingIndirect = 0;
+        int numDblIndirect = 0;
+        int numTripIndirect = 0;
+
 
         /* With FFS/UFS a full block contains the addresses, but block_size is
          * only a fragment.  Figure out the scratch buffer size and the buffers to 
@@ -313,15 +336,18 @@ tsk_fs_unix_make_data_run(TSK_FS_FILE * fs_file)
 
             fs_bufsize0 = ffs->ffsbsize_b;
             if ((fs->ftype == TSK_FS_TYPE_FFS1)
-                || (fs->ftype == TSK_FS_TYPE_FFS1B))
-                fs_bufsize1 = sizeof(TSK_DADDR_T) * ffs->ffsbsize_b / 4;
-            else
-                fs_bufsize1 = sizeof(TSK_DADDR_T) * ffs->ffsbsize_b / 8;
+                || (fs->ftype == TSK_FS_TYPE_FFS1B)) {
+                ptrsperblock = fs_bufsize0 / 4;
+            }
+            else {
+                ptrsperblock = fs_bufsize0 / 8;
+            }
         }
         else {
             fs_bufsize0 = fs->block_size;
-            fs_bufsize1 = sizeof(TSK_DADDR_T) * fs->block_size / 4;
+            ptrsperblock = fs_bufsize0 / 4;
         }
+        fs_bufsize1 = sizeof(TSK_DADDR_T) * ptrsperblock;
 
         /*
          * Initialize a buffer for the 3 levels of indirection that are supported by
@@ -339,6 +365,42 @@ tsk_fs_unix_make_data_run(TSK_FS_FILE * fs_file)
             return 1;
         }
 
+        if ((fs_attr_indir =
+                tsk_fs_attrlist_getnew(fs_meta->attr,
+                    TSK_FS_ATTR_NONRES)) == NULL) {
+            free(buf);
+            return 1;
+        }
+
+        // determine number of indirect lbocks needed for file size...
+        numBlocks = ((fs_meta->size + fs_bufsize0 - 1) / fs_bufsize0) - 12;
+        numSingIndirect = (numBlocks + ptrsperblock - 1) / ptrsperblock;
+        numDblIndirect = 0;
+        numTripIndirect = 0;
+
+        // double block pointer?
+        if (numSingIndirect > 1) {
+            numDblIndirect =
+                (numSingIndirect - 1 + ptrsperblock - 1) / ptrsperblock;
+            if (numDblIndirect > 1) {
+                numTripIndirect =
+                    (numDblIndirect - 1 + ptrsperblock - 1) / ptrsperblock;
+            }
+        }
+
+        // initialize the data run
+        if (tsk_fs_attr_set_run(fs_file, fs_attr_indir, NULL, NULL,
+                TSK_FS_ATTR_TYPE_UNIX_INDIR, TSK_FS_ATTR_ID_DEFAULT,
+                fs_bufsize0 * (numSingIndirect + numDblIndirect +
+                    numTripIndirect),
+                fs_bufsize0 * (numSingIndirect + numDblIndirect +
+                    numTripIndirect),
+                fs_bufsize0 * (numSingIndirect + numDblIndirect +
+                    numTripIndirect), 0, 0)) {
+            free(buf);
+            return 1;
+        }
+
         for (level = 1; length > 0 && level < 4; level++) {
             TSK_DADDR_T *addr_ptr = (TSK_DADDR_T *) fs_meta->content_ptr;
 
@@ -353,8 +415,8 @@ tsk_fs_unix_make_data_run(TSK_FS_FILE * fs_file)
             /* the indirect addresses are stored in addr_ptr after the 12
              * direct addresses */
             read_b =
-                unix_make_data_run_indirect(fs, fs_attr, buf, level,
-                addr_ptr[12 + level - 1], length);
+                unix_make_data_run_indirect(fs, fs_attr, fs_attr_indir,
+                buf, level, addr_ptr[12 + level - 1], length);
             if (read_b == -1)
                 break;
             length -= read_b;