inpcb: Use netisr_ncpus for listing inpcbs.
[dragonfly.git] / sbin / dhclient / privsep.c
blob4c626fab10fc6cbb6f0eca088f4de6013ece694e
1 /* $OpenBSD: src/sbin/dhclient/privsep.c,v 1.16 2011/04/04 11:14:52 krw Exp $ */
3 /*
4 * Copyright (c) 2004 Henning Brauer <henning@openbsd.org>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
15 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
16 * OF OR IN CONNECTION WITH THE USE, ABUSE OR PERFORMANCE OF THIS SOFTWARE.
19 #include "dhcpd.h"
20 #include "privsep.h"
22 struct buf *
23 buf_open(size_t len)
25 struct buf *buf;
27 if ((buf = calloc(1, sizeof(struct buf))) == NULL)
28 error("buf_open: %m");
29 if ((buf->buf = malloc(len)) == NULL) {
30 free(buf);
31 error("buf_open: %m");
33 buf->size = len;
35 return (buf);
38 void
39 buf_add(struct buf *buf, void *data, size_t len)
41 if (len == 0)
42 return;
44 if (buf->wpos + len > buf->size)
45 error("buf_add: %m");
47 memcpy(buf->buf + buf->wpos, data, len);
48 buf->wpos += len;
51 void
52 buf_close(int sock, struct buf *buf)
54 ssize_t n;
56 do {
57 n = write(sock, buf->buf + buf->rpos, buf->size - buf->rpos);
58 if (n == 0) /* connection closed */
59 error("buf_close (connection closed)");
60 if (n != -1 && n < buf->size - buf->rpos)
61 error("buf_close (short write): %m");
63 } while (n == -1 && (errno == EAGAIN || errno == EINTR));
65 if (n == -1)
66 error("buf_close: %m");
68 free(buf->buf);
69 free(buf);
72 void
73 buf_read(int sock, void *buf, size_t nbytes)
75 ssize_t n;
77 do {
78 n = read(sock, buf, nbytes);
79 if (n == 0) { /* connection closed */
80 #ifdef DEBUG
81 debug("buf_read (connection closed)");
82 #endif
83 exit(1);
85 if (n != -1 && n < nbytes)
86 error("buf_read (short read): %m");
87 } while (n == -1 && (errno == EINTR || errno == EAGAIN));
89 if (n == -1)
90 error("buf_read: %m");
93 void
94 dispatch_imsg(int fd)
96 struct imsg_hdr hdr;
97 char *reason, *filename,
98 *servername, *prefix;
99 size_t reason_len, filename_len,
100 servername_len, prefix_len, totlen;
101 struct client_lease lease;
102 int ret, i, optlen;
103 struct buf *buf;
105 buf_read(fd, &hdr, sizeof(hdr));
107 switch (hdr.code) {
108 case IMSG_SCRIPT_INIT:
109 if (hdr.len < sizeof(hdr) + sizeof(size_t))
110 error("corrupted message received");
111 buf_read(fd, &reason_len, sizeof(reason_len));
112 if (hdr.len < reason_len + sizeof(hdr) + sizeof(size_t) ||
113 reason_len == SIZE_T_MAX)
114 error("corrupted message received");
115 if (reason_len > 0) {
116 if ((reason = calloc(1, reason_len + 1)) == NULL)
117 error("%m");
118 buf_read(fd, reason, reason_len);
119 } else
120 reason = NULL;
122 priv_script_init(reason);
123 free(reason);
124 break;
125 case IMSG_SCRIPT_WRITE_PARAMS:
126 bzero(&lease, sizeof lease);
127 totlen = sizeof(hdr) + sizeof(lease) + sizeof(size_t);
128 if (hdr.len < totlen)
129 error("corrupted message received");
130 buf_read(fd, &lease, sizeof(lease));
132 buf_read(fd, &filename_len, sizeof(filename_len));
133 totlen += filename_len + sizeof(size_t);
134 if (hdr.len < totlen || filename_len == SIZE_T_MAX)
135 error("corrupted message received");
136 if (filename_len > 0) {
137 if ((filename = calloc(1, filename_len + 1)) == NULL)
138 error("%m");
139 buf_read(fd, filename, filename_len);
140 } else
141 filename = NULL;
143 buf_read(fd, &servername_len, sizeof(servername_len));
144 totlen += servername_len + sizeof(size_t);
145 if (hdr.len < totlen || servername_len == SIZE_T_MAX)
146 error("corrupted message received");
147 if (servername_len > 0) {
148 if ((servername =
149 calloc(1, servername_len + 1)) == NULL)
150 error("%m");
151 buf_read(fd, servername, servername_len);
152 } else
153 servername = NULL;
155 buf_read(fd, &prefix_len, sizeof(prefix_len));
156 totlen += prefix_len;
157 if (hdr.len < totlen || prefix_len == SIZE_T_MAX)
158 error("corrupted message received");
159 if (prefix_len > 0) {
160 if ((prefix = calloc(1, prefix_len + 1)) == NULL)
161 error("%m");
162 buf_read(fd, prefix, prefix_len);
163 } else
164 prefix = NULL;
166 for (i = 0; i < 256; i++) {
167 totlen += sizeof(optlen);
168 if (hdr.len < totlen)
169 error("corrupted message received");
170 buf_read(fd, &optlen, sizeof(optlen));
171 lease.options[i].data = NULL;
172 lease.options[i].len = optlen;
173 if (optlen > 0) {
174 totlen += optlen;
175 if (hdr.len < totlen || optlen == SIZE_T_MAX)
176 error("corrupted message received");
177 lease.options[i].data =
178 calloc(1, optlen + 1);
179 if (lease.options[i].data == NULL)
180 error("%m");
181 buf_read(fd, lease.options[i].data, optlen);
184 lease.server_name = servername;
185 lease.filename = filename;
187 priv_script_write_params(prefix, &lease);
189 free(servername);
190 free(filename);
191 free(prefix);
192 for (i = 0; i < 256; i++)
193 if (lease.options[i].len > 0)
194 free(lease.options[i].data);
195 break;
196 case IMSG_SCRIPT_GO:
197 if (hdr.len != sizeof(hdr))
198 error("corrupted message received");
200 ret = priv_script_go();
202 hdr.code = IMSG_SCRIPT_GO_RET;
203 hdr.len = sizeof(struct imsg_hdr) + sizeof(int);
204 if ((buf = buf_open(hdr.len)) == NULL)
205 error("buf_open: %m");
206 buf_add(buf, &hdr, sizeof(hdr));
207 buf_add(buf, &ret, sizeof(ret));
208 buf_close(fd, buf);
209 break;
210 default:
211 error("received unknown message, code %d", hdr.code);