[BACK]Return to msg.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / cvs

Annotation of src/usr.bin/cvs/msg.c, Revision 1.6

1.6     ! tedu        1: /*     $OpenBSD: msg.c,v 1.5 2004/12/06 21:03:12 deraadt Exp $ */
1.1       jfb         2: /*
1.2       jfb         3:  * Copyright (c) 2002 Matthieu Herrb
                      4:  * Copyright (c) 2001 Niels Provos <provos@citi.umich.edu>
                      5:  * Copyright (c) 2004 Jean-Francois Brousseau
1.1       jfb         6:  *
1.2       jfb         7:  * Permission to use, copy, modify, and distribute this software for any
                      8:  * purpose with or without fee is hereby granted, provided that the above
                      9:  * copyright notice and this permission notice appear in all copies.
                     10:  *
                     11:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     12:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     13:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     14:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     15:  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
                     16:  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
                     17:  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     18:  *
                     19:  * This code was adapted from the tcpdump source
1.1       jfb        20:  */
                     21:
                     22: #include <sys/param.h>
1.2       jfb        23: #include <sys/socket.h>
1.1       jfb        24: #include <sys/uio.h>
                     25:
1.2       jfb        26: #include <errno.h>
1.1       jfb        27: #include <fcntl.h>
                     28: #include <stdlib.h>
                     29: #include <unistd.h>
                     30: #include <string.h>
                     31:
                     32: #include "log.h"
                     33: #include "cvsd.h"
                     34:
1.2       jfb        35: /*
                     36:  * cvsd_sendfd()
                     37:  *
                     38:  * Pass a file descriptor <fd> to the other endpoint of the socket <sock>.
                     39:  */
                     40: int
                     41: cvsd_sendfd(int sock, int fd)
                     42: {
                     43:        struct msghdr msg;
                     44:        char tmp[CMSG_SPACE(sizeof(int))];
                     45:        struct cmsghdr *cmsg;
                     46:        struct iovec vec;
                     47:        int result = 0;
                     48:        ssize_t n;
                     49:
                     50:        memset(&msg, 0, sizeof(msg));
                     51:
                     52:        if (fd >= 0) {
                     53:                msg.msg_control = (caddr_t)tmp;
                     54:                msg.msg_controllen = CMSG_LEN(sizeof(int));
                     55:                cmsg = CMSG_FIRSTHDR(&msg);
                     56:                cmsg->cmsg_len = CMSG_LEN(sizeof(int));
                     57:                cmsg->cmsg_level = SOL_SOCKET;
                     58:                cmsg->cmsg_type = SCM_RIGHTS;
                     59:                *(int *)CMSG_DATA(cmsg) = fd;
                     60:        } else
                     61:                result = errno;
                     62:
                     63:        vec.iov_base = &result;
                     64:        vec.iov_len = sizeof(int);
                     65:        msg.msg_iov = &vec;
                     66:        msg.msg_iovlen = 1;
                     67:
                     68:        if ((n = sendmsg(sock, &msg, 0)) == -1) {
                     69:                cvs_log(LP_ERRNO, "failed to pass file descriptor");
                     70:                return (-1);
                     71:        }
                     72:        if (n != sizeof(int))
                     73:                cvs_log(LP_WARN, "unexpected return count from sendmsg()");
                     74:        return (0);
                     75: }
                     76:
                     77: /*
                     78:  * cvsd_recvfd()
                     79:  *
                     80:  * Receive a file descriptor over the socket <sock>.  Returns the descriptor
                     81:  * on success, or -1 on failure.
                     82:  */
                     83: int
                     84: cvsd_recvfd(int sock)
                     85: {
                     86:        struct msghdr msg;
                     87:        char tmp[CMSG_SPACE(sizeof(int))];
                     88:        struct cmsghdr *cmsg;
                     89:        struct iovec vec;
                     90:        ssize_t n;
                     91:        int result;
                     92:        int fd;
                     93:
                     94:        memset(&msg, 0, sizeof(msg));
                     95:        vec.iov_base = &result;
                     96:        vec.iov_len = sizeof(int);
                     97:        msg.msg_iov = &vec;
                     98:        msg.msg_iovlen = 1;
                     99:        msg.msg_control = tmp;
                    100:        msg.msg_controllen = sizeof(tmp);
                    101:
                    102:        if ((n = recvmsg(sock, &msg, 0)) == -1)
                    103:                cvs_log(LP_ERRNO, "failed to receive descriptor");
                    104:        if (n != sizeof(int))
                    105:                cvs_log(LP_WARN, "recvmsg: expected received 1 got %ld",
                    106:                    (long)n);
                    107:        if (result == 0) {
                    108:                cmsg = CMSG_FIRSTHDR(&msg);
                    109:                if (cmsg->cmsg_type != SCM_RIGHTS)
                    110:                        cvs_log(LP_WARN,
                    111:                            "unexpected message type in descriptor reception");
                    112:                fd = (*(int *)CMSG_DATA(cmsg));
                    113:                return (fd);
                    114:        } else {
                    115:                errno = result;
                    116:                return (-1);
                    117:        }
                    118: }
