sd-dns.c revision e963e3ada17e7592ad499b9d7fbb3355287a05ca
ee9c9500ab13c1093fc3feaf2aa5a0d330d0bfadKay Sievers/***
19aadacf92ad86967ffb678e37b2ff9e83cb9480Jan Engelhardt This file is part of libasyncns.
cff452c7e974db5053cdbd0d7bbbab2e3b4c91b9Kay Sievers
cff452c7e974db5053cdbd0d7bbbab2e3b4c91b9Kay Sievers Copyright 2005-2008 Lennart Poettering
cff452c7e974db5053cdbd0d7bbbab2e3b4c91b9Kay Sievers
cff452c7e974db5053cdbd0d7bbbab2e3b4c91b9Kay Sievers libasyncns is free software; you can redistribute it and/or modify
f957632b960a0a42999b38ded7089fa602b41745Kay Sievers it under the terms of the GNU Lesser General Public License as
f957632b960a0a42999b38ded7089fa602b41745Kay Sievers published by the Free Software Foundation, either version 2.1 of the
f957632b960a0a42999b38ded7089fa602b41745Kay Sievers License, or (at your option) any later version.
f957632b960a0a42999b38ded7089fa602b41745Kay Sievers
a40593a0d0d740efa387e35411e1e456a6c5aba7Lennart Poettering libasyncns is distributed in the hope that it will be useful, but
20ffc4c4a9226b0e45cc02ad9c0108981626c0bbKay Sievers WITHOUT ANY WARRANTY; without even the implied warranty of
04ac799283f517672a5424e7c5bf066cfa4ca020Zbigniew Jędrzejewski-Szmek MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
04ac799283f517672a5424e7c5bf066cfa4ca020Zbigniew Jędrzejewski-Szmek Lesser General Public License for more details.
04ac799283f517672a5424e7c5bf066cfa4ca020Zbigniew Jędrzejewski-Szmek
04ac799283f517672a5424e7c5bf066cfa4ca020Zbigniew Jędrzejewski-Szmek You should have received a copy of the GNU Lesser General Public
d8160f21fd295b451cee9679aa281fedf1cb8e8cZbigniew Jędrzejewski-Szmek License along with libasyncns. If not, see
d8160f21fd295b451cee9679aa281fedf1cb8e8cZbigniew Jędrzejewski-Szmek <http://www.gnu.org/licenses/>.
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering ***/
7b4da18c1717f811bae67ea3d39290495857c03eLennart Poettering
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering#ifdef HAVE_CONFIG_H
466784c8710e5cb0e0b86a16506d992d7ec5b619Kay Sievers#include <config.h>
55d32caf94d8df547ca763be52b0c35bb6388606Lennart Poettering#endif
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering
bafb15bab99887d1b6b8a35136531bac6c3876a6Lennart Poettering#include <assert.h>
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering#include <fcntl.h>
bafb15bab99887d1b6b8a35136531bac6c3876a6Lennart Poettering#include <signal.h>
eb124a97fb72d076014253b1acde69d428f15ecfLennart Poettering#include <unistd.h>
154ff088d371bee5651eaa2bc9bde8a34c185656Lennart Poettering#include <sys/select.h>
96197df081a16bec192a6cfb8f19674ca58f4835Lennart Poettering#include <stdio.h>
96197df081a16bec192a6cfb8f19674ca58f4835Lennart Poettering#include <string.h>
96197df081a16bec192a6cfb8f19674ca58f4835Lennart Poettering#include <stdlib.h>
96197df081a16bec192a6cfb8f19674ca58f4835Lennart Poettering#include <errno.h>
0183b74fa47d7f05b7bc3b46d82daf8cebb17fa7Lennart Poettering#include <sys/wait.h>
0183b74fa47d7f05b7bc3b46d82daf8cebb17fa7Lennart Poettering#include <sys/types.h>
0183b74fa47d7f05b7bc3b46d82daf8cebb17fa7Lennart Poettering#include <pwd.h>
0183b74fa47d7f05b7bc3b46d82daf8cebb17fa7Lennart Poettering#include <netinet/in.h>
0183b74fa47d7f05b7bc3b46d82daf8cebb17fa7Lennart Poettering#include <arpa/nameser.h>
0183b74fa47d7f05b7bc3b46d82daf8cebb17fa7Lennart Poettering#include <resolv.h>
0183b74fa47d7f05b7bc3b46d82daf8cebb17fa7Lennart Poettering#include <dirent.h>
0183b74fa47d7f05b7bc3b46d82daf8cebb17fa7Lennart Poettering#include <sys/time.h>
0183b74fa47d7f05b7bc3b46d82daf8cebb17fa7Lennart Poettering#include <sys/resource.h>
d4fdc205a4610965cee46408dbd046c922e7620cLennart Poettering#include <stdint.h>
d4fdc205a4610965cee46408dbd046c922e7620cLennart Poettering#include <pthread.h>
d4fdc205a4610965cee46408dbd046c922e7620cLennart Poettering
7bb2954901b2e568efaf67254e480032e0958cadLennart Poettering#ifdef HAVE_SYS_PRCTL_H
7bb2954901b2e568efaf67254e480032e0958cadLennart Poettering#include <sys/prctl.h>
7bb2954901b2e568efaf67254e480032e0958cadLennart Poettering#endif
7bb2954901b2e568efaf67254e480032e0958cadLennart Poettering
7bb2954901b2e568efaf67254e480032e0958cadLennart Poettering#include "sd-dns.h"
7bb2954901b2e568efaf67254e480032e0958cadLennart Poettering#include "util.h"
7bb2954901b2e568efaf67254e480032e0958cadLennart Poettering
7bb2954901b2e568efaf67254e480032e0958cadLennart Poettering#define MAX_WORKERS 16
7bb2954901b2e568efaf67254e480032e0958cadLennart Poettering#define MAX_QUERIES 256
7bb2954901b2e568efaf67254e480032e0958cadLennart Poettering#define BUFSIZE (10240)
7bb2954901b2e568efaf67254e480032e0958cadLennart Poettering
7bb2954901b2e568efaf67254e480032e0958cadLennart Poetteringtypedef enum {
7bb2954901b2e568efaf67254e480032e0958cadLennart Poettering REQUEST_ADDRINFO,
7bb2954901b2e568efaf67254e480032e0958cadLennart Poettering RESPONSE_ADDRINFO,
0f3e07b7cc535af3c4ea56c3b28c140c1771fa6aLennart Poettering REQUEST_NAMEINFO,
0f3e07b7cc535af3c4ea56c3b28c140c1771fa6aLennart Poettering RESPONSE_NAMEINFO,
0f3e07b7cc535af3c4ea56c3b28c140c1771fa6aLennart Poettering REQUEST_RES_QUERY,
0f3e07b7cc535af3c4ea56c3b28c140c1771fa6aLennart Poettering REQUEST_RES_SEARCH,
af1082b04a3d45a9b1d796b4271f44e87e307026Lennart Poettering RESPONSE_RES,
af1082b04a3d45a9b1d796b4271f44e87e307026Lennart Poettering REQUEST_TERMINATE,
af1082b04a3d45a9b1d796b4271f44e87e307026Lennart Poettering RESPONSE_DIED
af1082b04a3d45a9b1d796b4271f44e87e307026Lennart Poettering} query_type_t;
af1082b04a3d45a9b1d796b4271f44e87e307026Lennart Poettering
3540c7f88fd4b860d3d6d0e931ddb7cd91bc559aLennart Poetteringenum {
488ad3b32a7e2b5b1380abf4a15e5f65fa65f3feLennart Poettering REQUEST_RECV_FD = 0,
488ad3b32a7e2b5b1380abf4a15e5f65fa65f3feLennart Poettering REQUEST_SEND_FD = 1,
488ad3b32a7e2b5b1380abf4a15e5f65fa65f3feLennart Poettering RESPONSE_RECV_FD = 2,
488ad3b32a7e2b5b1380abf4a15e5f65fa65f3feLennart Poettering RESPONSE_SEND_FD = 3,
488ad3b32a7e2b5b1380abf4a15e5f65fa65f3feLennart Poettering MESSAGE_FD_MAX = 4
488ad3b32a7e2b5b1380abf4a15e5f65fa65f3feLennart Poettering};
47c94a96df29080f8b3a97e7362df4e9c6ba3265Lennart Poettering
47c94a96df29080f8b3a97e7362df4e9c6ba3265Lennart Poetteringstruct asyncns {
09ecd746c9d6581664873674c2188f8c93ed7780Lennart Poettering int fds[MESSAGE_FD_MAX];
09ecd746c9d6581664873674c2188f8c93ed7780Lennart Poettering
09ecd746c9d6581664873674c2188f8c93ed7780Lennart Poettering pthread_t workers[MAX_WORKERS];
09ecd746c9d6581664873674c2188f8c93ed7780Lennart Poettering unsigned valid_workers;
09ecd746c9d6581664873674c2188f8c93ed7780Lennart Poettering
09ecd746c9d6581664873674c2188f8c93ed7780Lennart Poettering unsigned current_id, current_index;
09ecd746c9d6581664873674c2188f8c93ed7780Lennart Poettering asyncns_query_t* queries[MAX_QUERIES];
ef417cfd2211ae017a38b9796c6db29130133e63Zbigniew Jędrzejewski-Szmek
ef417cfd2211ae017a38b9796c6db29130133e63Zbigniew Jędrzejewski-Szmek asyncns_query_t *done_head, *done_tail;
ef417cfd2211ae017a38b9796c6db29130133e63Zbigniew Jędrzejewski-Szmek
ef417cfd2211ae017a38b9796c6db29130133e63Zbigniew Jędrzejewski-Szmek int n_queries;
ef417cfd2211ae017a38b9796c6db29130133e63Zbigniew Jędrzejewski-Szmek int dead;
3333d748facc15f49935b6b793490ba0824976e6Zbigniew Jędrzejewski-Szmek};
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poetteringstruct asyncns_query {
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering asyncns_t *asyncns;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering int done;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering unsigned id;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering query_type_t type;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering asyncns_query_t *done_next, *done_prev;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering int ret;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering int _errno;
0bee65f0622c4faa8ac8ae771cc0c8a936dfa284Lennart Poettering int _h_errno;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering struct addrinfo *addrinfo;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering char *serv, *host;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering void *userdata;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering};
ebcf1f97de4f6b1580ae55eb56b1a3939fe6b602Lennart Poettering
47c94a96df29080f8b3a97e7362df4e9c6ba3265Lennart Poetteringtypedef struct rheader {
47c94a96df29080f8b3a97e7362df4e9c6ba3265Lennart Poettering query_type_t type;
718db96199eb307751264e4163555662c9a389faLennart Poettering unsigned id;
718db96199eb307751264e4163555662c9a389faLennart Poettering size_t length;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering} rheader_t;
718db96199eb307751264e4163555662c9a389faLennart Poettering
718db96199eb307751264e4163555662c9a389faLennart Poetteringtypedef struct addrinfo_request {
718db96199eb307751264e4163555662c9a389faLennart Poettering struct rheader header;
966204e010ed432a1d7a0481d41a326d8ec7b0c8Lennart Poettering int hints_is_null;
966204e010ed432a1d7a0481d41a326d8ec7b0c8Lennart Poettering int ai_flags;
94676f3e9352cbf1f72e0a512ee0d2ed83ff676dLennart Poettering int ai_family;
6fd4d0209827e5c3e52fa8c7144852f550f8f95cLennart Poettering int ai_socktype;
ced4d06784dbb19666688947901961f949f2aa6dLennart Poettering int ai_protocol;
ced4d06784dbb19666688947901961f949f2aa6dLennart Poettering size_t node_len, service_len;
af1082b04a3d45a9b1d796b4271f44e87e307026Lennart Poettering} addrinfo_request_t;
416446221d905b6815175dc4d525d27f8ae43d1bLennart Poettering
416446221d905b6815175dc4d525d27f8ae43d1bLennart Poetteringtypedef struct addrinfo_response {
416446221d905b6815175dc4d525d27f8ae43d1bLennart Poettering struct rheader header;
baa89da40a1d42242c9c62603501ada7e9e52613Lennart Poettering int ret;
baa89da40a1d42242c9c62603501ada7e9e52613Lennart Poettering int _errno;
7f79cd7109a60810140a045cc725291fc5515264Lennart Poettering int _h_errno;
0aafd43d235982510d1c40564079f7bcec0c7c19Lennart Poettering /* followed by addrinfo_serialization[] */
19aadacf92ad86967ffb678e37b2ff9e83cb9480Jan Engelhardt} addrinfo_response_t;
19aadacf92ad86967ffb678e37b2ff9e83cb9480Jan Engelhardt
df5f6971e6e15b4632884916c71daa076c8bae96Lennart Poetteringtypedef struct addrinfo_serialization {
df5f6971e6e15b4632884916c71daa076c8bae96Lennart Poettering int ai_flags;
fcba531ed4c6e6f8f21d8ca4e3a56e3162b1c578Lennart Poettering int ai_family;
fcba531ed4c6e6f8f21d8ca4e3a56e3162b1c578Lennart Poettering int ai_socktype;
8b8f259170e35b93e6c6d1757cb8b835bbdaa40cZbigniew Jędrzejewski-Szmek int ai_protocol;
8b8f259170e35b93e6c6d1757cb8b835bbdaa40cZbigniew Jędrzejewski-Szmek size_t ai_addrlen;
e10e429f2dcbb586215e65f62847f40c7d8b5956David Herrmann size_t canonname_len;
e1b7e7ec9b34ae6ae54a4c8084395cbf2bfe9960Lennart Poettering /* Followed by ai_addr amd ai_canonname with variable lengths */
6aaa8c2f783cd1b3ac27c5ce40625d032e7e3d71Zbigniew Jędrzejewski-Szmek} addrinfo_serialization_t;
c3bb87dbab8b79bb9253407cb5b7f3e6fe8db395Lennart Poettering
e1b7e7ec9b34ae6ae54a4c8084395cbf2bfe9960Lennart Poetteringtypedef struct nameinfo_request {
18d4e7c26e7806ac363d19989df7144d5058ce41Lennart Poettering struct rheader header;
bdeeb6b543a2a2d0a494f17b85f1498859cdfc2fLennart Poettering int flags;
bdeeb6b543a2a2d0a494f17b85f1498859cdfc2fLennart Poettering socklen_t sockaddr_len;
bdeeb6b543a2a2d0a494f17b85f1498859cdfc2fLennart Poettering int gethost, getserv;
bdeeb6b543a2a2d0a494f17b85f1498859cdfc2fLennart Poettering} nameinfo_request_t;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
69af45035913e7119cffd94c542bd3039600e45dZbigniew Jędrzejewski-Szmektypedef struct nameinfo_response {
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering struct rheader header;
466784c8710e5cb0e0b86a16506d992d7ec5b619Kay Sievers size_t hostlen, servlen;
466784c8710e5cb0e0b86a16506d992d7ec5b619Kay Sievers int ret;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering int _errno;
19aadacf92ad86967ffb678e37b2ff9e83cb9480Jan Engelhardt int _h_errno;
1f263d4dc23b9807ac6138eb5014d3d94c5fe51aLennart Poettering} nameinfo_response_t;
4e09014daf8f98584b3f15e64e93bed232e70a6bLennart Poettering
4e09014daf8f98584b3f15e64e93bed232e70a6bLennart Poetteringtypedef struct res_request {
4e09014daf8f98584b3f15e64e93bed232e70a6bLennart Poettering struct rheader header;
6bb648a16ae4a682ad4784412af706d2e6a3e4daTom Gundersen int class;
eb01ba5de14859d7a94835ab9299de40132d549aLennart Poettering int type;
86312ab8de59c1066d6d2b456f3a9106ce3e0991Lennart Poettering size_t dname_len;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering} res_request_t;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering
bee7e928990fd8a0c5909c2022a2b9eede557c81Lennart Poetteringtypedef struct res_response {
bee7e928990fd8a0c5909c2022a2b9eede557c81Lennart Poettering struct rheader header;
80caea6cc72ebd311a311b1527cc6b87201c13bfLennart Poettering int ret;
ab9716c2489f9141ed13ec22dbb216b3e6fbd6b5Lennart Poettering int _errno;
452de75e5b8b1cff207243848f4e5de68620554cLennart Poettering int _h_errno;
df98a87ba389bdfc0359beedf47557411f3af434Lennart Poettering} res_response_t;
df98a87ba389bdfc0359beedf47557411f3af434Lennart Poettering
df98a87ba389bdfc0359beedf47557411f3af434Lennart Poetteringtypedef union packet {
df98a87ba389bdfc0359beedf47557411f3af434Lennart Poettering rheader_t rheader;
bee7e928990fd8a0c5909c2022a2b9eede557c81Lennart Poettering addrinfo_request_t addrinfo_request;
0058679911db806b6db2fa445a1ce879a436c9d6Lennart Poettering addrinfo_response_t addrinfo_response;
6a8b5fa4635ed858788fb10099ec9b62b3359a0aLennart Poettering nameinfo_request_t nameinfo_request;
ab9716c2489f9141ed13ec22dbb216b3e6fbd6b5Lennart Poettering nameinfo_response_t nameinfo_response;
ab9716c2489f9141ed13ec22dbb216b3e6fbd6b5Lennart Poettering res_request_t res_request;
69727e6dc69ae5d9b5ae3681723778a3faa354e9Lennart Poettering res_response_t res_response;
2fcb3af6a2931cfc74c8602ab68f00bc99b61b1cLennart Poettering} packet_t;
0f3e07b7cc535af3c4ea56c3b28c140c1771fa6aLennart Poettering
0f3e07b7cc535af3c4ea56c3b28c140c1771fa6aLennart Poetteringstatic int send_died(int out_fd) {
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering rheader_t rh = {};
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering assert(out_fd > 0);
12179984a38fe74581333fbcdc11c822d81f505fLennart Poettering
eb01ba5de14859d7a94835ab9299de40132d549aLennart Poettering rh.type = RESPONSE_DIED;
154ff088d371bee5651eaa2bc9bde8a34c185656Lennart Poettering rh.id = 0;
154ff088d371bee5651eaa2bc9bde8a34c185656Lennart Poettering rh.length = sizeof(rh);
154ff088d371bee5651eaa2bc9bde8a34c185656Lennart Poettering
154ff088d371bee5651eaa2bc9bde8a34c185656Lennart Poettering return send(out_fd, &rh, rh.length, MSG_NOSIGNAL);
69af45035913e7119cffd94c542bd3039600e45dZbigniew Jędrzejewski-Szmek}
e8a7a315391a6a07897122725cd707f4e9ce63d7Lennart Poettering
461bd8e47cafacfcd38389e7558330bfb6e902adLennart Poetteringstatic void *serialize_addrinfo(void *p, const struct addrinfo *ai, size_t *length, size_t maxlength) {
461bd8e47cafacfcd38389e7558330bfb6e902adLennart Poettering addrinfo_serialization_t s;
461bd8e47cafacfcd38389e7558330bfb6e902adLennart Poettering size_t cnl, l;
ab8e074ce25b9947314c69e17afe1bd2527ee26dLennart Poettering assert(p);
ab8e074ce25b9947314c69e17afe1bd2527ee26dLennart Poettering assert(ai);
ab8e074ce25b9947314c69e17afe1bd2527ee26dLennart Poettering assert(length);
ab8e074ce25b9947314c69e17afe1bd2527ee26dLennart Poettering assert(*length <= maxlength);
b454b11220e87add6d0f011695c7912b009c853dLennart Poettering
b454b11220e87add6d0f011695c7912b009c853dLennart Poettering cnl = (ai->ai_canonname ? strlen(ai->ai_canonname)+1 : 0);
b454b11220e87add6d0f011695c7912b009c853dLennart Poettering l = sizeof(addrinfo_serialization_t) + ai->ai_addrlen + cnl;
b454b11220e87add6d0f011695c7912b009c853dLennart Poettering
06db8540cdfc8259423ed90e7352dbc1d71eccd9Lennart Poettering if (*length + l > maxlength)
06db8540cdfc8259423ed90e7352dbc1d71eccd9Lennart Poettering return NULL;
4ff49cb63075aba646b578f2516b37a8dfd5a65bLennart Poettering
4ff49cb63075aba646b578f2516b37a8dfd5a65bLennart Poettering s.ai_flags = ai->ai_flags;
fff87a35d9e26c0d4ea41273a963c0eb20e18da4Zbigniew Jędrzejewski-Szmek s.ai_family = ai->ai_family;
fff87a35d9e26c0d4ea41273a963c0eb20e18da4Zbigniew Jędrzejewski-Szmek s.ai_socktype = ai->ai_socktype;
fff87a35d9e26c0d4ea41273a963c0eb20e18da4Zbigniew Jędrzejewski-Szmek s.ai_protocol = ai->ai_protocol;
b8b4d3dddc7611dce3bf28004b0375d661120c62Lennart Poettering s.ai_addrlen = ai->ai_addrlen;
b8b4d3dddc7611dce3bf28004b0375d661120c62Lennart Poettering s.canonname_len = cnl;
b8b4d3dddc7611dce3bf28004b0375d661120c62Lennart Poettering
3df82d5a8cdc510f518fd5e234ccb3233b748719Lennart Poettering memcpy((uint8_t*) p, &s, sizeof(addrinfo_serialization_t));
3df82d5a8cdc510f518fd5e234ccb3233b748719Lennart Poettering memcpy((uint8_t*) p + sizeof(addrinfo_serialization_t), ai->ai_addr, ai->ai_addrlen);
3df82d5a8cdc510f518fd5e234ccb3233b748719Lennart Poettering
3df82d5a8cdc510f518fd5e234ccb3233b748719Lennart Poettering if (ai->ai_canonname)
b5c03638d48c07aa0eaf13b5f54000c7133e1883Lennart Poettering strcpy((char*) p + sizeof(addrinfo_serialization_t) + ai->ai_addrlen, ai->ai_canonname);
b5c03638d48c07aa0eaf13b5f54000c7133e1883Lennart Poettering
b5c03638d48c07aa0eaf13b5f54000c7133e1883Lennart Poettering *length += l;
b5c03638d48c07aa0eaf13b5f54000c7133e1883Lennart Poettering return (uint8_t*) p + l;
b5c03638d48c07aa0eaf13b5f54000c7133e1883Lennart Poettering}
eece8c6fb5f4d354dcef6fd369e876c4f3a3f163Lennart Poettering
eece8c6fb5f4d354dcef6fd369e876c4f3a3f163Lennart Poetteringstatic int send_addrinfo_reply(int out_fd, unsigned id, int ret, struct addrinfo *ai, int _errno, int _h_errno) {
eece8c6fb5f4d354dcef6fd369e876c4f3a3f163Lennart Poettering addrinfo_response_t data[BUFSIZE/sizeof(addrinfo_response_t) + 1] = {};
356ce9915ab1a4a1e6dc26954df34936a69e7c12Lennart Poettering addrinfo_response_t *resp = data;
356ce9915ab1a4a1e6dc26954df34936a69e7c12Lennart Poettering assert(out_fd >= 0);
09f727eebd87661f263d3c2c1e0de7b7771acd40Lennart Poettering
09f727eebd87661f263d3c2c1e0de7b7771acd40Lennart Poettering resp->header.type = RESPONSE_ADDRINFO;
09f727eebd87661f263d3c2c1e0de7b7771acd40Lennart Poettering resp->header.id = id;
795607b22308f5b92073b012e43be1892fdd97c0Lennart Poettering resp->header.length = sizeof(addrinfo_response_t);
795607b22308f5b92073b012e43be1892fdd97c0Lennart Poettering resp->ret = ret;
795607b22308f5b92073b012e43be1892fdd97c0Lennart Poettering resp->_errno = _errno;
795607b22308f5b92073b012e43be1892fdd97c0Lennart Poettering resp->_h_errno = _h_errno;
795607b22308f5b92073b012e43be1892fdd97c0Lennart Poettering
0be8342c04bbf129b4a21e5073eacccbbce4e896Lennart Poettering if (ret == 0 && ai) {
0be8342c04bbf129b4a21e5073eacccbbce4e896Lennart Poettering void *p = data + 1;
0be8342c04bbf129b4a21e5073eacccbbce4e896Lennart Poettering struct addrinfo *k;
0be8342c04bbf129b4a21e5073eacccbbce4e896Lennart Poettering
0be8342c04bbf129b4a21e5073eacccbbce4e896Lennart Poettering for (k = ai; k; k = k->ai_next) {
e5ec62c56963d997edaffa904af5dc45dac23988Lennart Poettering if (!(p = serialize_addrinfo(p, k, &resp->header.length, (char*) data + BUFSIZE - (char*) p))) {
54c31a79f72ff57ac8eba089acacc4ab482b745dLennart Poettering resp->ret = EAI_MEMORY;
826872b61e4857dfffe63ba84e2b005623baecd6Lennart Poettering break;
826872b61e4857dfffe63ba84e2b005623baecd6Lennart Poettering }
54c31a79f72ff57ac8eba089acacc4ab482b745dLennart Poettering }
826872b61e4857dfffe63ba84e2b005623baecd6Lennart Poettering }
3679d1126bae52e02f6cd60fca196f616b9e660dLennart Poettering
3679d1126bae52e02f6cd60fca196f616b9e660dLennart Poettering if (ai)
3679d1126bae52e02f6cd60fca196f616b9e660dLennart Poettering freeaddrinfo(ai);
3679d1126bae52e02f6cd60fca196f616b9e660dLennart Poettering
3679d1126bae52e02f6cd60fca196f616b9e660dLennart Poettering return send(out_fd, resp, resp->header.length, MSG_NOSIGNAL);
3679d1126bae52e02f6cd60fca196f616b9e660dLennart Poettering}
cbb7712189527f9f483321607e44c4ead3dd11b8Lennart Poettering
cbb7712189527f9f483321607e44c4ead3dd11b8Lennart Poetteringstatic int send_nameinfo_reply(int out_fd, unsigned id, int ret, const char *host, const char *serv, int _errno, int _h_errno) {
d01a73b6396f57792113c1b5df6e8492fc703e5eLennart Poettering nameinfo_response_t data[BUFSIZE/sizeof(nameinfo_response_t) + 1] = {};
d01a73b6396f57792113c1b5df6e8492fc703e5eLennart Poettering size_t hl, sl;
f8aeee1f1fe432924b355f48f01f09c9a552ed97Lennart Poettering nameinfo_response_t *resp = data;
f8aeee1f1fe432924b355f48f01f09c9a552ed97Lennart Poettering
f8aeee1f1fe432924b355f48f01f09c9a552ed97Lennart Poettering assert(out_fd >= 0);
f8aeee1f1fe432924b355f48f01f09c9a552ed97Lennart Poettering
f8aeee1f1fe432924b355f48f01f09c9a552ed97Lennart Poettering sl = serv ? strlen(serv)+1 : 0;
356ce9915ab1a4a1e6dc26954df34936a69e7c12Lennart Poettering hl = host ? strlen(host)+1 : 0;
490b7e47093d491a2bdb1084fe92b796f4e07eefLennart Poettering
81d112a8f0522a09fcfe317f420363a2b728137cLennart Poettering resp->header.type = RESPONSE_NAMEINFO;
490b7e47093d491a2bdb1084fe92b796f4e07eefLennart Poettering resp->header.id = id;
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering resp->header.length = sizeof(nameinfo_response_t) + hl + sl;
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering resp->ret = ret;
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering resp->_errno = _errno;
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering resp->_h_errno = _h_errno;
466784c8710e5cb0e0b86a16506d992d7ec5b619Kay Sievers resp->hostlen = hl;
e41814846c19a48f4490169d82e359e005c4db45Lennart Poettering resp->servlen = sl;
c0fe5db522b52f27e030655ce2c03e05cbbc1558Kay Sievers
e9fd44b728ff1fc0d1f24fccb87a767f6865df27Lennart Poettering assert(sizeof(data) >= resp->header.length);
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering
e9fd44b728ff1fc0d1f24fccb87a767f6865df27Lennart Poettering if (host)
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering memcpy((uint8_t *)data + sizeof(nameinfo_response_t), host, hl);
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering
3040728b6691ea2e9df3a2060e2d49a792bbaedaLennart Poettering if (serv)
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering memcpy((uint8_t *)data + sizeof(nameinfo_response_t) + hl, serv, sl);
8ed206517c2be381324ac5832bf34cc14024270eLennart Poettering
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering return send(out_fd, resp, resp->header.length, MSG_NOSIGNAL);
e6c6e7afffa80ad74efdb1ddfa815294624f1608Lennart Poettering}
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poetteringstatic int send_res_reply(int out_fd, unsigned id, const unsigned char *answer, int ret, int _errno, int _h_errno) {
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering res_response_t data[BUFSIZE/sizeof(res_response_t) + 1] = {};
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering res_response_t *resp = data;
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering assert(out_fd >= 0);
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering
e5ec62c56963d997edaffa904af5dc45dac23988Lennart Poettering resp->header.type = RESPONSE_RES;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering resp->header.id = id;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering resp->header.length = sizeof(res_response_t) + (ret < 0 ? 0 : ret);
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering resp->ret = ret;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering resp->_errno = _errno;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering resp->_h_errno = _h_errno;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering assert(sizeof(data) >= resp->header.length);
e673ad0415d89c322e5b1a121e411f1b1d8075c0Lennart Poettering
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering if (ret > 0)
e673ad0415d89c322e5b1a121e411f1b1d8075c0Lennart Poettering memcpy((uint8_t *)data + sizeof(res_response_t), answer, ret);
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering
e673ad0415d89c322e5b1a121e411f1b1d8075c0Lennart Poettering return send(out_fd, resp, resp->header.length, MSG_NOSIGNAL);
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering}
c06bf414042cd1bf94e0af63e9e2a0c291bfc546Kay Sievers
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poetteringstatic int handle_request(int out_fd, const packet_t *packet, size_t length) {
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering const rheader_t *req;
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering assert(out_fd >= 0);
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering req = &packet->rheader;
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering assert(req);
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering assert(length >= sizeof(rheader_t));
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering assert(length == req->length);
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering switch (req->type) {
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering case REQUEST_ADDRINFO: {
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering struct addrinfo ai = {}, *result = NULL;
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering const addrinfo_request_t *ai_req = &packet->addrinfo_request;
f47ec8ebb3858553dec870e1c596e39525f46360Lennart Poettering const char *node, *service;
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering int ret;
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering assert(length >= sizeof(addrinfo_request_t));
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering assert(length == sizeof(addrinfo_request_t) + ai_req->node_len + ai_req->service_len);
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering ai.ai_flags = ai_req->ai_flags;
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering ai.ai_family = ai_req->ai_family;
f47ec8ebb3858553dec870e1c596e39525f46360Lennart Poettering ai.ai_socktype = ai_req->ai_socktype;
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering ai.ai_protocol = ai_req->ai_protocol;
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering node = ai_req->node_len ? (const char*) ai_req + sizeof(addrinfo_request_t) : NULL;
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering service = ai_req->service_len ? (const char*) ai_req + sizeof(addrinfo_request_t) + ai_req->node_len : NULL;
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering ret = getaddrinfo(node, service,
601d9d6fb394a780765e80581daab850623e9698Josh Triplett ai_req->hints_is_null ? NULL : &ai,
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering &result);
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering /* send_addrinfo_reply() frees result */
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering return send_addrinfo_reply(out_fd, req->id, ret, result, errno, h_errno);
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering }
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering case REQUEST_NAMEINFO: {
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering int ret;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering const nameinfo_request_t *ni_req = &packet->nameinfo_request;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering char hostbuf[NI_MAXHOST], servbuf[NI_MAXSERV];
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering struct sockaddr_storage sa;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering assert(length >= sizeof(nameinfo_request_t));
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering assert(length == sizeof(nameinfo_request_t) + ni_req->sockaddr_len);
8b8f259170e35b93e6c6d1757cb8b835bbdaa40cZbigniew Jędrzejewski-Szmek
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering memcpy(&sa, (const uint8_t *) ni_req + sizeof(nameinfo_request_t), ni_req->sockaddr_len);
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering ret = getnameinfo((struct sockaddr *)&sa, ni_req->sockaddr_len,
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering ni_req->gethost ? hostbuf : NULL, ni_req->gethost ? sizeof(hostbuf) : 0,
eb124a97fb72d076014253b1acde69d428f15ecfLennart Poettering ni_req->getserv ? servbuf : NULL, ni_req->getserv ? sizeof(servbuf) : 0,
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering ni_req->flags);
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering return send_nameinfo_reply(out_fd, req->id, ret,
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering ret == 0 && ni_req->gethost ? hostbuf : NULL,
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering ret == 0 && ni_req->getserv ? servbuf : NULL,
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering errno, h_errno);
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering }
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering case REQUEST_RES_QUERY:
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering case REQUEST_RES_SEARCH: {
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering int ret;
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering HEADER answer[BUFSIZE/sizeof(HEADER) + 1];
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering const res_request_t *res_req = &packet->res_request;
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering const char *dname;
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering assert(length >= sizeof(res_request_t));
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering assert(length == sizeof(res_request_t) + res_req->dname_len);
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering dname = (const char *) req + sizeof(res_request_t);
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering if (req->type == REQUEST_RES_QUERY)
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering ret = res_query(dname, res_req->class, res_req->type, (unsigned char *) answer, BUFSIZE);
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering else
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering ret = res_search(dname, res_req->class, res_req->type, (unsigned char *) answer, BUFSIZE);
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering
8b8f259170e35b93e6c6d1757cb8b835bbdaa40cZbigniew Jędrzejewski-Szmek return send_res_reply(out_fd, req->id, (unsigned char *) answer, ret, errno, h_errno);
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering }
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering case REQUEST_TERMINATE:
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering /* Quit */
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering return -1;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering default:
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering ;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering }
8b04b925e587ff56568c62ff5ad3f2ea2b34ca7aLennart Poettering
e673ad0415d89c322e5b1a121e411f1b1d8075c0Lennart Poettering return 0;
e673ad0415d89c322e5b1a121e411f1b1d8075c0Lennart Poettering}
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poetteringstatic void* thread_worker(void *p) {
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering asyncns_t *asyncns = p;
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering sigset_t fullset;
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering /* No signals in this thread please */
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering sigfillset(&fullset);
eb124a97fb72d076014253b1acde69d428f15ecfLennart Poettering pthread_sigmask(SIG_BLOCK, &fullset, NULL);
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering while (!asyncns->dead) {
90e071d1d59be05fcba66561439c3ca67c80ee20Lennart Poettering packet_t buf[BUFSIZE/sizeof(packet_t) + 1];
90e071d1d59be05fcba66561439c3ca67c80ee20Lennart Poettering ssize_t length;
d2e83c23f5f0cdd3b6ec05c5c40209708721e704Kay Sievers
d2e83c23f5f0cdd3b6ec05c5c40209708721e704Kay Sievers length = recv(asyncns->fds[REQUEST_RECV_FD], buf, sizeof(buf), 0);
d2e83c23f5f0cdd3b6ec05c5c40209708721e704Kay Sievers
d2e83c23f5f0cdd3b6ec05c5c40209708721e704Kay Sievers if (length <= 0) {
f6113d42d015ad9f3a9e702a09eb8006511a4424Kay Sievers if (length < 0 && (errno == EAGAIN || errno == EINTR))
f6113d42d015ad9f3a9e702a09eb8006511a4424Kay Sievers continue;
d2e83c23f5f0cdd3b6ec05c5c40209708721e704Kay Sievers break;
7a43e910ce00eef22fd42925ae4c85cbea1b1320Kay Sievers }
d2e83c23f5f0cdd3b6ec05c5c40209708721e704Kay Sievers
c55b1b59b837dfd924b704d457ed77c55f8bfeabLennart Poettering if (asyncns->dead)
59704f3e937c664f7324bfbb08483c358dfbc4c6Lennart Poettering break;
59704f3e937c664f7324bfbb08483c358dfbc4c6Lennart Poettering
59704f3e937c664f7324bfbb08483c358dfbc4c6Lennart Poettering if (handle_request(asyncns->fds[RESPONSE_SEND_FD], buf, (size_t) length) < 0)
9ec82de1725ddaab333149171b790d62c47ae133Lennart Poettering break;
e707c49485b8f4f2ec040d3da232d39153e650b9Lennart Poettering }
e707c49485b8f4f2ec040d3da232d39153e650b9Lennart Poettering
e707c49485b8f4f2ec040d3da232d39153e650b9Lennart Poettering send_died(asyncns->fds[RESPONSE_SEND_FD]);
7f8732835295fce29479b1afc9e8ee801852db09Lennart Poettering
7f8732835295fce29479b1afc9e8ee801852db09Lennart Poettering return NULL;
7f8732835295fce29479b1afc9e8ee801852db09Lennart Poettering}
e707c49485b8f4f2ec040d3da232d39153e650b9Lennart Poettering
a19554ed92a7460b4e709cc40c558cde827ab85bLennart Poetteringasyncns_t* asyncns_new(unsigned n_proc) {
a19554ed92a7460b4e709cc40c558cde827ab85bLennart Poettering int i;
1cb88f2c61f590083847d65cd5a518e834da87d3Lennart Poettering asyncns_t *asyncns = NULL;
1cb88f2c61f590083847d65cd5a518e834da87d3Lennart Poettering
1cb88f2c61f590083847d65cd5a518e834da87d3Lennart Poettering assert(n_proc >= 1);
1cb88f2c61f590083847d65cd5a518e834da87d3Lennart Poettering
1cb88f2c61f590083847d65cd5a518e834da87d3Lennart Poettering if (n_proc > MAX_WORKERS)
603cd8fe07cb03e8b11722d1a732e569e5a46347Lennart Poettering n_proc = MAX_WORKERS;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering
6d0274f11547a0f11200bb82bf598a5a253e12cfLennart Poettering asyncns = malloc(sizeof(asyncns_t));
a7a3f28be404875eff20443a0fa8088bcc4c18dfLennart Poettering if (!asyncns) {
a7a3f28be404875eff20443a0fa8088bcc4c18dfLennart Poettering errno = ENOMEM;
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering goto fail;
08f9588885c5d65694b324846b0ed19211d2c178Lennart Poettering }
7d8197d1f25c1291855bb6cffc705444978c6d8dKay Sievers
7d8197d1f25c1291855bb6cffc705444978c6d8dKay Sievers asyncns->dead = 0;
7d8197d1f25c1291855bb6cffc705444978c6d8dKay Sievers asyncns->valid_workers = 0;
7d8197d1f25c1291855bb6cffc705444978c6d8dKay Sievers
7d8197d1f25c1291855bb6cffc705444978c6d8dKay Sievers for (i = 0; i < MESSAGE_FD_MAX; i++)
7d8197d1f25c1291855bb6cffc705444978c6d8dKay Sievers asyncns->fds[i] = -1;
7d8197d1f25c1291855bb6cffc705444978c6d8dKay Sievers
9ee58bddeb6eb044753167e0047fe836479ca5dbKay Sievers memset(asyncns->queries, 0, sizeof(asyncns->queries));
9ee58bddeb6eb044753167e0047fe836479ca5dbKay Sievers
dcfc4b2e5c1af6375488c00bdc6fb8122f86c4d7Lennart Poettering#ifdef SOCK_CLOEXEC
71ef24d09573874c0f7bc323c07c3aec2a458707Lennart Poettering if (socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, asyncns->fds) < 0 ||
71ef24d09573874c0f7bc323c07c3aec2a458707Lennart Poettering socketpair(PF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0, asyncns->fds+2) < 0) {
1b89884ba31cbe98f159ce2c7d6fac5f6a57698fLennart Poettering
1b89884ba31cbe98f159ce2c7d6fac5f6a57698fLennart Poettering /* Try again, without SOCK_CLOEXEC */
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering if (errno == EINVAL) {
86d0d519429b85b0cad93c8c9fe8e68c5b9a4fe3Lennart Poettering#endif
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering if (socketpair(PF_UNIX, SOCK_DGRAM, 0, asyncns->fds) < 0 ||
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering socketpair(PF_UNIX, SOCK_DGRAM, 0, asyncns->fds+2) < 0)
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering goto fail;
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering#ifdef SOCK_CLOEXEC
3679d1126bae52e02f6cd60fca196f616b9e660dLennart Poettering } else
9cb74bcb23dde8488459ca233bf9caee642b8402Zbigniew Jędrzejewski-Szmek goto fail;
a56b63f41dc779a86573ae77814c14c1db156398Lennart Poettering }
af1082b04a3d45a9b1d796b4271f44e87e307026Lennart Poettering#endif
af1082b04a3d45a9b1d796b4271f44e87e307026Lennart Poettering
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering for (i = 0; i < MESSAGE_FD_MAX; i++)
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering fd_cloexec(asyncns->fds[i], true);
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering for (asyncns->valid_workers = 0; asyncns->valid_workers < n_proc; asyncns->valid_workers++) {
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering int r;
5f1dac6bf605871615b35891a3966fa474db5b20Lennart Poettering
f801968466fed39d50d410b30ac828c26722cc95Lennart Poettering if ((r = pthread_create(&asyncns->workers[asyncns->valid_workers], NULL, thread_worker, asyncns)) != 0) {
424a19f8a2061c6b058283228734010b2fa24db4Lennart Poettering errno = r;
41f9172f427bdbb8221c64029f78364b8dd4e527Lennart Poettering goto fail;
424a19f8a2061c6b058283228734010b2fa24db4Lennart Poettering }
424a19f8a2061c6b058283228734010b2fa24db4Lennart Poettering }
424a19f8a2061c6b058283228734010b2fa24db4Lennart Poettering
a1cccad1fe88ddd6943e18af97cf7f466296970fLennart Poettering asyncns->current_index = asyncns->current_id = 0;
a1cccad1fe88ddd6943e18af97cf7f466296970fLennart Poettering asyncns->done_head = asyncns->done_tail = NULL;
8556879e0d14925ce897875c6c264368e2d048c2Lennart Poettering asyncns->n_queries = 0;
d05c556b6b2a680ec8b51ecbbc99a9ab14c28eedZbigniew Jędrzejewski-Szmek
8556879e0d14925ce897875c6c264368e2d048c2Lennart Poettering fd_nonblock(asyncns->fds[RESPONSE_RECV_FD], true);
8556879e0d14925ce897875c6c264368e2d048c2Lennart Poettering
8556879e0d14925ce897875c6c264368e2d048c2Lennart Poettering return asyncns;
4a30847b9d71e0381948d68279c8f775b9de7850Lennart Poettering
4a30847b9d71e0381948d68279c8f775b9de7850Lennart Poetteringfail:
5e8b28838e493b59628322b69580097ef7dd9384Lennart Poettering if (asyncns)
5e8b28838e493b59628322b69580097ef7dd9384Lennart Poettering asyncns_free(asyncns);
d87be9b0af81a6e07d4fb3028e45c4409100dc26Lennart Poettering
d87be9b0af81a6e07d4fb3028e45c4409100dc26Lennart Poettering return NULL;
38a60d7112d33ffd596b23e8df53d75a7c09e71bLennart Poettering}
38a60d7112d33ffd596b23e8df53d75a7c09e71bLennart Poettering
d8b78264a5245307babbf5af8e39d6d4a1ae095fLennart Poetteringvoid asyncns_free(asyncns_t *asyncns) {
d8b78264a5245307babbf5af8e39d6d4a1ae095fLennart Poettering int i;
68f160039eb78fe122cfe0d4c49695ae91f6f0d1Lennart Poettering int saved_errno = errno;
0790b9fed42eefc4e22dbbe2337cba9713b7848cLennart Poettering unsigned p;
5a7e959984788cf89719dec31999409b63bb802bLennart Poettering
5a7e959984788cf89719dec31999409b63bb802bLennart Poettering assert(asyncns);
68f160039eb78fe122cfe0d4c49695ae91f6f0d1Lennart Poettering
68f160039eb78fe122cfe0d4c49695ae91f6f0d1Lennart Poettering asyncns->dead = 1;
68f160039eb78fe122cfe0d4c49695ae91f6f0d1Lennart Poettering
68f160039eb78fe122cfe0d4c49695ae91f6f0d1Lennart Poettering if (asyncns->fds[REQUEST_SEND_FD] >= 0) {
edca2e2348b314e2d892fe6f8ae276fdc223f014Thomas Hindoe Paaboel Andersen rheader_t req = {};
68f160039eb78fe122cfe0d4c49695ae91f6f0d1Lennart Poettering
0790b9fed42eefc4e22dbbe2337cba9713b7848cLennart Poettering req.type = REQUEST_TERMINATE;
fd4d89b2c0b31da01d134301e30916931ae3c7d9Lennart Poettering req.length = sizeof(req);
fd4d89b2c0b31da01d134301e30916931ae3c7d9Lennart Poettering req.id = 0;
8230e26dc954a40d8c9dbc8ddd9376117021f9d2Lennart Poettering
8230e26dc954a40d8c9dbc8ddd9376117021f9d2Lennart Poettering /* Send one termination packet for each worker */
4d9909c93e9c58789c71b34555a1908307c6849eLennart Poettering for (p = 0; p < asyncns->valid_workers; p++)
4d9909c93e9c58789c71b34555a1908307c6849eLennart Poettering send(asyncns->fds[REQUEST_SEND_FD], &req, req.length, MSG_NOSIGNAL);
47ae7201b1df43bd3da83a19e38483b0e5694c99Lennart Poettering }
47ae7201b1df43bd3da83a19e38483b0e5694c99Lennart Poettering
88a6c5894c9d3f85d63b87b040c130366b4006ceKay Sievers /* Now terminate them and wait until they are gone. */
8351ceaea9480d9c2979aa2ff0f4982cfdfef58dLennart Poettering for (p = 0; p < asyncns->valid_workers; p++) {
bcd02123e10a23d79b0317072ed8d4a250163475Lennart Poettering for (;;) {
c66d36e5b5ae81f3c5297d6dacadc13c88c530f6Lennart Poettering if (pthread_join(asyncns->workers[p], NULL) != EINTR)
9946996cda11a18b44d82344676e5a0e96339408Lennart Poettering break;
9946996cda11a18b44d82344676e5a0e96339408Lennart Poettering }
9946996cda11a18b44d82344676e5a0e96339408Lennart Poettering }
3471bedc005fab03f40b99bf6599645330adcd9eLennart Poettering
3471bedc005fab03f40b99bf6599645330adcd9eLennart Poettering /* Close all communication channels */
59cea26a349cfa8db906b520dac72563dd773ff2Lennart Poettering for (i = 0; i < MESSAGE_FD_MAX; i++)
35eb6b124ebdf82bd77aad6e44962a9a039c4d33Lennart Poettering if (asyncns->fds[i] >= 0)
5b40d33761376354116a8cddb9b9fbdb6c4727d6Lennart Poettering close(asyncns->fds[i]);
5b40d33761376354116a8cddb9b9fbdb6c4727d6Lennart Poettering
d3a3f22267a7dac426b07a7ed0baa1632f5daf04Kay Sievers for (p = 0; p < MAX_QUERIES; p++)
d3a3f22267a7dac426b07a7ed0baa1632f5daf04Kay Sievers if (asyncns->queries[p])
d3a3f22267a7dac426b07a7ed0baa1632f5daf04Kay Sievers asyncns_cancel(asyncns, asyncns->queries[p]);
d3a3f22267a7dac426b07a7ed0baa1632f5daf04Kay Sievers
d3a3f22267a7dac426b07a7ed0baa1632f5daf04Kay Sievers free(asyncns);
d3a3f22267a7dac426b07a7ed0baa1632f5daf04Kay Sievers
d3a3f22267a7dac426b07a7ed0baa1632f5daf04Kay Sievers errno = saved_errno;
d3a3f22267a7dac426b07a7ed0baa1632f5daf04Kay Sievers}
d3a3f22267a7dac426b07a7ed0baa1632f5daf04Kay Sievers
d3a3f22267a7dac426b07a7ed0baa1632f5daf04Kay Sieversint asyncns_fd(asyncns_t *asyncns) {
465349c06d994dd2cc6b6fc4109ac0b9952d500aLennart Poettering assert(asyncns);
e01a15b71e18bf2008aec7e75041ffa42eb80b80Kay Sievers
a888b352eb53b07daa24fa859ceeb254336b293dLennart Poettering return asyncns->fds[RESPONSE_RECV_FD];
abd55b16547d0bb0ed1c31e72e16838f0f59f48bKay Sievers}
3f60bcb5e69846fe8a3156ca1c9a7e0813ac158aKay Sievers
abd55b16547d0bb0ed1c31e72e16838f0f59f48bKay Sieversstatic asyncns_query_t *lookup_query(asyncns_t *asyncns, unsigned id) {
abd55b16547d0bb0ed1c31e72e16838f0f59f48bKay Sievers asyncns_query_t *q;
abd55b16547d0bb0ed1c31e72e16838f0f59f48bKay Sievers assert(asyncns);
e8d842a0d0b39f298e1e7f70d29759e50b2b16d4Tom Gundersen
b8217b7bd5fd171916a095b150fad4c3a37f5a41Kay Sievers if ((q = asyncns->queries[id % MAX_QUERIES]))
169c4f65131fbc7bcb51e7d5487a715cdcd0e0ebLennart Poettering if (q->id == id)
169c4f65131fbc7bcb51e7d5487a715cdcd0e0ebLennart Poettering return q;
fb0864e7b9c6d26269ccea6ec5c0fd921c029781Lennart Poettering
fb0864e7b9c6d26269ccea6ec5c0fd921c029781Lennart Poettering return NULL;
9586cdfab6a2638078702b7fea7e16b3a71899e2Lennart Poettering}
9586cdfab6a2638078702b7fea7e16b3a71899e2Lennart Poettering
7f110ff9b8828b477e87de7b28c708cf69a3d008Lennart Poetteringstatic void complete_query(asyncns_t *asyncns, asyncns_query_t *q) {
7f110ff9b8828b477e87de7b28c708cf69a3d008Lennart Poettering assert(asyncns);
d0e5a33374cee92962af33dfc03873e470b014f6Lennart Poettering assert(q);
d0e5a33374cee92962af33dfc03873e470b014f6Lennart Poettering assert(!q->done);
d0e5a33374cee92962af33dfc03873e470b014f6Lennart Poettering
d0e5a33374cee92962af33dfc03873e470b014f6Lennart Poettering q->done = 1;
87a8baa35d6d65ac3b58ae8e26e338e67f8ae8edLennart Poettering
87a8baa35d6d65ac3b58ae8e26e338e67f8ae8edLennart Poettering if ((q->done_prev = asyncns->done_tail))
87a8baa35d6d65ac3b58ae8e26e338e67f8ae8edLennart Poettering asyncns->done_tail->done_next = q;
87a8baa35d6d65ac3b58ae8e26e338e67f8ae8edLennart Poettering else
65c0cf7108ae3537a357c74b4586a783baba82f9Lennart Poettering asyncns->done_head = q;
65c0cf7108ae3537a357c74b4586a783baba82f9Lennart Poettering
f957632b960a0a42999b38ded7089fa602b41745Kay Sievers asyncns->done_tail = q;
f957632b960a0a42999b38ded7089fa602b41745Kay Sievers q->done_next = NULL;
f957632b960a0a42999b38ded7089fa602b41745Kay Sievers}
ad740100d108282d0244d5739d4dcc86fe4c5fdeLennart Poettering
ad740100d108282d0244d5739d4dcc86fe4c5fdeLennart Poetteringstatic const void *unserialize_addrinfo(const void *p, struct addrinfo **ret_ai, size_t *length) {
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering addrinfo_serialization_t s;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering size_t l;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering struct addrinfo *ai;
7d441ddb5ca090b5a97f58ac4b4d97b3e84fa81eLennart Poettering assert(p);
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering assert(ret_ai);
14e639ae7a1dbf156273ce697d30fbc6c6594209Lennart Poettering assert(length);
ff01d048b4c1455241c894cf7982662c9d28fd34Lennart Poettering
ff01d048b4c1455241c894cf7982662c9d28fd34Lennart Poettering if (*length < sizeof(addrinfo_serialization_t))
d3c7d7dd77b2b72315164b672462825cef6c0f9aKay Sievers return NULL;
72b9ed828bd22f3ddd74b6853c183eebf006d6d8Lennart Poettering
1d6702e8d3877c0bebf3ac817dc45ff72f5ecfa9Lennart Poettering memcpy(&s, p, sizeof(s));
1d6702e8d3877c0bebf3ac817dc45ff72f5ecfa9Lennart Poettering
1d6702e8d3877c0bebf3ac817dc45ff72f5ecfa9Lennart Poettering l = sizeof(addrinfo_serialization_t) + s.ai_addrlen + s.canonname_len;
71092d70af35567dd154d3de2ce04ce62e157a7cLennart Poettering if (*length < l)
71092d70af35567dd154d3de2ce04ce62e157a7cLennart Poettering return NULL;
1258097cd3cdbc5dd3d264850119e553a29c5068Lennart Poettering
1258097cd3cdbc5dd3d264850119e553a29c5068Lennart Poettering if (!(ai = malloc(sizeof(struct addrinfo))))
1258097cd3cdbc5dd3d264850119e553a29c5068Lennart Poettering goto fail;
a4c279f87451186b8beb1b8cc21c7cad561ecf4bLennart Poettering
a4c279f87451186b8beb1b8cc21c7cad561ecf4bLennart Poettering ai->ai_addr = NULL;
7c697168102cb64c5cb65a542959684014da99c7Lennart Poettering ai->ai_canonname = NULL;
253ee27a0c7a410d27d490bb79ea97caed6a2b68Lennart Poettering ai->ai_next = NULL;
71092d70af35567dd154d3de2ce04ce62e157a7cLennart Poettering
8d0e38a2b966799af884e78a54fd6a2dffa44788Lennart Poettering if (s.ai_addrlen && !(ai->ai_addr = malloc(s.ai_addrlen)))
f28f1daf754a9a07de90e6fc4ada581bf5de677dLennart Poettering goto fail;
f28f1daf754a9a07de90e6fc4ada581bf5de677dLennart Poettering
f28f1daf754a9a07de90e6fc4ada581bf5de677dLennart Poettering if (s.canonname_len && !(ai->ai_canonname = malloc(s.canonname_len)))
f28f1daf754a9a07de90e6fc4ada581bf5de677dLennart Poettering goto fail;
f38afcd0c7f558ca5bf0854b42f8c6954f8ad7f3Lennart Poettering
a012ab5293a28af93454b3105ca85ca148b1c11fDave Reisner ai->ai_flags = s.ai_flags;
88a07670cfa974a605c7c7b520b8a3135fce37f9Lennart Poettering ai->ai_family = s.ai_family;
88a07670cfa974a605c7c7b520b8a3135fce37f9Lennart Poettering ai->ai_socktype = s.ai_socktype;
88a07670cfa974a605c7c7b520b8a3135fce37f9Lennart Poettering ai->ai_protocol = s.ai_protocol;
71092d70af35567dd154d3de2ce04ce62e157a7cLennart Poettering ai->ai_addrlen = s.ai_addrlen;
916abb21d0a6653e0187b91591e492026886b0a4Lennart Poettering
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering if (ai->ai_addr)
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering memcpy(ai->ai_addr, (const uint8_t*) p + sizeof(addrinfo_serialization_t), s.ai_addrlen);
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering if (ai->ai_canonname)
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering memcpy(ai->ai_canonname, (const uint8_t*) p + sizeof(addrinfo_serialization_t) + s.ai_addrlen, s.canonname_len);
b44be3ecf6326c27aa2c6c6d1fe34e22e22592a0Lennart Poettering
b23de6af893c11da4286bc416455cd0926d1532eLennart Poettering *length -= l;
21bdae12e11ae20460715475d8a0c991f15464acLennart Poettering *ret_ai = ai;
21bdae12e11ae20460715475d8a0c991f15464acLennart Poettering
9534ce54858c67363b841cdbdc315140437bfdb4Lennart Poettering return (const uint8_t*) p + l;
9534ce54858c67363b841cdbdc315140437bfdb4Lennart Poettering
68c7d001f4117f0c3d0a4582e32cbb03ae5fac57Lennart Poettering
796b06c21b62d13c9021e2fbd9c58a5c6edb2764Kay Sieversfail:
68c7d001f4117f0c3d0a4582e32cbb03ae5fac57Lennart Poettering if (ai)
68c7d001f4117f0c3d0a4582e32cbb03ae5fac57Lennart Poettering asyncns_freeaddrinfo(ai);
7a2a0b907b5cc60f5d9a871997d7d6e7f62bf4d8Lennart Poettering
253ee27a0c7a410d27d490bb79ea97caed6a2b68Lennart Poettering return NULL;
5d0fcd7c8d29340ac9425c309e8ac436a9af699cLennart Poettering}
5d0fcd7c8d29340ac9425c309e8ac436a9af699cLennart Poettering
8bbabc447b1d913bd21faf97c7b17d20d315d2b4Lennart Poetteringstatic int handle_response(asyncns_t *asyncns, const packet_t *packet, size_t length) {
f530371f1f85a070d7d0fb5112146a43533ae00bLennart Poettering const rheader_t *resp;
e707c49485b8f4f2ec040d3da232d39153e650b9Lennart Poettering asyncns_query_t *q;
a19554ed92a7460b4e709cc40c558cde827ab85bLennart Poettering
a73d88fa024b5668ed7dde681e99547d41e6a864Lennart Poettering assert(asyncns);
a74a8793b04de9886b4f6987b9cb86fa02c73520Lennart Poettering
3040728b6691ea2e9df3a2060e2d49a792bbaedaLennart Poettering resp = &packet->rheader;
3679d1126bae52e02f6cd60fca196f616b9e660dLennart Poettering assert(resp);
3679d1126bae52e02f6cd60fca196f616b9e660dLennart Poettering assert(length >= sizeof(rheader_t));
3679d1126bae52e02f6cd60fca196f616b9e660dLennart Poettering assert(length == resp->length);
3679d1126bae52e02f6cd60fca196f616b9e660dLennart Poettering
3679d1126bae52e02f6cd60fca196f616b9e660dLennart Poettering if (resp->type == RESPONSE_DIED) {
73090dc815390f4fca4e3ed8a7e1d3806605daaaLennart Poettering asyncns->dead = 1;
44143309dd0b37d61d7d842ca58f01a65646ec71Kay Sievers return 0;
3d57c6ab801f4437f12948e29589e3d00c3ad9dbLennart Poettering }
71092d70af35567dd154d3de2ce04ce62e157a7cLennart Poettering
3f7a8c4e9f1d3ce48919e24eb2c9d56dd6fd88d8Kay Sievers if (!(q = lookup_query(asyncns, resp->id)))
260abb780a135e4cae8c10715c7e85675efc345aLennart Poettering return 0;
2791a8f8dc8764a9247cdba3562bd4c04010f144Lennart Poettering
a8f11321c209830a35edd0357e8def5d4437d854Lennart Poettering switch (resp->type) {
a8f11321c209830a35edd0357e8def5d4437d854Lennart Poettering case RESPONSE_ADDRINFO: {
Error!

 

There was an error!

null

java.lang.NullPointerException