/src/lldpd/src/daemon/privsep_fd.c
Line | Count | Source |
1 | | /* -*- mode: c; c-file-style: "openbsd" -*- */ |
2 | | |
3 | | #include "lldpd.h" |
4 | | |
5 | | #include <sys/param.h> |
6 | | #include <sys/uio.h> |
7 | | #include <sys/types.h> |
8 | | #include <sys/socket.h> |
9 | | #include <sys/stat.h> |
10 | | #include <errno.h> |
11 | | #include <fcntl.h> |
12 | | #include <signal.h> |
13 | | #include <stdio.h> |
14 | | #include <stdlib.h> |
15 | | #include <string.h> |
16 | | #include <unistd.h> |
17 | | |
18 | | /* |
19 | | * Copyright 2001 Niels Provos <provos@citi.umich.edu> |
20 | | * All rights reserved. |
21 | | * |
22 | | * Copyright (c) 2002 Matthieu Herrb |
23 | | * All rights reserved. |
24 | | * |
25 | | * Redistribution and use in source and binary forms, with or without |
26 | | * modification, are permitted provided that the following conditions |
27 | | * are met: |
28 | | * |
29 | | * - Redistributions of source code must retain the above copyright |
30 | | * notice, this list of conditions and the following disclaimer. |
31 | | * - Redistributions in binary form must reproduce the above |
32 | | * copyright notice, this list of conditions and the following |
33 | | * disclaimer in the documentation and/or other materials provided |
34 | | * with the distribution. |
35 | | * |
36 | | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
37 | | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
38 | | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
39 | | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
40 | | * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
41 | | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
42 | | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
43 | | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
44 | | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
45 | | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
46 | | * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
47 | | * POSSIBILITY OF SUCH DAMAGE. |
48 | | */ |
49 | | |
50 | | void |
51 | | send_fd(enum priv_context ctx, int fd) |
52 | 0 | { |
53 | 0 | struct msghdr msg; |
54 | 0 | union { |
55 | 0 | struct cmsghdr hdr; |
56 | 0 | char buf[CMSG_SPACE(sizeof(int))]; |
57 | 0 | } cmsgbuf; |
58 | 0 | struct cmsghdr *cmsg; |
59 | 0 | struct iovec vec; |
60 | 0 | int result = 0; |
61 | 0 | ssize_t n; |
62 | |
|
63 | 0 | memset(&msg, 0, sizeof(msg)); |
64 | 0 | memset(&cmsgbuf.buf, 0, sizeof(cmsgbuf.buf)); |
65 | |
|
66 | 0 | if (fd >= 0) { |
67 | 0 | msg.msg_control = (caddr_t)&cmsgbuf.buf; |
68 | 0 | msg.msg_controllen = sizeof(cmsgbuf.buf); |
69 | 0 | cmsg = CMSG_FIRSTHDR(&msg); |
70 | 0 | cmsg->cmsg_len = CMSG_LEN(sizeof(int)); |
71 | 0 | cmsg->cmsg_level = SOL_SOCKET; |
72 | 0 | cmsg->cmsg_type = SCM_RIGHTS; |
73 | 0 | memcpy(CMSG_DATA(cmsg), &fd, sizeof(int)); |
74 | 0 | } else { |
75 | 0 | result = errno; |
76 | 0 | } |
77 | |
|
78 | 0 | vec.iov_base = &result; |
79 | 0 | vec.iov_len = sizeof(int); |
80 | 0 | msg.msg_iov = &vec; |
81 | 0 | msg.msg_iovlen = 1; |
82 | |
|
83 | 0 | if ((n = sendmsg(priv_fd(ctx), &msg, 0)) == -1) |
84 | 0 | log_warn("privsep", "sendmsg(%d)", priv_fd(ctx)); |
85 | 0 | if (n != sizeof(int)) |
86 | 0 | log_warnx("privsep", "sendmsg: expected sent 1 got %ld", (long)n); |
87 | 0 | } |
88 | | |
89 | | int |
90 | | receive_fd(enum priv_context ctx) |
91 | 0 | { |
92 | 0 | struct msghdr msg; |
93 | 0 | union { |
94 | 0 | struct cmsghdr hdr; |
95 | 0 | char buf[CMSG_SPACE(sizeof(int))]; |
96 | 0 | } cmsgbuf; |
97 | 0 | struct cmsghdr *cmsg; |
98 | 0 | struct iovec vec; |
99 | 0 | ssize_t n; |
100 | 0 | int result; |
101 | 0 | int fd; |
102 | |
|
103 | 0 | memset(&msg, 0, sizeof(msg)); |
104 | 0 | vec.iov_base = &result; |
105 | 0 | vec.iov_len = sizeof(int); |
106 | 0 | msg.msg_iov = &vec; |
107 | 0 | msg.msg_iovlen = 1; |
108 | 0 | msg.msg_control = &cmsgbuf.buf; |
109 | 0 | msg.msg_controllen = sizeof(cmsgbuf.buf); |
110 | |
|
111 | 0 | if ((n = recvmsg(priv_fd(ctx), &msg, 0)) == -1) log_warn("privsep", "recvmsg"); |
112 | 0 | if (n != sizeof(int)) |
113 | 0 | log_warnx("privsep", "recvmsg: expected received 1 got %ld", (long)n); |
114 | 0 | if (result == 0) { |
115 | 0 | cmsg = CMSG_FIRSTHDR(&msg); |
116 | 0 | if (cmsg == NULL) { |
117 | 0 | log_warnx("privsep", "no message header"); |
118 | 0 | return -1; |
119 | 0 | } |
120 | 0 | if (cmsg->cmsg_type != SCM_RIGHTS) |
121 | 0 | log_warnx("privsep", "expected type %d got %d", SCM_RIGHTS, |
122 | 0 | cmsg->cmsg_type); |
123 | 0 | memcpy(&fd, CMSG_DATA(cmsg), sizeof(int)); |
124 | 0 | return fd; |
125 | 0 | } else { |
126 | | errno = result; |
127 | 0 | return -1; |
128 | 0 | } |
129 | 0 | } |