[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.2

1.1       jfb         1: /*     $OpenBSD$       */
                      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:  */
1.1       jfb        40:
1.2     ! jfb        41: int
        !            42: cvsd_sendfd(int sock, int fd)
        !            43: {
        !            44:        struct msghdr msg;
        !            45:        char tmp[CMSG_SPACE(sizeof(int))];
        !            46:        struct cmsghdr *cmsg;
        !            47:        struct iovec vec;
        !            48:        int result = 0;
        !            49:        ssize_t n;
        !            50:
        !            51:        memset(&msg, 0, sizeof(msg));
        !            52:
        !            53:        if (fd >= 0) {
        !            54:                msg.msg_control = (caddr_t)tmp;
        !            55:                msg.msg_controllen = CMSG_LEN(sizeof(int));
        !            56:                cmsg = CMSG_FIRSTHDR(&msg);
        !            57:                cmsg->cmsg_len = CMSG_LEN(sizeof(int));
        !            58:                cmsg->cmsg_level = SOL_SOCKET;
        !            59:                cmsg->cmsg_type = SCM_RIGHTS;
        !            60:                *(int *)CMSG_DATA(cmsg) = fd;
        !            61:        } else
        !            62:                result = errno;
        !            63:
        !            64:        vec.iov_base = &result;
        !            65:        vec.iov_len = sizeof(int);
        !            66:        msg.msg_iov = &vec;
        !            67:        msg.msg_iovlen = 1;
        !            68:
        !            69:        if ((n = sendmsg(sock, &msg, 0)) == -1) {
        !            70:                cvs_log(LP_ERRNO, "failed to pass file descriptor");
        !            71:                return (-1);
        !            72:        }
        !            73:        if (n != sizeof(int))
        !            74:                cvs_log(LP_WARN, "unexpected return count from sendmsg()");
        !            75:        return (0);
        !            76: }
        !            77:
        !            78: /*
        !            79:  * cvsd_recvfd()
        !            80:  *
        !            81:  * Receive a file descriptor over the socket <sock>.  Returns the descriptor
        !            82:  * on success, or -1 on failure.
        !            83:  */
        !            84:
        !            85: int
        !            86: cvsd_recvfd(int sock)
        !            87: {
        !            88:        struct msghdr msg;
        !            89:        char tmp[CMSG_SPACE(sizeof(int))];
        !            90:        struct cmsghdr *cmsg;
        !            91:        struct iovec vec;
        !            92:        ssize_t n;
        !            93:        int result;
        !            94:        int fd;
        !            95:
        !            96:        memset(&msg, 0, sizeof(msg));
        !            97:        vec.iov_base = &result;
        !            98:        vec.iov_len = sizeof(int);
        !            99:        msg.msg_iov = &vec;
        !           100:        msg.msg_iovlen = 1;
        !           101:        msg.msg_control = tmp;
        !           102:        msg.msg_controllen = sizeof(tmp);
        !           103:
        !           104:        if ((n = recvmsg(sock, &msg, 0)) == -1)
        !           105:                cvs_log(LP_ERRNO, "failed to receive descriptor");
        !           106:        if (n != sizeof(int))
        !           107:                cvs_log(LP_WARN, "recvmsg: expected received 1 got %ld",
        !           108:                    (long)n);
        !           109:        if (result == 0) {
        !           110:                cmsg = CMSG_FIRSTHDR(&msg);
        !           111:                if (cmsg->cmsg_type != SCM_RIGHTS)
        !           112:                        cvs_log(LP_WARN,
        !           113:                            "unexpected message type in descriptor reception");
        !           114:                fd = (*(int *)CMSG_DATA(cmsg));
        !           115:                return (fd);
        !           116:        } else {
        !           117:                errno = result;
        !           118:                return (-1);
        !           119:        }
        !           120: }
1.1       jfb       121:
                    122:
                    123:
                    124: /*
                    125:  * cvsd_sendmsg()
                    126:  *
                    127:  * Send a message of type <type> along with the first <len> bytes of data
                    128:  * from <data> (which can be up to CVSD_MSG_MAXLEN bytes) on the descriptor
                    129:  * <fd>.
                    130:  * Returns 0 on success, or -1 on failure.
                    131:  */
                    132:
                    133: int
                    134: cvsd_sendmsg(int fd, u_int type, const void *data, size_t len)
                    135: {
1.2     ! jfb       136:        int cnt;
1.1       jfb       137:        struct iovec iov[2];
                    138:        struct cvsd_msg msg;
                    139:
                    140:        if (len > CVSD_MSG_MAXLEN) {
                    141:                cvs_log(LP_ERR, "message too large");
                    142:                return (-1);
                    143:        }
                    144:
1.2     ! jfb       145:        memset(&msg, 0, sizeof(msg));
1.1       jfb       146:
1.2     ! jfb       147:        cnt = 1;
1.1       jfb       148:        iov[0].iov_base = &msg;
                    149:        iov[0].iov_len = sizeof(msg);
1.2     ! jfb       150:        msg.cm_type = type;
        !           151:
        !           152:        if (type != CVSD_MSG_PASSFD) {
        !           153:                msg.cm_len = len;
        !           154:                iov[1].iov_base = (void *)data;
        !           155:                iov[1].iov_len = len;
        !           156:                cnt = 2;
        !           157:        }
        !           158:        else
        !           159:                msg.cm_len = sizeof(int);       /* dummy */
1.1       jfb       160:
1.2     ! jfb       161:        if (writev(fd, iov, cnt) == -1) {
1.1       jfb       162:                cvs_log(LP_ERRNO, "failed to send message");
                    163:                return (-1);
                    164:        }
                    165:
1.2     ! jfb       166:        if (type == CVSD_MSG_PASSFD) {
        !           167:                /* pass the file descriptor for real */
        !           168:                cvsd_sendfd(fd, *(int *)data);
        !           169:        }
        !           170:
1.1       jfb       171:        return (0);
                    172: }
                    173:
                    174:
                    175: /*
                    176:  * cvsd_recvmsg()
                    177:  *
                    178:  * Read a message from the file descriptor <fd> and store the message data
                    179:  * in the <dst> buffer.  The <len> parameter should contain the maximum
                    180:  * length of data that can be stored in <dst>, and will contain the actual
                    181:  * size of data stored on return.  The message type is stored in <type>.
                    182:  * Returns 0 on success, or -1 on failure.
                    183:  */
                    184:
                    185: int
                    186: cvsd_recvmsg(int fd, u_int *type, void *dst, size_t *len)
                    187: {
1.2     ! jfb       188:        int sfd;
1.1       jfb       189:        ssize_t ret;
                    190:        struct cvsd_msg msg;
                    191:
                    192:        if (read(fd, &msg, sizeof(msg)) == -1) {
                    193:                cvs_log(LP_ERRNO, "failed to read message header");
                    194:                return (-1);
                    195:        }
                    196:
                    197:        if (*len < msg.cm_len) {
                    198:                cvs_log(LP_ERR, "buffer size too small for message data");
                    199:                return (-1);
                    200:        }
                    201:
1.2     ! jfb       202:        if (msg.cm_type == CVSD_MSG_PASSFD) {
        !           203:                sfd = cvsd_recvfd(fd);
        !           204:                if (sfd == -1)
        !           205:                        return (-1);
        !           206:
        !           207:                *(int *)dst = sfd;
        !           208:                *len = sizeof(sfd);
1.1       jfb       209:        }
1.2     ! jfb       210:        else {
        !           211:                ret = read(fd, dst, msg.cm_len);
        !           212:                if (ret == -1) {
        !           213:                        cvs_log(LP_ERRNO, "failed to read message");
        !           214:                        return (-1);
        !           215:                }
        !           216:                else if (ret == 0) {
        !           217:                }
        !           218:
        !           219:                *len = (size_t)ret;
1.1       jfb       220:        }
                    221:
                    222:        *type = msg.cm_type;
                    223:
                    224:        return (0);
                    225: }