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

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>.
1.3       jfb       182:  * Returns 1 if a message was read, 0 if the remote end closed the message
                    183:  * socket and no further messages can be read, or -1 on failure.
1.1       jfb       184:  */
                    185:
                    186: int
                    187: cvsd_recvmsg(int fd, u_int *type, void *dst, size_t *len)
                    188: {
1.2       jfb       189:        int sfd;
1.1       jfb       190:        ssize_t ret;
                    191:        struct cvsd_msg msg;
                    192:
1.3       jfb       193:        if ((ret = read(fd, &msg, sizeof(msg))) == -1) {
1.1       jfb       194:                cvs_log(LP_ERRNO, "failed to read message header");
                    195:                return (-1);
                    196:        }
1.3       jfb       197:        else if (ret == 0)
                    198:                return (0);
1.1       jfb       199:
                    200:        if (*len < msg.cm_len) {
                    201:                cvs_log(LP_ERR, "buffer size too small for message data");
                    202:                return (-1);
                    203:        }
                    204:
1.2       jfb       205:        if (msg.cm_type == CVSD_MSG_PASSFD) {
                    206:                sfd = cvsd_recvfd(fd);
                    207:                if (sfd == -1)
                    208:                        return (-1);
                    209:
                    210:                *(int *)dst = sfd;
                    211:                *len = sizeof(sfd);
1.1       jfb       212:        }
1.2       jfb       213:        else {
                    214:                ret = read(fd, dst, msg.cm_len);
                    215:                if (ret == -1) {
                    216:                        cvs_log(LP_ERRNO, "failed to read message");
                    217:                        return (-1);
                    218:                }
                    219:                else if (ret == 0) {
                    220:                }
                    221:
                    222:                *len = (size_t)ret;
1.1       jfb       223:        }
                    224:
                    225:        *type = msg.cm_type;
                    226:
1.4     ! jfb       227:        return (1);
1.1       jfb       228: }