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