1.1       jfb       119:
                    120:
                    121:
                    122: /*
                    123:  * cvsd_sendmsg()
                    124:  *
                    125:  * Send a message of type <type> along with the first <len> bytes of data
                    126:  * from <data> (which can be up to CVSD_MSG_MAXLEN bytes) on the descriptor
                    127:  * <fd>.
                    128:  * Returns 0 on success, or -1 on failure.
                    129:  */
                    130: int
                    131: cvsd_sendmsg(int fd, u_int type, const void *data, size_t len)
                    132: {
1.2       jfb       133:        int cnt;
1.1       jfb       134:        struct iovec iov[2];
                    135:        struct cvsd_msg msg;
                    136:
                    137:        if (len > CVSD_MSG_MAXLEN) {
                    138:                cvs_log(LP_ERR, "message too large");
                    139:                return (-1);
                    140:        }
                    141:
1.2       jfb       142:        memset(&msg, 0, sizeof(msg));
1.1       jfb       143:
1.2       jfb       144:        cnt = 1;
1.1       jfb       145:        iov[0].iov_base = &msg;
                    146:        iov[0].iov_len = sizeof(msg);
1.2       jfb       147:        msg.cm_type = type;
                    148:
                    149:        if (type != CVSD_MSG_PASSFD) {
                    150:                msg.cm_len = len;
                    151:                iov[1].iov_base = (void *)data;
                    152:                iov[1].iov_len = len;
                    153:                cnt = 2;
1.5       deraadt   154:        } else
1.2       jfb       155:                msg.cm_len = sizeof(int);       /* dummy */
1.1       jfb       156:
1.2       jfb       157:        if (writev(fd, iov, cnt) == -1) {
1.1       jfb       158:                cvs_log(LP_ERRNO, "failed to send message");
                    159:                return (-1);
                    160:        }
                    161:
1.2       jfb       162:        if (type == CVSD_MSG_PASSFD) {
                    163:                /* pass the file descriptor for real */
                    164:                cvsd_sendfd(fd, *(int *)data);
                    165:        }
                    166:
1.1       jfb       167:        return (0);
                    168: }
                    169:
                    170:
                    171: /*
                    172:  * cvsd_recvmsg()
                    173:  *
                    174:  * Read a message from the file descriptor <fd> and store the message data
                    175:  * in the <dst> buffer.  The <len> parameter should contain the maximum
                    176:  * length of data that can be stored in <dst>, and will contain the actual
                    177:  * size of data stored on return.  The message type is stored in <type>.
1.3       jfb       178:  * Returns 1 if a message was read, 0 if the remote end closed the message
                    179:  * socket and no further messages can be read, or -1 on failure.
1.1       jfb       180:  */
                    181: int
                    182: cvsd_recvmsg(int fd, u_int *type, void *dst, size_t *len)
                    183: {
1.2       jfb       184:        int sfd;
1.1       jfb       185:        ssize_t ret;
                    186:        struct cvsd_msg msg;
                    187:
1.3       jfb       188:        if ((ret = read(fd, &msg, sizeof(msg))) == -1) {
1.1       jfb       189:                cvs_log(LP_ERRNO, "failed to read message header");
                    190:                return (-1);
1.5       deraadt   191:        } else if (ret == 0)
1.3       jfb       192:                return (0);
1.1       jfb       193:
                    194:        if (*len < msg.cm_len) {
                    195:                cvs_log(LP_ERR, "buffer size too small for message data");
                    196:                return (-1);
                    197:        }
                    198:
1.2       jfb       199:        if (msg.cm_type == CVSD_MSG_PASSFD) {
                    200:                sfd = cvsd_recvfd(fd);
                    201:                if (sfd == -1)
                    202:                        return (-1);
                    203:
                    204:                *(int *)dst = sfd;
                    205:                *len = sizeof(sfd);
1.5       deraadt   206:        } else {
1.2       jfb       207:                ret = read(fd, dst, msg.cm_len);
                    208:                if (ret == -1) {
                    209:                        cvs_log(LP_ERRNO, "failed to read message");
                    210:                        return (-1);
1.5       deraadt   211:                } else if (ret == 0) {
1.2       jfb       212:                }
                    213:
                    214:                *len = (size_t)ret;
1.1       jfb       215:        }
                    216:
                    217:        *type = msg.cm_type;
                    218:
1.4       jfb       219:        return (1);
1.1       jfb       220: }