LCOV - code coverage report
Current view: top level - lib/util - msghdr.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 48 91 52.7 %
Date: 2024-04-21 15:09:00 Functions: 3 5 60.0 %

          Line data    Source code
       1             : /*
       2             :  * Unix SMB/CIFS implementation.
       3             :  * Copyright (C) Volker Lendecke 2014
       4             :  *
       5             :  * This program is free software; you can redistribute it and/or modify
       6             :  * it under the terms of the GNU General Public License as published by
       7             :  * the Free Software Foundation; either version 3 of the License, or
       8             :  * (at your option) any later version.
       9             :  *
      10             :  * This program is distributed in the hope that it will be useful,
      11             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13             :  * GNU General Public License for more details.
      14             :  *
      15             :  * You should have received a copy of the GNU General Public License
      16             :  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
      17             :  */
      18             : 
      19             : #include "replace.h"
      20             : #include "lib/util/msghdr.h"
      21             : #include "lib/util/iov_buf.h"
      22             : #include <sys/socket.h>
      23             : 
      24             : #if defined(HAVE_STRUCT_MSGHDR_MSG_CONTROL)
      25             : 
      26     1104544 : ssize_t msghdr_prep_fds(struct msghdr *msg, uint8_t *buf, size_t bufsize,
      27             :                         const int *fds, size_t num_fds)
      28             : {
      29     1104544 :         size_t fds_size = sizeof(int) * MIN(num_fds, INT8_MAX);
      30     1104544 :         size_t cmsg_len = CMSG_LEN(fds_size);
      31     1104544 :         size_t cmsg_space = CMSG_SPACE(fds_size);
      32      139558 :         struct cmsghdr *cmsg;
      33      139558 :         void *fdptr;
      34             : 
      35     1104544 :         if (num_fds == 0) {
      36      964160 :                 if (msg != NULL) {
      37      964160 :                         msg->msg_control = NULL;
      38      964160 :                         msg->msg_controllen = 0;
      39             :                 }
      40             :                 /*
      41             :                  * C99 doesn't allow 0-length arrays
      42             :                  */
      43      964160 :                 return 1;
      44             :         }
      45      140384 :         if (num_fds > INT8_MAX) {
      46           0 :                 return -1;
      47             :         }
      48      140384 :         if ((msg == NULL) || (cmsg_space > bufsize)) {
      49             :                 /*
      50             :                  * C99 doesn't allow 0-length arrays
      51             :                  */
      52       70192 :                 return MAX(cmsg_space, 1);
      53             :         }
      54             : 
      55       70192 :         msg->msg_control = buf;
      56       70192 :         msg->msg_controllen = cmsg_space;
      57             : 
      58       70192 :         cmsg = CMSG_FIRSTHDR(msg);
      59       70192 :         cmsg->cmsg_level = SOL_SOCKET;
      60       70192 :         cmsg->cmsg_type = SCM_RIGHTS;
      61       70192 :         cmsg->cmsg_len = cmsg_len;
      62       70192 :         fdptr = CMSG_DATA(cmsg);
      63       70192 :         memcpy(fdptr, fds, fds_size);
      64       70192 :         msg->msg_controllen = cmsg->cmsg_len;
      65             : 
      66       70192 :         return cmsg_space;
      67             : }
      68             : 
      69      458694 : size_t msghdr_prep_recv_fds(struct msghdr *msg, uint8_t *buf, size_t bufsize,
      70             :                             size_t num_fds)
      71             : {
      72      458694 :         size_t ret = CMSG_SPACE(sizeof(int) * num_fds);
      73             : 
      74      458694 :         if (bufsize < ret) {
      75      160663 :                 return ret;
      76             :         }
      77      229347 :         if (msg != NULL) {
      78      229347 :                 if (num_fds != 0) {
      79      229347 :                         msg->msg_control = buf;
      80      229347 :                         msg->msg_controllen = ret;
      81             :                 } else {
      82           0 :                         msg->msg_control = NULL;
      83           0 :                         msg->msg_controllen = 0;
      84             :                 }
      85             :         }
      86      160663 :         return ret;
      87             : }
      88             : 
      89      297991 : size_t msghdr_extract_fds(struct msghdr *msg, int *fds, size_t fds_size)
      90             : {
      91       68739 :         struct cmsghdr *cmsg;
      92       68739 :         size_t num_fds;
      93             : 
      94      297991 :         for(cmsg = CMSG_FIRSTHDR(msg);
      95      297991 :             cmsg != NULL;
      96       68739 :             cmsg = CMSG_NXTHDR(msg, cmsg))
      97             :         {
      98      137256 :                 if ((cmsg->cmsg_type == SCM_RIGHTS) &&
      99      137146 :                     (cmsg->cmsg_level == SOL_SOCKET)) {
     100      137146 :                         break;
     101             :                 }
     102             :         }
     103             : 
     104      297991 :         if (cmsg == NULL) {
     105       92106 :                 return 0;
     106             :         }
     107             : 
     108      137256 :         num_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
     109             : 
     110      137256 :         if ((num_fds != 0) && (fds != NULL) && (fds_size >= num_fds)) {
     111       68628 :                 memcpy(fds, CMSG_DATA(cmsg), num_fds * sizeof(int));
     112             :         }
     113             : 
     114      137146 :         return num_fds;
     115             : }
     116             : 
     117             : #elif defined(HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS)
     118             : 
     119             : ssize_t msghdr_prep_fds(struct msghdr *msg, uint8_t *buf, size_t bufsize,
     120             :                         const int *fds, size_t num_fds)
     121             : {
     122             :         size_t needed;
     123             : 
     124             :         if (num_fds > INT8_MAX) {
     125             :                 return -1;
     126             :         }
     127             : 
     128             :         needed = sizeof(int) * num_fds;
     129             : 
     130             :         if ((msg == NULL) || (needed > bufsize)) {
     131             :                 return needed;
     132             :         }
     133             : 
     134             :         memcpy(buf, fds, needed);
     135             : 
     136             :         msg->msg_accrights = (caddr_t) buf;
     137             :         msg->msg_accrightslen = needed;
     138             : 
     139             :         return needed;
     140             : }
     141             : 
     142             : size_t msghdr_prep_recv_fds(struct msghdr *msg, uint8_t *buf, size_t bufsize,
     143             :                             size_t num_fds)
     144             : {
     145             :         size_t ret = num_fds * sizeof(int);
     146             : 
     147             :         if (bufsize < ret) {
     148             :                 return ret;
     149             :         }
     150             : 
     151             :         if (msg != NULL) {
     152             :                 if (num_fds != 0) {
     153             :                         msg->msg_accrights = (caddr_t) buf;
     154             :                         msg->msg_accrightslen = ret;
     155             :                 } else {
     156             :                         msg->msg_accrights = NULL;
     157             :                         msg->msg_accrightslen = 0;
     158             :                 }
     159             :         }
     160             :         return ret;
     161             : }
     162             : 
     163             : size_t msghdr_extract_fds(struct msghdr *msg, int *fds, size_t fds_size)
     164             : {
     165             :         size_t num_fds = msg->msg_accrightslen / sizeof(int);
     166             : 
     167             :         if ((fds != 0) && (num_fds <= fds_size)) {
     168             :                 memcpy(fds, msg->msg_accrights, msg->msg_accrightslen);
     169             :         }
     170             : 
     171             :         return num_fds;
     172             : }
     173             : 
     174             : #else
     175             : 
     176             : ssize_t msghdr_prep_fds(struct msghdr *msg, uint8_t *buf, size_t bufsize,
     177             :                         const int *fds, size_t num_fds)
     178             : {
     179             :         return -1;
     180             : }
     181             : 
     182             : size_t msghdr_prep_recv_fds(struct msghdr *msg, uint8_t *buf, size_t bufsize,
     183             :                             size_t num_fds)
     184             : {
     185             :         return 0;
     186             : }
     187             : 
     188             : size_t msghdr_extract_fds(struct msghdr *msg, int *fds, size_t fds_size)
     189             : {
     190             :         return 0;
     191             : }
     192             : 
     193             : #endif
     194             : 
     195             : struct msghdr_buf {
     196             :         struct msghdr msg;
     197             :         struct sockaddr_storage addr;
     198             :         struct iovec iov;
     199             :         uint8_t buf[];
     200             : };
     201             : 
     202           0 : ssize_t msghdr_copy(struct msghdr_buf *msg, size_t msgsize,
     203             :                     const void *addr, socklen_t addrlen,
     204             :                     const struct iovec *iov, int iovcnt,
     205             :                     const int *fds, size_t num_fds)
     206             : {
     207           0 :         ssize_t fd_len;
     208           0 :         size_t iov_len, needed, bufsize;
     209             : 
     210           0 :         bufsize = (msgsize > offsetof(struct msghdr_buf, buf)) ?
     211           0 :                 msgsize - offsetof(struct msghdr_buf, buf) : 0;
     212             : 
     213           0 :         if (msg != NULL) {
     214           0 :                 msg->msg = (struct msghdr) { 0 };
     215             : 
     216           0 :                 fd_len = msghdr_prep_fds(&msg->msg, msg->buf, bufsize,
     217             :                                          fds, num_fds);
     218             :         } else {
     219           0 :                 fd_len = msghdr_prep_fds(NULL, NULL, bufsize, fds, num_fds);
     220             :         }
     221             : 
     222           0 :         if (fd_len == -1) {
     223           0 :                 return -1;
     224             :         }
     225             : 
     226           0 :         if (bufsize >= (size_t)fd_len) {
     227           0 :                 bufsize -= fd_len;
     228             :         } else {
     229           0 :                 bufsize = 0;
     230             :         }
     231             : 
     232           0 :         if (msg != NULL) {
     233             : 
     234           0 :                 if (addr != NULL) {
     235           0 :                         if (addrlen > sizeof(struct sockaddr_storage)) {
     236           0 :                                 errno = EMSGSIZE;
     237           0 :                                 return -1;
     238             :                         }
     239           0 :                         memcpy(&msg->addr, addr, addrlen);
     240           0 :                         msg->msg.msg_name = &msg->addr;
     241           0 :                         msg->msg.msg_namelen = addrlen;
     242             :                 } else {
     243           0 :                         msg->msg.msg_name = NULL;
     244           0 :                         msg->msg.msg_namelen = 0;
     245             :                 }
     246             : 
     247           0 :                 msg->iov.iov_base = msg->buf + fd_len;
     248           0 :                 msg->iov.iov_len = iov_buf(
     249           0 :                         iov, iovcnt, msg->iov.iov_base, bufsize);
     250           0 :                 iov_len = msg->iov.iov_len;
     251             : 
     252           0 :                 msg->msg.msg_iov = &msg->iov;
     253           0 :                 msg->msg.msg_iovlen = 1;
     254             :         } else {
     255           0 :                 iov_len = iov_buflen(iov, iovcnt);
     256             :         }
     257             : 
     258           0 :         needed = offsetof(struct msghdr_buf, buf) + fd_len;
     259           0 :         if (needed < (size_t)fd_len) {
     260           0 :                 return -1;
     261             :         }
     262           0 :         needed += iov_len;
     263           0 :         if (needed < iov_len) {
     264           0 :                 return -1;
     265             :         }
     266             : 
     267           0 :         return needed;
     268             : }
     269             : 
     270           0 : struct msghdr *msghdr_buf_msghdr(struct msghdr_buf *msg)
     271             : {
     272           0 :         return &msg->msg;
     273             : }

Generated by: LCOV version 1.14