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

1.5     ! deraadt     1: /*     $OpenBSD: msg.c,v 1.4 2004/09/27 17:11:07 jfb 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:  */
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;
1.5     ! deraadt   157:        } else
1.2       jfb       158:                msg.cm_len = sizeof(int);       /* dummy */
1.1       jfb       159:
1.2       jfb       160:        if (writev(fd, iov, cnt) == -1) {
1.1       jfb       161:                cvs_log(LP_ERRNO, "failed to send message");
                    162:                return (-1);
                    163:        }
                    164:
1.2       jfb       165:        if (type == CVSD_MSG_PASSFD) {
                    166:                /* pass the file descriptor for real */
                    167:                cvsd_sendfd(fd, *(int *)data);
                    168:        }
                    169:
1.1       jfb       170:        return (0);
                    171: }
                    172:
                    173:
                    174: /*
                    175:  * cvsd_recvmsg()
                    176:  *
                    177:  * Read a message from the file descriptor <fd> and store the message data
                    178:  * in the <dst> buffer.  The <len> parameter should contain the maximum
                    179:  * length of data that can be stored in <dst>, and will contain the actual
                    180:  * size of data stored on return.  The message type is stored in <type>.
1.3       jfb       181:  * Returns 1 if a message was read, 0 if the remote end closed the message
                    182:  * socket and no further messages can be read, or -1 on failure.
1.1       jfb       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:
1.3       jfb       192:        if ((ret = read(fd, &msg, sizeof(msg))) == -1) {
1.1       jfb       193:                cvs_log(LP_ERRNO, "failed to read message header");
                    194:                return (-1);
1.5     ! deraadt   195:        } else if (ret == 0)
1.3       jfb       196:                return (0);
1.1       jfb       197:
                    198:        if (*len < msg.cm_len) {
                    199:                cvs_log(LP_ERR, "buffer size too small for message data");
                    200:                return (-1);
                    201:        }
                    202:
1.2       jfb       203:        if (msg.cm_type == CVSD_MSG_PASSFD) {
                    204:                sfd = cvsd_recvfd(fd);
                    205:                if (sfd == -1)
                    206:                        return (-1);
                    207:
                    208:                *(int *)dst = sfd;
                    209:                *len = sizeof(sfd);
1.5     ! deraadt   210:        } else {
1.2       jfb       211:                ret = read(fd, dst, msg.cm_len);
                    212:                if (ret == -1) {
                    213:                        cvs_log(LP_ERRNO, "failed to read message");
                    214:                        return (-1);
1.5     ! deraadt   215:                } else if (ret == 0) {
1.2       jfb       216:                }
                    217:
                    218:                *len = (size_t)ret;
1.1       jfb       219:        }
                    220:
                    221:        *type = msg.cm_type;
                    222:
1.4       jfb       223:        return (1);
1.1       jfb       224: }