LCOV - code coverage report
Current view: top level - libcli/smb - reparse.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 92 283 32.5 %
Date: 2024-04-21 15:09:00 Functions: 6 9 66.7 %

          Line data    Source code
       1             : /*
       2             :  * Unix SMB/CIFS implementation.
       3             :  *
       4             :  * This program is free software; you can redistribute it and/or modify
       5             :  * it under the terms of the GNU General Public License as published by
       6             :  * the Free Software Foundation; either version 3 of the License, or
       7             :  * (at your option) any later version.
       8             :  *
       9             :  * This program is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :  * GNU General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU General Public License
      15             :  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : #include "replace.h"
      19             : #include "libcli/smb/reparse.h"
      20             : #include "lib/util/iov_buf.h"
      21             : #include "libcli/smb/smb_constants.h"
      22             : #include "libcli/util/error.h"
      23             : #include "lib/util/debug.h"
      24             : #include "lib/util/bytearray.h"
      25             : #include "lib/util/talloc_stack.h"
      26             : #include "lib/util/charset/charset.h"
      27             : #include "smb_util.h"
      28             : 
      29           2 : static NTSTATUS reparse_buffer_check(const uint8_t *in_data,
      30             :                                      size_t in_len,
      31             :                                      uint32_t *reparse_tag,
      32             :                                      const uint8_t **_reparse_data,
      33             :                                      size_t *_reparse_data_length)
      34             : {
      35           0 :         uint16_t reparse_data_length;
      36             : 
      37           2 :         if (in_len == 0) {
      38           0 :                 DBG_DEBUG("in_len=0\n");
      39           0 :                 return NT_STATUS_INVALID_BUFFER_SIZE;
      40             :         }
      41           2 :         if (in_len < 8) {
      42           0 :                 DBG_DEBUG("in_len=%zu\n", in_len);
      43           0 :                 return NT_STATUS_IO_REPARSE_DATA_INVALID;
      44             :         }
      45             : 
      46           2 :         reparse_data_length = PULL_LE_U16(in_data, 4);
      47             : 
      48           2 :         if (reparse_data_length > (in_len - 8)) {
      49           0 :                 DBG_DEBUG("in_len=%zu, reparse_data_length=%" PRIu16 "\n",
      50             :                           in_len,
      51             :                           reparse_data_length);
      52           0 :                 return NT_STATUS_IO_REPARSE_DATA_INVALID;
      53             :         }
      54             : 
      55           2 :         *reparse_tag = PULL_LE_U32(in_data, 0);
      56           2 :         *_reparse_data = in_data + 8;
      57           2 :         *_reparse_data_length = reparse_data_length;
      58             : 
      59           2 :         return NT_STATUS_OK;
      60             : }
      61             : 
      62           0 : static int nfs_reparse_buffer_parse(TALLOC_CTX *mem_ctx,
      63             :                                     struct nfs_reparse_data_buffer *dst,
      64             :                                     const uint8_t *src,
      65             :                                     size_t srclen)
      66             : {
      67           0 :         uint64_t type;
      68             : 
      69           0 :         if (srclen < 8) {
      70           0 :                 DBG_DEBUG("srclen=%zu too short\n", srclen);
      71           0 :                 return EINVAL;
      72             :         }
      73             : 
      74           0 :         type = PULL_LE_U64(src, 0);
      75             : 
      76           0 :         switch (type) {
      77           0 :         case NFS_SPECFILE_CHR:
      78           0 :                 FALL_THROUGH;
      79             :         case NFS_SPECFILE_BLK:
      80           0 :                 if (srclen < 16) {
      81           0 :                         DBG_DEBUG("srclen %zu too short for type %" PRIx64 "\n",
      82             :                                   srclen,
      83             :                                   type);
      84           0 :                         return EINVAL;
      85             :                 }
      86           0 :                 dst->data.dev.major = PULL_LE_U32(src, 8);
      87           0 :                 dst->data.dev.minor = PULL_LE_U32(src, 12);
      88           0 :                 break;
      89           0 :         case NFS_SPECFILE_LNK: {
      90           0 :                 bool ok;
      91             : 
      92           0 :                 ok = convert_string_talloc(mem_ctx,
      93             :                                            CH_UTF16,
      94             :                                            CH_UNIX,
      95           0 :                                            src + 8,
      96             :                                            srclen - 8,
      97           0 :                                            &dst->data.lnk_target,
      98             :                                            NULL);
      99           0 :                 if (!ok) {
     100           0 :                         return errno;
     101             :                 }
     102           0 :                 break;
     103             :         }
     104           0 :         case NFS_SPECFILE_FIFO:
     105           0 :                 break; /* empty, no data */
     106           0 :         case NFS_SPECFILE_SOCK:
     107           0 :                 break; /* empty, no data */
     108           0 :         default:
     109           0 :                 DBG_DEBUG("Unknown NFS reparse type %" PRIx64 "\n", type);
     110           0 :                 return EINVAL;
     111             :         }
     112             : 
     113           0 :         dst->type = type;
     114             : 
     115           0 :         return 0;
     116             : }
     117             : 
     118           2 : static int symlink_reparse_buffer_parse(TALLOC_CTX *mem_ctx,
     119             :                                         struct symlink_reparse_struct *dst,
     120             :                                         const uint8_t *src,
     121             :                                         size_t srclen)
     122             : {
     123           0 :         uint16_t reparse_data_length;
     124           0 :         uint16_t substitute_name_offset, substitute_name_length;
     125           0 :         uint16_t print_name_offset, print_name_length;
     126           0 :         bool ok;
     127             : 
     128           2 :         if (srclen < 20) {
     129           0 :                 DBG_DEBUG("srclen = %zu, expected >= 20\n", srclen);
     130           0 :                 return EINVAL;
     131             :         }
     132           2 :         if (PULL_LE_U32(src, 0) != IO_REPARSE_TAG_SYMLINK) {
     133           0 :                 DBG_DEBUG("Got ReparseTag %8.8x, expected %8.8x\n",
     134             :                           PULL_LE_U32(src, 0),
     135             :                           IO_REPARSE_TAG_SYMLINK);
     136           0 :                 return EINVAL;
     137             :         }
     138             : 
     139           2 :         reparse_data_length     = PULL_LE_U16(src, 4);
     140           2 :         substitute_name_offset  = PULL_LE_U16(src, 8);
     141           2 :         substitute_name_length  = PULL_LE_U16(src, 10);
     142           2 :         print_name_offset       = PULL_LE_U16(src, 12);
     143           2 :         print_name_length       = PULL_LE_U16(src, 14);
     144             : 
     145           2 :         if (reparse_data_length < 12) {
     146           0 :                 DBG_DEBUG("reparse_data_length = %"PRIu16", expected >= 12\n",
     147             :                           reparse_data_length);
     148           0 :                 return EINVAL;
     149             :         }
     150           2 :         if (smb_buffer_oob(srclen - 8, reparse_data_length, 0)) {
     151           0 :                 DBG_DEBUG("reparse_data_length (%"PRIu16") too large for "
     152             :                            "src_len (%zu)\n",
     153             :                           reparse_data_length,
     154             :                           srclen);
     155           0 :                 return EINVAL;
     156             :         }
     157           2 :         if (smb_buffer_oob(reparse_data_length - 12, substitute_name_offset,
     158             :                            substitute_name_length)) {
     159           0 :                 DBG_DEBUG("substitute_name (%"PRIu16"/%"PRIu16") does not fit "
     160             :                           "in reparse_data_length (%"PRIu16")\n",
     161             :                           substitute_name_offset,
     162             :                           substitute_name_length,
     163             :                           reparse_data_length - 12);
     164           0 :                 return EINVAL;
     165             :         }
     166           2 :         if (smb_buffer_oob(reparse_data_length - 12, print_name_offset,
     167             :                            print_name_length)) {
     168           0 :                 DBG_DEBUG("print_name (%"PRIu16"/%"PRIu16") does not fit in "
     169             :                           "reparse_data_length (%"PRIu16")\n",
     170             :                           print_name_offset,
     171             :                           print_name_length,
     172             :                           reparse_data_length - 12);
     173           0 :                 return EINVAL;
     174             :         }
     175             : 
     176           2 :         *dst = (struct symlink_reparse_struct) {
     177           2 :                 .unparsed_path_length = PULL_LE_U16(src, 6),
     178           2 :                 .flags = PULL_LE_U32(src, 16),
     179             :         };
     180             : 
     181           2 :         ok = convert_string_talloc(mem_ctx,
     182             :                                    CH_UTF16,
     183             :                                    CH_UNIX,
     184           2 :                                    src + 20 + substitute_name_offset,
     185             :                                    substitute_name_length,
     186           2 :                                    &dst->substitute_name,
     187             :                                    NULL);
     188           2 :         if (!ok) {
     189           0 :                 int ret = errno;
     190           0 :                 DBG_DEBUG("convert_string_talloc for substitute_name "
     191             :                           "failed\n");
     192           0 :                 return ret;
     193             :         }
     194             : 
     195           2 :         ok = convert_string_talloc(mem_ctx,
     196             :                                    CH_UTF16,
     197             :                                    CH_UNIX,
     198           2 :                                    src + 20 + print_name_offset,
     199             :                                    print_name_length,
     200           2 :                                    &dst->print_name,
     201             :                                    NULL);
     202           2 :         if (!ok) {
     203           0 :                 int ret = errno;
     204           0 :                 DBG_DEBUG("convert_string_talloc for print_name failed\n");
     205           0 :                 TALLOC_FREE(dst->substitute_name);
     206           0 :                 return ret;
     207             :         }
     208             : 
     209           2 :         return 0;
     210             : }
     211             : 
     212           2 : NTSTATUS reparse_data_buffer_parse(TALLOC_CTX *mem_ctx,
     213             :                                    struct reparse_data_buffer *dst,
     214             :                                    const uint8_t *buf,
     215             :                                    size_t buflen)
     216             : {
     217           0 :         const uint8_t *reparse_data;
     218           0 :         size_t reparse_data_length;
     219           0 :         NTSTATUS status;
     220           0 :         int ret;
     221             : 
     222           2 :         status = reparse_buffer_check(buf,
     223             :                                       buflen,
     224             :                                       &dst->tag,
     225             :                                       &reparse_data,
     226             :                                       &reparse_data_length);
     227           2 :         if (!NT_STATUS_IS_OK(status)) {
     228           0 :                 return status;
     229             :         }
     230             : 
     231           2 :         switch (dst->tag) {
     232           2 :         case IO_REPARSE_TAG_SYMLINK:
     233           2 :                 ret = symlink_reparse_buffer_parse(mem_ctx,
     234             :                                                    &dst->parsed.lnk,
     235             :                                                    buf,
     236             :                                                    buflen);
     237           2 :                 if (ret != 0) {
     238           0 :                         return map_nt_error_from_unix_common(ret);
     239             :                 }
     240           2 :                 break;
     241           0 :         case IO_REPARSE_TAG_NFS:
     242           0 :                 ret = nfs_reparse_buffer_parse(mem_ctx,
     243             :                                                &dst->parsed.nfs,
     244             :                                                reparse_data,
     245             :                                                reparse_data_length);
     246           0 :                 if (ret != 0) {
     247           0 :                         return map_nt_error_from_unix_common(ret);
     248             :                 }
     249           0 :                 break;
     250           0 :         default:
     251           0 :                 dst->parsed.raw.data = talloc_memdup(mem_ctx,
     252             :                                                      reparse_data,
     253             :                                                      reparse_data_length);
     254           0 :                 if (dst->parsed.raw.data == NULL) {
     255           0 :                         return NT_STATUS_NO_MEMORY;
     256             :                 }
     257           0 :                 dst->parsed.raw.length = reparse_data_length;
     258           0 :                 dst->parsed.raw.reserved = PULL_LE_U16(buf, 6);
     259           0 :                 break;
     260             :         }
     261             : 
     262           2 :         return NT_STATUS_OK;
     263             : }
     264             : 
     265           0 : char *reparse_data_buffer_str(TALLOC_CTX *mem_ctx,
     266             :                               const struct reparse_data_buffer *dst)
     267             : {
     268           0 :         char *s = talloc_strdup(mem_ctx, "");
     269             : 
     270           0 :         switch (dst->tag) {
     271           0 :         case IO_REPARSE_TAG_SYMLINK: {
     272           0 :                 const struct symlink_reparse_struct *lnk = &dst->parsed.lnk;
     273           0 :                 talloc_asprintf_addbuf(&s,
     274             :                                        "0x%" PRIx32
     275             :                                        " (IO_REPARSE_TAG_SYMLINK)\n",
     276           0 :                                        dst->tag);
     277           0 :                 talloc_asprintf_addbuf(&s,
     278             :                                        "unparsed=%" PRIu16 "\n",
     279           0 :                                        lnk->unparsed_path_length);
     280           0 :                 talloc_asprintf_addbuf(&s,
     281             :                                        "substitute_name=%s\n",
     282           0 :                                        lnk->substitute_name);
     283           0 :                 talloc_asprintf_addbuf(&s, "print_name=%s\n", lnk->print_name);
     284           0 :                 talloc_asprintf_addbuf(&s, "flags=%" PRIu32 "\n", lnk->flags);
     285           0 :                 break;
     286             :         }
     287           0 :         case IO_REPARSE_TAG_NFS: {
     288           0 :                 const struct nfs_reparse_data_buffer *nfs = &dst->parsed.nfs;
     289             : 
     290           0 :                 talloc_asprintf_addbuf(&s,
     291             :                                        "0x%" PRIx32 " (IO_REPARSE_TAG_NFS)\n",
     292           0 :                                        dst->tag);
     293             : 
     294           0 :                 switch (nfs->type) {
     295           0 :                 case NFS_SPECFILE_FIFO:
     296           0 :                         talloc_asprintf_addbuf(&s,
     297             :                                                " 0x%" PRIx64
     298             :                                                " (NFS_SPECFILE_FIFO)\n",
     299           0 :                                                nfs->type);
     300           0 :                         break;
     301           0 :                 case NFS_SPECFILE_SOCK:
     302           0 :                         talloc_asprintf_addbuf(&s,
     303             :                                                " 0x%" PRIx64
     304             :                                                " (NFS_SPECFILE_SOCK)\n",
     305           0 :                                                nfs->type);
     306           0 :                         break;
     307           0 :                 case NFS_SPECFILE_LNK:
     308           0 :                         talloc_asprintf_addbuf(&s,
     309             :                                                " 0x%" PRIx64
     310             :                                                " (NFS_SPECFILE_LNK)\n",
     311           0 :                                                nfs->type);
     312           0 :                         talloc_asprintf_addbuf(&s,
     313             :                                                " -> %s\n ",
     314           0 :                                                nfs->data.lnk_target);
     315           0 :                         break;
     316           0 :                 case NFS_SPECFILE_BLK:
     317           0 :                         talloc_asprintf_addbuf(&s,
     318             :                                                " 0x%" PRIx64
     319             :                                                " (NFS_SPECFILE_BLK)\n",
     320           0 :                                                nfs->type);
     321           0 :                         talloc_asprintf_addbuf(&s,
     322             :                                                " %" PRIu32 "/%" PRIu32 "\n",
     323           0 :                                                nfs->data.dev.major,
     324           0 :                                                nfs->data.dev.minor);
     325           0 :                         break;
     326           0 :                 case NFS_SPECFILE_CHR:
     327           0 :                         talloc_asprintf_addbuf(&s,
     328             :                                                " 0x%" PRIx64
     329             :                                                " (NFS_SPECFILE_CHR)\n",
     330           0 :                                                nfs->type);
     331           0 :                         talloc_asprintf_addbuf(&s,
     332             :                                                " %" PRIu32 "/%" PRIu32 "\n",
     333           0 :                                                nfs->data.dev.major,
     334           0 :                                                nfs->data.dev.minor);
     335           0 :                         break;
     336           0 :                 default:
     337           0 :                         talloc_asprintf_addbuf(&s,
     338             :                                                " 0x%" PRIu64
     339             :                                                " (Unknown type)\n",
     340           0 :                                                nfs->type);
     341           0 :                         break;
     342             :                 }
     343           0 :                 break;
     344             :         }
     345           0 :         default:
     346           0 :                 talloc_asprintf_addbuf(&s, "%" PRIu32 "\n", dst->tag);
     347           0 :                 break;
     348             :         }
     349           0 :         return s;
     350             : }
     351             : 
     352          28 : static ssize_t reparse_buffer_marshall(uint32_t reparse_tag,
     353             :                                        uint16_t reserved,
     354             :                                        const struct iovec *iov,
     355             :                                        int iovlen,
     356             :                                        uint8_t *buf,
     357             :                                        size_t buflen)
     358             : {
     359          28 :         ssize_t reparse_data_length = iov_buflen(iov, iovlen);
     360           0 :         size_t needed;
     361             : 
     362          28 :         if (reparse_data_length == -1) {
     363           0 :                 return -1;
     364             :         }
     365          28 :         if (reparse_data_length > UINT16_MAX) {
     366           0 :                 return -1;
     367             :         }
     368             : 
     369          28 :         needed = reparse_data_length + 8;
     370          28 :         if (needed < reparse_data_length) {
     371           0 :                 return -1;
     372             :         }
     373             : 
     374          28 :         if (buflen >= needed) {
     375          14 :                 PUSH_LE_U32(buf, 0, reparse_tag);
     376          14 :                 PUSH_LE_U16(buf, 4, reparse_data_length);
     377          14 :                 PUSH_LE_U16(buf, 6, reserved);
     378          14 :                 iov_buf(iov, iovlen, buf + 8, buflen - 8);
     379             :         }
     380             : 
     381          28 :         return needed;
     382             : }
     383             : 
     384             : static ssize_t
     385          28 : reparse_data_buffer_marshall_syml(const struct symlink_reparse_struct *src,
     386             :                                   uint8_t *buf,
     387             :                                   size_t buflen)
     388             : {
     389           0 :         uint8_t sbuf[12];
     390           0 :         struct iovec iov[3];
     391          28 :         const char *print_name = src->print_name;
     392          28 :         uint8_t *subst_utf16 = NULL;
     393          28 :         uint8_t *print_utf16 = NULL;
     394          28 :         size_t subst_len = 0;
     395          28 :         size_t print_len = 0;
     396          28 :         ssize_t ret = -1;
     397           0 :         bool ok;
     398             : 
     399          28 :         if (src->substitute_name == NULL) {
     400           0 :                 return -1;
     401             :         }
     402          28 :         if (src->print_name == NULL) {
     403           0 :                 print_name = src->substitute_name;
     404             :         }
     405             : 
     406          28 :         iov[0] = (struct iovec){
     407             :                 .iov_base = sbuf,
     408             :                 .iov_len = sizeof(sbuf),
     409             :         };
     410             : 
     411          28 :         ok = convert_string_talloc(talloc_tos(),
     412             :                                    CH_UNIX,
     413             :                                    CH_UTF16,
     414          28 :                                    src->substitute_name,
     415          28 :                                    strlen(src->substitute_name),
     416             :                                    &subst_utf16,
     417             :                                    &subst_len);
     418          28 :         if (!ok) {
     419           0 :                 goto fail;
     420             :         }
     421          28 :         if (subst_len > UINT16_MAX) {
     422           0 :                 goto fail;
     423             :         }
     424          28 :         iov[1] = (struct iovec){
     425             :                 .iov_base = subst_utf16,
     426             :                 .iov_len = subst_len,
     427             :         };
     428             : 
     429          28 :         ok = convert_string_talloc(talloc_tos(),
     430             :                                    CH_UNIX,
     431             :                                    CH_UTF16,
     432             :                                    print_name,
     433             :                                    strlen(print_name),
     434             :                                    &print_utf16,
     435             :                                    &print_len);
     436          28 :         if (!ok) {
     437           0 :                 goto fail;
     438             :         }
     439          28 :         if (print_len > UINT16_MAX) {
     440           0 :                 goto fail;
     441             :         }
     442          28 :         iov[2] = (struct iovec){
     443             :                 .iov_base = print_utf16,
     444             :                 .iov_len = print_len,
     445             :         };
     446             : 
     447          28 :         PUSH_LE_U16(sbuf, 0, 0);          /* SubstituteNameOffset */
     448          28 :         PUSH_LE_U16(sbuf, 2, subst_len);  /* SubstituteNameLength */
     449          28 :         PUSH_LE_U16(sbuf, 4, subst_len);  /* PrintNameOffset */
     450          28 :         PUSH_LE_U16(sbuf, 6, print_len);  /* PrintNameLength */
     451          28 :         PUSH_LE_U32(sbuf, 8, src->flags); /* Flags */
     452             : 
     453          28 :         ret = reparse_buffer_marshall(IO_REPARSE_TAG_SYMLINK,
     454          28 :                                       src->unparsed_path_length,
     455             :                                       iov,
     456             :                                       ARRAY_SIZE(iov),
     457             :                                       buf,
     458             :                                       buflen);
     459             : 
     460          28 : fail:
     461          28 :         TALLOC_FREE(subst_utf16);
     462          28 :         TALLOC_FREE(print_utf16);
     463          28 :         return ret;
     464             : }
     465             : 
     466             : static ssize_t
     467           0 : reparse_data_buffer_marshall_nfs(const struct nfs_reparse_data_buffer *src,
     468             :                                  uint8_t *buf,
     469             :                                  size_t buflen)
     470             : {
     471           0 :         uint8_t typebuf[8];
     472           0 :         uint8_t devbuf[8];
     473           0 :         struct iovec iov[2] = {};
     474           0 :         size_t iovlen;
     475           0 :         uint8_t *lnk_utf16 = NULL;
     476           0 :         size_t lnk_len = 0;
     477           0 :         ssize_t ret;
     478             : 
     479           0 :         PUSH_LE_U64(typebuf, 0, src->type);
     480           0 :         iov[0] = (struct iovec){
     481             :                 .iov_base = typebuf,
     482             :                 .iov_len = sizeof(typebuf),
     483             :         };
     484           0 :         iovlen = 1;
     485             : 
     486           0 :         switch (src->type) {
     487           0 :         case NFS_SPECFILE_LNK: {
     488           0 :                 bool ok = convert_string_talloc(talloc_tos(),
     489             :                                                 CH_UNIX,
     490             :                                                 CH_UTF16,
     491           0 :                                                 src->data.lnk_target,
     492           0 :                                                 strlen(src->data.lnk_target),
     493             :                                                 &lnk_utf16,
     494             :                                                 &lnk_len);
     495           0 :                 if (!ok) {
     496           0 :                         return -1;
     497             :                 }
     498           0 :                 iov[1] = (struct iovec){
     499             :                         .iov_base = lnk_utf16,
     500             :                         .iov_len = lnk_len,
     501             :                 };
     502           0 :                 iovlen = 2;
     503           0 :                 break;
     504             :         }
     505           0 :         case NFS_SPECFILE_CHR:
     506           0 :                 FALL_THROUGH;
     507             :         case NFS_SPECFILE_BLK:
     508           0 :                 PUSH_LE_U32(devbuf, 0, src->data.dev.major);
     509           0 :                 PUSH_LE_U32(devbuf, 4, src->data.dev.minor);
     510           0 :                 iov[1] = (struct iovec){
     511             :                         .iov_base = devbuf,
     512             :                         .iov_len = sizeof(devbuf),
     513             :                 };
     514           0 :                 iovlen = 2;
     515           0 :                 break;
     516           0 :         default:
     517           0 :                 break;
     518             :                 /* Nothing to do for NFS_SPECFILE_FIFO and _SOCK */
     519             :         }
     520             : 
     521           0 :         ret = reparse_buffer_marshall(IO_REPARSE_TAG_NFS,
     522             :                                       0,
     523             :                                       iov,
     524             :                                       iovlen,
     525             :                                       buf,
     526             :                                       buflen);
     527           0 :         TALLOC_FREE(lnk_utf16);
     528           0 :         return ret;
     529             : }
     530             : 
     531          28 : ssize_t reparse_data_buffer_marshall(const struct reparse_data_buffer *src,
     532             :                                      uint8_t *buf,
     533             :                                      size_t buflen)
     534             : {
     535          28 :         ssize_t ret = -1;
     536             : 
     537          28 :         switch (src->tag) {
     538          28 :         case IO_REPARSE_TAG_SYMLINK:
     539             : 
     540          28 :                 ret = reparse_data_buffer_marshall_syml(&src->parsed.lnk,
     541             :                                                         buf,
     542             :                                                         buflen);
     543          28 :                 break;
     544             : 
     545           0 :         case IO_REPARSE_TAG_NFS:
     546             : 
     547           0 :                 ret = reparse_data_buffer_marshall_nfs(&src->parsed.nfs,
     548             :                                                        buf,
     549             :                                                        buflen);
     550           0 :                 break;
     551             : 
     552           0 :         default: {
     553           0 :                 struct iovec iov = {
     554           0 :                         .iov_base = src->parsed.raw.data,
     555           0 :                         .iov_len = src->parsed.raw.length,
     556             :                 };
     557           0 :                 ret = reparse_buffer_marshall(src->tag,
     558           0 :                                               src->parsed.raw.reserved,
     559             :                                               &iov,
     560             :                                               1,
     561             :                                               buf,
     562             :                                               buflen);
     563             :         }
     564             :         }
     565             : 
     566          28 :         return ret;
     567             : }

Generated by: LCOV version 1.14