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: }