Deleted Added
full compact
ypldap_dns.c (290934) ypldap_dns.c (290937)
1/* $OpenBSD: ypldap_dns.c,v 1.8 2015/01/16 06:40:22 deraadt Exp $ */
1/* $OpenBSD: ypldap_dns.c,v 1.8 2015/01/16 06:40:22 deraadt Exp $ */
2/* $FreeBSD: head/usr.sbin/ypldap/ypldap_dns.c 290934 2015-11-16 16:58:09Z rodrigc $ */
2/* $FreeBSD: head/usr.sbin/ypldap/ypldap_dns.c 290937 2015-11-16 17:06:33Z rodrigc $ */
3
4/*
5 * Copyright (c) 2003-2008 Henning Brauer <henning@openbsd.org>
6 *
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
20#include <sys/types.h>
3
4/*
5 * Copyright (c) 2003-2008 Henning Brauer <henning@openbsd.org>
6 *
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
20#include <sys/types.h>
21#include <sys/param.h>
21#include <sys/socket.h>
22#include <sys/stat.h>
23#include <sys/time.h>
24#include <sys/tree.h>
25#include <sys/queue.h>
26
27#include <netinet/in.h>
28#include <arpa/nameser.h>
29
30#include <netdb.h>
31#include <pwd.h>
32#include <errno.h>
33#include <event.h>
34#include <resolv.h>
35#include <poll.h>
36#include <signal.h>
37#include <stdlib.h>
38#include <string.h>
39#include <unistd.h>
40#include <limits.h>
41
42#include "ypldap.h"
43
44volatile sig_atomic_t quit_dns = 0;
45struct imsgev *iev_dns;
46
47void dns_dispatch_imsg(int, short, void *);
48void dns_sig_handler(int, short, void *);
49void dns_shutdown(void);
50int host_dns(const char *s, struct ypldap_addr **hn);
51
52void
53dns_sig_handler(int sig, short event, void *p)
54{
55 switch (sig) {
56 case SIGINT:
57 case SIGTERM:
58 dns_shutdown();
59 break;
60 default:
61 fatalx("unexpected signal");
62 }
63}
64
65void
66dns_shutdown(void)
67{
68 log_info("dns engine exiting");
69 _exit(0);
70}
71
72pid_t
73ypldap_dns(int pipe_ntp[2], struct passwd *pw)
74{
75 pid_t pid;
76 struct event ev_sigint;
77 struct event ev_sigterm;
78 struct event ev_sighup;
79 struct env env;
80
81 switch (pid = fork()) {
82 case -1:
83 fatal("cannot fork");
84 break;
85 case 0:
86 break;
87 default:
88 return (pid);
89 }
90
91 setproctitle("dns engine");
92 close(pipe_ntp[0]);
93
94 if (setgroups(1, &pw->pw_gid) ||
95 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
96 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
97 fatal("can't drop privileges");
98 endservent();
99
100 event_init();
101 signal_set(&ev_sigint, SIGINT, dns_sig_handler, NULL);
102 signal_set(&ev_sigterm, SIGTERM, dns_sig_handler, NULL);
103 signal_set(&ev_sighup, SIGHUP, dns_sig_handler, NULL);
104 signal_add(&ev_sigint, NULL);
105 signal_add(&ev_sigterm, NULL);
106 signal_add(&ev_sighup, NULL);
107
108 if ((env.sc_iev = calloc(1, sizeof(*env.sc_iev))) == NULL)
109 fatal(NULL);
110
111 env.sc_iev->events = EV_READ;
112 env.sc_iev->data = &env;
113 imsg_init(&env.sc_iev->ibuf, pipe_ntp[1]);
114 env.sc_iev->handler = dns_dispatch_imsg;
115 event_set(&env.sc_iev->ev, env.sc_iev->ibuf.fd, env.sc_iev->events,
116 env.sc_iev->handler, &env);
117 event_add(&env.sc_iev->ev, NULL);
118
119 event_dispatch();
120 dns_shutdown();
121
122 return (0);
123}
124
125void
126dns_dispatch_imsg(int fd, short events, void *p)
127{
128 struct imsg imsg;
129 int n, cnt;
130 char *name;
131 struct ypldap_addr *h, *hn;
132 struct ibuf *buf;
133 struct env *env = p;
134 struct imsgev *iev = env->sc_iev;
135 struct imsgbuf *ibuf = &iev->ibuf;
136 int shut = 0;
137
138 if ((events & (EV_READ | EV_WRITE)) == 0)
139 fatalx("unknown event");
140
141 if (events & EV_READ) {
142 if ((n = imsg_read(ibuf)) == -1)
143 fatal("imsg_read error");
144 if (n == 0)
145 shut = 1;
146 }
147 if (events & EV_WRITE) {
148 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
149 fatal("msgbuf_write");
150 if (n == 0)
151 shut = 1;
152 goto done;
153 }
154
155 for (;;) {
156 if ((n = imsg_get(ibuf, &imsg)) == -1)
157 fatal("client_dispatch_imsg: imsg_get error");
158 if (n == 0)
159 break;
160
161 switch (imsg.hdr.type) {
162 case IMSG_HOST_DNS:
163 name = imsg.data;
164 if (imsg.hdr.len < 1 + IMSG_HEADER_SIZE)
165 fatalx("invalid IMSG_HOST_DNS received");
166 imsg.hdr.len -= 1 + IMSG_HEADER_SIZE;
167 if (name[imsg.hdr.len] != '\0' ||
168 strlen(name) != imsg.hdr.len)
169 fatalx("invalid IMSG_HOST_DNS received");
170 if ((cnt = host_dns(name, &hn)) == -1)
171 break;
172 buf = imsg_create(ibuf, IMSG_HOST_DNS,
173 imsg.hdr.peerid, 0,
174 cnt * sizeof(struct sockaddr_storage));
175 if (buf == NULL)
176 break;
177 if (cnt > 0) {
178 h = hn;
179 while (h != NULL) {
180 imsg_add(buf, &h->ss, sizeof(h->ss));
181 hn = h->next;
182 free(h);
183 h = hn;
184 }
185 }
186
187 imsg_close(ibuf, buf);
188 break;
189 default:
190 break;
191 }
192 imsg_free(&imsg);
193 }
194
195done:
196 if (!shut)
197 imsg_event_add(iev);
198 else {
199 /* this pipe is dead, so remove the event handler */
200 event_del(&iev->ev);
201 event_loopexit(NULL);
202 }
203}
204
205int
206host_dns(const char *s, struct ypldap_addr **hn)
207{
208 struct addrinfo hints, *res0, *res;
209 int error, cnt = 0;
210 struct sockaddr_in *sa_in;
211 struct sockaddr_in6 *sa_in6;
212 struct ypldap_addr *h, *hh = NULL;
213
214 bzero(&hints, sizeof(hints));
215 hints.ai_family = PF_UNSPEC;
216 hints.ai_socktype = SOCK_DGRAM; /* DUMMY */
217 error = getaddrinfo(s, NULL, &hints, &res0);
218 if (error == EAI_AGAIN || error == EAI_NONAME)
219 return (0);
220 if (error) {
221 log_warnx("could not parse \"%s\": %s", s,
222 gai_strerror(error));
223 return (-1);
224 }
225
226 for (res = res0; res && cnt < MAX_SERVERS_DNS; res = res->ai_next) {
227 if (res->ai_family != AF_INET &&
228 res->ai_family != AF_INET6)
229 continue;
230 if ((h = calloc(1, sizeof(struct ypldap_addr))) == NULL)
231 fatal(NULL);
232 h->ss.ss_family = res->ai_family;
233 if (res->ai_family == AF_INET) {
234 sa_in = (struct sockaddr_in *)&h->ss;
235 sa_in->sin_len = sizeof(struct sockaddr_in);
236 sa_in->sin_addr.s_addr = ((struct sockaddr_in *)
237 res->ai_addr)->sin_addr.s_addr;
238 } else {
239 sa_in6 = (struct sockaddr_in6 *)&h->ss;
240 sa_in6->sin6_len = sizeof(struct sockaddr_in6);
241 memcpy(&sa_in6->sin6_addr, &((struct sockaddr_in6 *)
242 res->ai_addr)->sin6_addr, sizeof(struct in6_addr));
243 }
244
245 h->next = hh;
246 hh = h;
247 cnt++;
248 }
249 freeaddrinfo(res0);
250
251 *hn = hh;
252 return (cnt);
253}
22#include <sys/socket.h>
23#include <sys/stat.h>
24#include <sys/time.h>
25#include <sys/tree.h>
26#include <sys/queue.h>
27
28#include <netinet/in.h>
29#include <arpa/nameser.h>
30
31#include <netdb.h>
32#include <pwd.h>
33#include <errno.h>
34#include <event.h>
35#include <resolv.h>
36#include <poll.h>
37#include <signal.h>
38#include <stdlib.h>
39#include <string.h>
40#include <unistd.h>
41#include <limits.h>
42
43#include "ypldap.h"
44
45volatile sig_atomic_t quit_dns = 0;
46struct imsgev *iev_dns;
47
48void dns_dispatch_imsg(int, short, void *);
49void dns_sig_handler(int, short, void *);
50void dns_shutdown(void);
51int host_dns(const char *s, struct ypldap_addr **hn);
52
53void
54dns_sig_handler(int sig, short event, void *p)
55{
56 switch (sig) {
57 case SIGINT:
58 case SIGTERM:
59 dns_shutdown();
60 break;
61 default:
62 fatalx("unexpected signal");
63 }
64}
65
66void
67dns_shutdown(void)
68{
69 log_info("dns engine exiting");
70 _exit(0);
71}
72
73pid_t
74ypldap_dns(int pipe_ntp[2], struct passwd *pw)
75{
76 pid_t pid;
77 struct event ev_sigint;
78 struct event ev_sigterm;
79 struct event ev_sighup;
80 struct env env;
81
82 switch (pid = fork()) {
83 case -1:
84 fatal("cannot fork");
85 break;
86 case 0:
87 break;
88 default:
89 return (pid);
90 }
91
92 setproctitle("dns engine");
93 close(pipe_ntp[0]);
94
95 if (setgroups(1, &pw->pw_gid) ||
96 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
97 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
98 fatal("can't drop privileges");
99 endservent();
100
101 event_init();
102 signal_set(&ev_sigint, SIGINT, dns_sig_handler, NULL);
103 signal_set(&ev_sigterm, SIGTERM, dns_sig_handler, NULL);
104 signal_set(&ev_sighup, SIGHUP, dns_sig_handler, NULL);
105 signal_add(&ev_sigint, NULL);
106 signal_add(&ev_sigterm, NULL);
107 signal_add(&ev_sighup, NULL);
108
109 if ((env.sc_iev = calloc(1, sizeof(*env.sc_iev))) == NULL)
110 fatal(NULL);
111
112 env.sc_iev->events = EV_READ;
113 env.sc_iev->data = &env;
114 imsg_init(&env.sc_iev->ibuf, pipe_ntp[1]);
115 env.sc_iev->handler = dns_dispatch_imsg;
116 event_set(&env.sc_iev->ev, env.sc_iev->ibuf.fd, env.sc_iev->events,
117 env.sc_iev->handler, &env);
118 event_add(&env.sc_iev->ev, NULL);
119
120 event_dispatch();
121 dns_shutdown();
122
123 return (0);
124}
125
126void
127dns_dispatch_imsg(int fd, short events, void *p)
128{
129 struct imsg imsg;
130 int n, cnt;
131 char *name;
132 struct ypldap_addr *h, *hn;
133 struct ibuf *buf;
134 struct env *env = p;
135 struct imsgev *iev = env->sc_iev;
136 struct imsgbuf *ibuf = &iev->ibuf;
137 int shut = 0;
138
139 if ((events & (EV_READ | EV_WRITE)) == 0)
140 fatalx("unknown event");
141
142 if (events & EV_READ) {
143 if ((n = imsg_read(ibuf)) == -1)
144 fatal("imsg_read error");
145 if (n == 0)
146 shut = 1;
147 }
148 if (events & EV_WRITE) {
149 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
150 fatal("msgbuf_write");
151 if (n == 0)
152 shut = 1;
153 goto done;
154 }
155
156 for (;;) {
157 if ((n = imsg_get(ibuf, &imsg)) == -1)
158 fatal("client_dispatch_imsg: imsg_get error");
159 if (n == 0)
160 break;
161
162 switch (imsg.hdr.type) {
163 case IMSG_HOST_DNS:
164 name = imsg.data;
165 if (imsg.hdr.len < 1 + IMSG_HEADER_SIZE)
166 fatalx("invalid IMSG_HOST_DNS received");
167 imsg.hdr.len -= 1 + IMSG_HEADER_SIZE;
168 if (name[imsg.hdr.len] != '\0' ||
169 strlen(name) != imsg.hdr.len)
170 fatalx("invalid IMSG_HOST_DNS received");
171 if ((cnt = host_dns(name, &hn)) == -1)
172 break;
173 buf = imsg_create(ibuf, IMSG_HOST_DNS,
174 imsg.hdr.peerid, 0,
175 cnt * sizeof(struct sockaddr_storage));
176 if (buf == NULL)
177 break;
178 if (cnt > 0) {
179 h = hn;
180 while (h != NULL) {
181 imsg_add(buf, &h->ss, sizeof(h->ss));
182 hn = h->next;
183 free(h);
184 h = hn;
185 }
186 }
187
188 imsg_close(ibuf, buf);
189 break;
190 default:
191 break;
192 }
193 imsg_free(&imsg);
194 }
195
196done:
197 if (!shut)
198 imsg_event_add(iev);
199 else {
200 /* this pipe is dead, so remove the event handler */
201 event_del(&iev->ev);
202 event_loopexit(NULL);
203 }
204}
205
206int
207host_dns(const char *s, struct ypldap_addr **hn)
208{
209 struct addrinfo hints, *res0, *res;
210 int error, cnt = 0;
211 struct sockaddr_in *sa_in;
212 struct sockaddr_in6 *sa_in6;
213 struct ypldap_addr *h, *hh = NULL;
214
215 bzero(&hints, sizeof(hints));
216 hints.ai_family = PF_UNSPEC;
217 hints.ai_socktype = SOCK_DGRAM; /* DUMMY */
218 error = getaddrinfo(s, NULL, &hints, &res0);
219 if (error == EAI_AGAIN || error == EAI_NONAME)
220 return (0);
221 if (error) {
222 log_warnx("could not parse \"%s\": %s", s,
223 gai_strerror(error));
224 return (-1);
225 }
226
227 for (res = res0; res && cnt < MAX_SERVERS_DNS; res = res->ai_next) {
228 if (res->ai_family != AF_INET &&
229 res->ai_family != AF_INET6)
230 continue;
231 if ((h = calloc(1, sizeof(struct ypldap_addr))) == NULL)
232 fatal(NULL);
233 h->ss.ss_family = res->ai_family;
234 if (res->ai_family == AF_INET) {
235 sa_in = (struct sockaddr_in *)&h->ss;
236 sa_in->sin_len = sizeof(struct sockaddr_in);
237 sa_in->sin_addr.s_addr = ((struct sockaddr_in *)
238 res->ai_addr)->sin_addr.s_addr;
239 } else {
240 sa_in6 = (struct sockaddr_in6 *)&h->ss;
241 sa_in6->sin6_len = sizeof(struct sockaddr_in6);
242 memcpy(&sa_in6->sin6_addr, &((struct sockaddr_in6 *)
243 res->ai_addr)->sin6_addr, sizeof(struct in6_addr));
244 }
245
246 h->next = hh;
247 hh = h;
248 cnt++;
249 }
250 freeaddrinfo(res0);
251
252 *hn = hh;
253 return (cnt);
254}