entropy.c revision 0c27b3fe77ac1d5094ba3521e8142d9e7973133f
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder/*
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder * Copyright (C) 2000-2008, 2012, 2016 Internet Systems Consortium, Inc. ("ISC")
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder *
e6d40133bc9f858308654afb1262b8b483ec5922Till Mossakowski * This Source Code Form is subject to the terms of the Mozilla Public
2725abe920f91de62ae5c0b7230c1627cccf5fabChristian Maeder * License, v. 2.0. If a copy of the MPL was not distributed with this
98890889ffb2e8f6f722b00e265a211f13b5a861Corneliu-Claudiu Prodescu * file, You can obtain one at http://mozilla.org/MPL/2.0/.
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder */
3f69b6948966979163bdfe8331c38833d5d90ecdChristian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder/* $Id: entropy.c,v 1.82 2008/12/01 23:47:45 tbox Exp $ */
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder/* \file unix/entropy.c
f3a94a197960e548ecd6520bb768cb0d547457bbChristian Maeder * \brief
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder * This is the system dependent part of the ISC entropy API.
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder */
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder#include <config.h>
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder#include <sys/param.h> /* Openserver 5.0.6A and FD_SETSIZE */
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder#include <sys/types.h>
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder#include <sys/time.h>
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder#include <sys/stat.h>
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder#include <sys/socket.h>
ea5ccb1c6e89486a54e1f4bd95840147e96093edChristian Maeder#include <sys/un.h>
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder#ifdef HAVE_NANOSLEEP
85e1d54a475bfc30b3eac5ae6c5e42a2d7e93f10Christian Maeder#include <time.h>
85e1d54a475bfc30b3eac5ae6c5e42a2d7e93f10Christian Maeder#endif
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder#include <unistd.h>
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder#include <isc/platform.h>
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder#include <isc/strerror.h>
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder#ifdef ISC_PLATFORM_NEEDSYSSELECTH
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder#include <sys/select.h>
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder#endif
0130083f314580170af1195037be3325f125fbceChristian Maeder
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder#include "errno2result.h"
0130083f314580170af1195037be3325f125fbceChristian Maeder
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder/*%
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder * There is only one variable in the entropy data structures that is not
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder * system independent, but pulling the structure that uses it into this file
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder * ultimately means pulling several other independent structures here also to
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder * resolve their interdependencies. Thus only the problem variable's type
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder * is defined here.
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder */
bbba6dd86153aacb0f662b182b128df0eb09fd54Christian Maeder#define FILESOURCE_HANDLE_TYPE int
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder
a461314c811f4187dff85c8be079a41b2f13f176Christian Maedertypedef struct {
4eb859461f8fd904f40f57261cf23e5c73cf8ecaChristian Maeder int handle;
109a53dbf4c9233f869f63ba7a7f3fece49973c3Christian Maeder enum {
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder isc_usocketsource_disconnected,
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder isc_usocketsource_connecting,
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder isc_usocketsource_connected,
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder isc_usocketsource_ndesired,
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder isc_usocketsource_wrote,
f39b8dd9651dfcc38b06191cda23cacbfc298323Christian Maeder isc_usocketsource_reading
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder } status;
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder size_t sz_to_recv;
3a9d784341454573b50b32fa1b494e7418df3086Christian Maeder} isc_entropyusocketsource_t;
dff1de7ad15d1582e25d636c3724dd202874897fChristian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder#include "../entropy.c"
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
9d6562465b41f17c7967d4e5678f34811d958cb2Christian Maederstatic unsigned int
b53688bfed888214b485cf76439d57262d80e0a7Christian Maederget_from_filesource(isc_entropysource_t *source, isc_uint32_t desired) {
502483734c83d0bf1eadcc94113d0362f8713784Christian Maeder isc_entropy_t *ent = source->ent;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder unsigned char buf[128];
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder int fd = source->sources.file.handle;
7f7460e7095628f3437b116ee78d3043d11f8febChristian Maeder ssize_t n, ndesired;
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder unsigned int added;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
96ae1a1d2197d0e0d5b80da2474b64c456feb1b0Christian Maeder if (source->bad)
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder return (0);
38c817b94e0a5b1ae94178b1075c187e07bcc5e1Christian Maeder
38c817b94e0a5b1ae94178b1075c187e07bcc5e1Christian Maeder desired = desired / 8 + (((desired & 0x07) > 0) ? 1 : 0);
38c817b94e0a5b1ae94178b1075c187e07bcc5e1Christian Maeder
38c817b94e0a5b1ae94178b1075c187e07bcc5e1Christian Maeder added = 0;
4eb859461f8fd904f40f57261cf23e5c73cf8ecaChristian Maeder while (desired > 0) {
4eb859461f8fd904f40f57261cf23e5c73cf8ecaChristian Maeder ndesired = ISC_MIN(desired, sizeof(buf));
4eb859461f8fd904f40f57261cf23e5c73cf8ecaChristian Maeder n = read(fd, buf, ndesired);
4eb859461f8fd904f40f57261cf23e5c73cf8ecaChristian Maeder if (n < 0) {
4eb859461f8fd904f40f57261cf23e5c73cf8ecaChristian Maeder if (errno == EAGAIN || errno == EINTR)
4eb859461f8fd904f40f57261cf23e5c73cf8ecaChristian Maeder goto out;
4eb859461f8fd904f40f57261cf23e5c73cf8ecaChristian Maeder goto err;
4eb859461f8fd904f40f57261cf23e5c73cf8ecaChristian Maeder }
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder if (n == 0)
2353f65833a3da763392f771223250cd50b8d873Christian Maeder goto err;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder entropypool_adddata(ent, buf, n, n * 8);
dff1de7ad15d1582e25d636c3724dd202874897fChristian Maeder added += n * 8;
dff1de7ad15d1582e25d636c3724dd202874897fChristian Maeder desired -= n;
96ae1a1d2197d0e0d5b80da2474b64c456feb1b0Christian Maeder }
8c8545dd3bf34fbcbc16904b65d249658f8f9efcChristian Maeder goto out;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
d81905a5b924415c524d702df26204683c82c12eChristian Maeder err:
96ae1a1d2197d0e0d5b80da2474b64c456feb1b0Christian Maeder (void)close(fd);
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder source->sources.file.handle = -1;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder source->bad = ISC_TRUE;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder out:
dff1de7ad15d1582e25d636c3724dd202874897fChristian Maeder return (added);
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder}
cb2044812811d66efe038d914966e04290be93faChristian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maederstatic unsigned int
b53688bfed888214b485cf76439d57262d80e0a7Christian Maederget_from_usocketsource(isc_entropysource_t *source, isc_uint32_t desired) {
dff1de7ad15d1582e25d636c3724dd202874897fChristian Maeder isc_entropy_t *ent = source->ent;
0ae7a79e865d4a6022d705d160530682b3c1f825Christian Maeder unsigned char buf[128];
083bc1972a66d73749760eab3a90bf4eb9ca7951Christian Maeder int fd = source->sources.usocket.handle;
6352f3c31da3043783a13be6594aacb2147378baRazvan Pascanu ssize_t n = 0, ndesired;
fefee7e1dee1ee5f0768a03a4abae88d1ca2c3fdRazvan Pascanu unsigned int added;
b324cda6178c49ddeead3ce62b832ccf644cbcabRazvan Pascanu size_t sz_to_recv = source->sources.usocket.sz_to_recv;
fefee7e1dee1ee5f0768a03a4abae88d1ca2c3fdRazvan Pascanu
bc263f610d20a9cd3014ddfca903026127fa0d48Christian Maeder if (source->bad)
966519955f5f7111abac20118563132b9dd41165Christian Maeder return (0);
8c8545dd3bf34fbcbc16904b65d249658f8f9efcChristian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder desired = desired / 8 + (((desired & 0x07) > 0) ? 1 : 0);
0b13f102310e03a20b38c870b5acb88712f316a4Christian Maeder
0b13f102310e03a20b38c870b5acb88712f316a4Christian Maeder added = 0;
0b13f102310e03a20b38c870b5acb88712f316a4Christian Maeder while (desired > 0) {
33fcc19ef2b59493b4e91eebf701df95fd230765Christian Maeder ndesired = ISC_MIN(desired, sizeof(buf));
33fcc19ef2b59493b4e91eebf701df95fd230765Christian Maeder eagain_loop:
33fcc19ef2b59493b4e91eebf701df95fd230765Christian Maeder
d4ebd9e5adc974cfa2bdf4bdd155e07be0e26f75Christian Maeder switch ( source->sources.usocket.status ) {
d4ebd9e5adc974cfa2bdf4bdd155e07be0e26f75Christian Maeder case isc_usocketsource_ndesired:
d4ebd9e5adc974cfa2bdf4bdd155e07be0e26f75Christian Maeder buf[0] = ndesired;
8865728716566f42fa73e7e0bc080ba3225df764Christian Maeder if ((n = sendto(fd, buf, 1, 0, NULL, 0)) < 0) {
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder if (errno == EWOULDBLOCK || errno == EINTR ||
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder errno == ECONNRESET)
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder goto out;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder goto err;
2360728d4185c0c04279c999941c64d36626af79Christian Maeder }
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder INSIST(n == 1);
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder source->sources.usocket.status =
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder isc_usocketsource_wrote;
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder goto eagain_loop;
fdac680252d7347858bd67b4c2a2aaa52e623815Christian Maeder
fdac680252d7347858bd67b4c2a2aaa52e623815Christian Maeder case isc_usocketsource_connecting:
a9e804dbec424ec36e34bab955cbe90edac5baa6Christian Maeder case isc_usocketsource_connected:
f8cc2399c16fcda7e3bf9d901a0de0cc8a455f86Ewaryst Schulz buf[0] = 1;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder buf[1] = ndesired;
b76d27eba526ecac2a20400fa505ec5c642ae7d2Dominik Luecke if ((n = sendto(fd, buf, 2, 0, NULL, 0)) < 0) {
b76d27eba526ecac2a20400fa505ec5c642ae7d2Dominik Luecke if (errno == EWOULDBLOCK || errno == EINTR ||
8a5c05062ef501bf725a86a370a5145a198e81fdKlaus Luettich errno == ECONNRESET)
8a5c05062ef501bf725a86a370a5145a198e81fdKlaus Luettich goto out;
8a5c05062ef501bf725a86a370a5145a198e81fdKlaus Luettich goto err;
2353f65833a3da763392f771223250cd50b8d873Christian Maeder }
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder if (n == 1) {
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder source->sources.usocket.status =
2353f65833a3da763392f771223250cd50b8d873Christian Maeder isc_usocketsource_ndesired;
2353f65833a3da763392f771223250cd50b8d873Christian Maeder goto eagain_loop;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder }
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder INSIST(n == 2);
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder source->sources.usocket.status =
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder isc_usocketsource_wrote;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder /*FALLTHROUGH*/
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder case isc_usocketsource_wrote:
0b13f102310e03a20b38c870b5acb88712f316a4Christian Maeder if (recvfrom(fd, buf, 1, 0, NULL, NULL) != 1) {
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder if (errno == EAGAIN) {
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder /*
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder * The problem of EAGAIN (try again
00df6fd583c19393fa141d5a0e21ac74c7bf5b19Christian Maeder * later) is a major issue on HP-UX.
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder * Solaris actually tries the recvfrom
cb2044812811d66efe038d914966e04290be93faChristian Maeder * call again, while HP-UX just dies.
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder * This code is an attempt to let the
96ae1a1d2197d0e0d5b80da2474b64c456feb1b0Christian Maeder * entropy pool fill back up (at least
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder * that's what I think the problem is.)
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder * We go to eagain_loop because if we
8d780c893d6df5dab3dcc7d8444b7517f6547f11Christian Maeder * just "break", then the "desired"
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder * amount gets borked.
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder */
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder#ifdef HAVE_NANOSLEEP
dff1de7ad15d1582e25d636c3724dd202874897fChristian Maeder struct timespec ts;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder ts.tv_sec = 0;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder ts.tv_nsec = 1000000;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder nanosleep(&ts, NULL);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder#else
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder usleep(1000);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder#endif
bc263f610d20a9cd3014ddfca903026127fa0d48Christian Maeder goto eagain_loop;
966519955f5f7111abac20118563132b9dd41165Christian Maeder }
bbba6dd86153aacb0f662b182b128df0eb09fd54Christian Maeder if (errno == EWOULDBLOCK || errno == EINTR)
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder goto out;
d96bfd1d7a4595bfff87771b91797330fa939455Christian Maeder goto err;
d96bfd1d7a4595bfff87771b91797330fa939455Christian Maeder }
8c8545dd3bf34fbcbc16904b65d249658f8f9efcChristian Maeder source->sources.usocket.status =
d27b1887e61f1dc53d77c37f59dbf5019242a686Christian Maeder isc_usocketsource_reading;
34d14197eb3dd643a8e6ef3ed8cba5629528e97fAivaras Jakubauskas sz_to_recv = buf[0];
d4ebd9e5adc974cfa2bdf4bdd155e07be0e26f75Christian Maeder source->sources.usocket.sz_to_recv = sz_to_recv;
d4ebd9e5adc974cfa2bdf4bdd155e07be0e26f75Christian Maeder if (sz_to_recv > sizeof(buf))
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder goto err;
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder /*FALLTHROUGH*/
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder case isc_usocketsource_reading:
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder if (sz_to_recv != 0U) {
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder n = recv(fd, buf, sz_to_recv, 0);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder if (n < 0) {
0b13f102310e03a20b38c870b5acb88712f316a4Christian Maeder if (errno == EWOULDBLOCK ||
2360728d4185c0c04279c999941c64d36626af79Christian Maeder errno == EINTR)
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder goto out;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder goto err;
00df6fd583c19393fa141d5a0e21ac74c7bf5b19Christian Maeder }
2360728d4185c0c04279c999941c64d36626af79Christian Maeder } else
2360728d4185c0c04279c999941c64d36626af79Christian Maeder n = 0;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder break;
96ae1a1d2197d0e0d5b80da2474b64c456feb1b0Christian Maeder
2360728d4185c0c04279c999941c64d36626af79Christian Maeder default:
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder goto err;
8d780c893d6df5dab3dcc7d8444b7517f6547f11Christian Maeder }
2360728d4185c0c04279c999941c64d36626af79Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder if ((size_t)n != sz_to_recv)
dff1de7ad15d1582e25d636c3724dd202874897fChristian Maeder source->sources.usocket.sz_to_recv -= n;
2360728d4185c0c04279c999941c64d36626af79Christian Maeder else
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder source->sources.usocket.status =
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder isc_usocketsource_connected;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder if (n == 0)
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder goto out;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder entropypool_adddata(ent, buf, n, n * 8);
bc263f610d20a9cd3014ddfca903026127fa0d48Christian Maeder added += n * 8;
966519955f5f7111abac20118563132b9dd41165Christian Maeder desired -= n;
bbba6dd86153aacb0f662b182b128df0eb09fd54Christian Maeder }
5a448e9be8c4482a978b174b744237757335140fChristian Maeder goto out;
d96bfd1d7a4595bfff87771b91797330fa939455Christian Maeder
8c8545dd3bf34fbcbc16904b65d249658f8f9efcChristian Maeder err:
d27b1887e61f1dc53d77c37f59dbf5019242a686Christian Maeder close(fd);
34d14197eb3dd643a8e6ef3ed8cba5629528e97fAivaras Jakubauskas source->bad = ISC_TRUE;
d4ebd9e5adc974cfa2bdf4bdd155e07be0e26f75Christian Maeder source->sources.usocket.status = isc_usocketsource_disconnected;
d4ebd9e5adc974cfa2bdf4bdd155e07be0e26f75Christian Maeder source->sources.usocket.handle = -1;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder out:
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder return (added);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder}
bbba6dd86153aacb0f662b182b128df0eb09fd54Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder/*
0b13f102310e03a20b38c870b5acb88712f316a4Christian Maeder * Poll each source, trying to get data from it to stuff into the entropy
dff1de7ad15d1582e25d636c3724dd202874897fChristian Maeder * pool.
0b13f102310e03a20b38c870b5acb88712f316a4Christian Maeder */
0b13f102310e03a20b38c870b5acb88712f316a4Christian Maederstatic void
dff1de7ad15d1582e25d636c3724dd202874897fChristian Maederfillpool(isc_entropy_t *ent, unsigned int desired, isc_boolean_t blocking) {
0b13f102310e03a20b38c870b5acb88712f316a4Christian Maeder unsigned int added;
cb2044812811d66efe038d914966e04290be93faChristian Maeder unsigned int remaining;
0b13f102310e03a20b38c870b5acb88712f316a4Christian Maeder unsigned int needed;
96ae1a1d2197d0e0d5b80da2474b64c456feb1b0Christian Maeder unsigned int nsource;
0b13f102310e03a20b38c870b5acb88712f316a4Christian Maeder isc_entropysource_t *source;
0b13f102310e03a20b38c870b5acb88712f316a4Christian Maeder
96ae1a1d2197d0e0d5b80da2474b64c456feb1b0Christian Maeder REQUIRE(VALID_ENTROPY(ent));
96ae1a1d2197d0e0d5b80da2474b64c456feb1b0Christian Maeder
0b13f102310e03a20b38c870b5acb88712f316a4Christian Maeder needed = desired;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder /*
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder * This logic is a little strange, so an explanation is in order.
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder *
96ae1a1d2197d0e0d5b80da2474b64c456feb1b0Christian Maeder * If needed is 0, it means we are being asked to "fill to whatever
8c8545dd3bf34fbcbc16904b65d249658f8f9efcChristian Maeder * we think is best." This means that if we have at least a
33fcc19ef2b59493b4e91eebf701df95fd230765Christian Maeder * partially full pool (say, > 1/4th of the pool) we probably don't
d4ebd9e5adc974cfa2bdf4bdd155e07be0e26f75Christian Maeder * need to add anything.
0b13f102310e03a20b38c870b5acb88712f316a4Christian Maeder *
0b13f102310e03a20b38c870b5acb88712f316a4Christian Maeder * Also, we will check to see if the "pseudo" count is too high.
0b13f102310e03a20b38c870b5acb88712f316a4Christian Maeder * If it is, try to mix in better data. Too high is currently
0b13f102310e03a20b38c870b5acb88712f316a4Christian Maeder * defined as 1/4th of the pool.
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder *
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder * Next, if we are asked to add a specific bit of entropy, make
8bb80c9684e905de8dcfcfb1291542677e7d77b6Christian Maeder * certain that we will do so. Clamp how much we try to add to
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder * (DIGEST_SIZE * 8 < needed < POOLBITS - entropy).
bc263f610d20a9cd3014ddfca903026127fa0d48Christian Maeder *
966519955f5f7111abac20118563132b9dd41165Christian Maeder * Note that if we are in a blocking mode, we will only try to
dff1de7ad15d1582e25d636c3724dd202874897fChristian Maeder * get as much data as we need, not as much as we might want
8bb80c9684e905de8dcfcfb1291542677e7d77b6Christian Maeder * to build up.
00df6fd583c19393fa141d5a0e21ac74c7bf5b19Christian Maeder */
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder if (needed == 0) {
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder REQUIRE(!blocking);
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder if ((ent->pool.entropy >= RND_POOLBITS / 4)
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder && (ent->pool.pseudo <= RND_POOLBITS / 4))
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder return;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder needed = THRESHOLD_BITS * 4;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder } else {
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder needed = ISC_MAX(needed, THRESHOLD_BITS);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder needed = ISC_MIN(needed, RND_POOLBITS);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder }
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
bc263f610d20a9cd3014ddfca903026127fa0d48Christian Maeder /*
966519955f5f7111abac20118563132b9dd41165Christian Maeder * In any case, clamp how much we need to how much we can add.
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder */
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder needed = ISC_MIN(needed, RND_POOLBITS - ent->pool.entropy);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder /*
dff1de7ad15d1582e25d636c3724dd202874897fChristian Maeder * But wait! If we're not yet initialized, we need at least
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder * THRESHOLD_BITS
cb2044812811d66efe038d914966e04290be93faChristian Maeder * of randomness.
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder */
8d780c893d6df5dab3dcc7d8444b7517f6547f11Christian Maeder if (ent->initialized < THRESHOLD_BITS)
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder needed = ISC_MAX(needed, THRESHOLD_BITS - ent->initialized);
96ae1a1d2197d0e0d5b80da2474b64c456feb1b0Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder /*
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder * Poll each file source to see if we can read anything useful from
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder * it. XXXMLG When where are multiple sources, we should keep a
00df6fd583c19393fa141d5a0e21ac74c7bf5b19Christian Maeder * record of which one we last used so we can start from it (or the
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder * next one) to avoid letting some sources build up entropy while
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder * others are always drained.
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder */
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
bbba6dd86153aacb0f662b182b128df0eb09fd54Christian Maeder added = 0;
16b71dad8d398af412d66a4f4763f1ada5b03d23Christian Maeder remaining = needed;
8c8545dd3bf34fbcbc16904b65d249658f8f9efcChristian Maeder if (ent->nextsource == NULL) {
33fcc19ef2b59493b4e91eebf701df95fd230765Christian Maeder ent->nextsource = ISC_LIST_HEAD(ent->sources);
d27b1887e61f1dc53d77c37f59dbf5019242a686Christian Maeder if (ent->nextsource == NULL)
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder return;
34d14197eb3dd643a8e6ef3ed8cba5629528e97fAivaras Jakubauskas }
d4ebd9e5adc974cfa2bdf4bdd155e07be0e26f75Christian Maeder source = ent->nextsource;
0b13f102310e03a20b38c870b5acb88712f316a4Christian Maeder again_file:
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder for (nsource = 0; nsource < ent->nsources; nsource++) {
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder unsigned int got;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
f39b8dd9651dfcc38b06191cda23cacbfc298323Christian Maeder if (remaining == 0)
12aef5992d3af07dee81a4e02cf4be65a83f28bcChristian Maeder break;
2360728d4185c0c04279c999941c64d36626af79Christian Maeder
2360728d4185c0c04279c999941c64d36626af79Christian Maeder got = 0;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
f39b8dd9651dfcc38b06191cda23cacbfc298323Christian Maeder switch ( source->type ) {
2360728d4185c0c04279c999941c64d36626af79Christian Maeder case ENTROPY_SOURCETYPE_FILE:
2360728d4185c0c04279c999941c64d36626af79Christian Maeder got = get_from_filesource(source, remaining);
0130083f314580170af1195037be3325f125fbceChristian Maeder break;
d81905a5b924415c524d702df26204683c82c12eChristian Maeder
96ae1a1d2197d0e0d5b80da2474b64c456feb1b0Christian Maeder case ENTROPY_SOURCETYPE_USOCKET:
2360728d4185c0c04279c999941c64d36626af79Christian Maeder got = get_from_usocketsource(source, remaining);
f39b8dd9651dfcc38b06191cda23cacbfc298323Christian Maeder break;
8d780c893d6df5dab3dcc7d8444b7517f6547f11Christian Maeder }
2360728d4185c0c04279c999941c64d36626af79Christian Maeder
bc263f610d20a9cd3014ddfca903026127fa0d48Christian Maeder added += got;
966519955f5f7111abac20118563132b9dd41165Christian Maeder
2360728d4185c0c04279c999941c64d36626af79Christian Maeder remaining -= ISC_MIN(remaining, got);
2360728d4185c0c04279c999941c64d36626af79Christian Maeder
00df6fd583c19393fa141d5a0e21ac74c7bf5b19Christian Maeder source = ISC_LIST_NEXT(source, link);
2360728d4185c0c04279c999941c64d36626af79Christian Maeder if (source == NULL)
f39b8dd9651dfcc38b06191cda23cacbfc298323Christian Maeder source = ISC_LIST_HEAD(ent->sources);
dff1de7ad15d1582e25d636c3724dd202874897fChristian Maeder }
2360728d4185c0c04279c999941c64d36626af79Christian Maeder ent->nextsource = source;
2360728d4185c0c04279c999941c64d36626af79Christian Maeder
2360728d4185c0c04279c999941c64d36626af79Christian Maeder if (blocking && remaining != 0) {
2360728d4185c0c04279c999941c64d36626af79Christian Maeder int fds;
2360728d4185c0c04279c999941c64d36626af79Christian Maeder
d27b1887e61f1dc53d77c37f59dbf5019242a686Christian Maeder fds = wait_for_sources(ent);
8994ef587ce7c7c39ddd20f0f7e4575838a6694aChristian Maeder if (fds > 0)
33fcc19ef2b59493b4e91eebf701df95fd230765Christian Maeder goto again_file;
0b13f102310e03a20b38c870b5acb88712f316a4Christian Maeder }
0b13f102310e03a20b38c870b5acb88712f316a4Christian Maeder
0b13f102310e03a20b38c870b5acb88712f316a4Christian Maeder /*
2360728d4185c0c04279c999941c64d36626af79Christian Maeder * Here, if there are bits remaining to be had and we can block,
2360728d4185c0c04279c999941c64d36626af79Christian Maeder * check to see if we have a callback source. If so, call them.
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder */
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder source = ISC_LIST_HEAD(ent->sources);
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder while ((remaining != 0) && (source != NULL)) {
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder unsigned int got;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder got = 0;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
dff1de7ad15d1582e25d636c3724dd202874897fChristian Maeder if (source->type == ENTROPY_SOURCETYPE_CALLBACK)
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder got = get_from_callback(source, remaining, blocking);
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder added += got;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder remaining -= ISC_MIN(remaining, got);
d56ece59c372cb887355825901222b9f3377f7e6Thiemo Wiedemeyer
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder if (added >= needed)
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder break;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder source = ISC_LIST_NEXT(source, link);
2360728d4185c0c04279c999941c64d36626af79Christian Maeder }
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder /*
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder * Mark as initialized if we've added enough data.
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder */
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder if (ent->initialized < THRESHOLD_BITS)
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder ent->initialized += added;
34746b7edb13c8b0fe36066b410ed4e7695b7649Christian Maeder}
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
12324a24aa5aa42edc749c7473fcf5264d4a81e4Christian Maederstatic int
3753288339ad80053053d92409bd37b335a96197Christian Maederwait_for_sources(isc_entropy_t *ent) {
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder isc_entropysource_t *source;
76d027be764e2ff61bef959efb3ac8f56499e646Christian Maeder int maxfd, fd;
9f85afecbd79b3df5a0bb17bd28cd0b288dc3213Kristina Sojakova int cc;
a166da43d4e8f9dfa7a2651d033c6bea02627ca6Mihai Codescu fd_set reads;
22b772f8753f0cdb4508ba460356c238de2ee375Jonathan von Schroeder fd_set writes;
7bbfb15142ab4286dfc6fcde2fc94a5512297e41Jonathan von Schroeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder maxfd = -1;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder FD_ZERO(&reads);
63da71bfb4226f504944b293fb77177ebcaea7d4Ewaryst Schulz FD_ZERO(&writes);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder source = ISC_LIST_HEAD(ent->sources);
af6e92e4a9ca308f928f9909acee115f801c5db5Ewaryst Schulz while (source != NULL) {
b47b1ea8a412f6e4c731779f6a572384e7cf06d8Christian Maeder if (source->type == ENTROPY_SOURCETYPE_FILE) {
26b1c101b72100b69045effdfaab3889de6c8c93Christian Maeder fd = source->sources.file.handle;
c4076ff1721f8901a30e4b7aa004479ecb2631e0Felix Gabriel Mance if (fd >= 0) {
a68ff26ddb1d300f7e16097edef615f130fcd5ceChristian Maeder maxfd = ISC_MAX(maxfd, fd);
9f226cec9f978edaba67aee4c4e04e3d3b994b87Daniel Calegari FD_SET(fd, &reads);
f730570f7c284b252ad2e24cf23cc594021f9e25Jonathan von Schroeder }
897a04683fb30873e84dc3360dea770a4435971cChristian Maeder }
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder if (source->type == ENTROPY_SOURCETYPE_USOCKET) {
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder fd = source->sources.usocket.handle;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder if (fd >= 0) {
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder switch (source->sources.usocket.status) {
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder case isc_usocketsource_disconnected:
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder break;
34746b7edb13c8b0fe36066b410ed4e7695b7649Christian Maeder case isc_usocketsource_connecting:
12324a24aa5aa42edc749c7473fcf5264d4a81e4Christian Maeder case isc_usocketsource_connected:
2360728d4185c0c04279c999941c64d36626af79Christian Maeder case isc_usocketsource_ndesired:
3753288339ad80053053d92409bd37b335a96197Christian Maeder maxfd = ISC_MAX(maxfd, fd);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder FD_SET(fd, &writes);
63da71bfb4226f504944b293fb77177ebcaea7d4Ewaryst Schulz break;
76d027be764e2ff61bef959efb3ac8f56499e646Christian Maeder case isc_usocketsource_wrote:
9f85afecbd79b3df5a0bb17bd28cd0b288dc3213Kristina Sojakova case isc_usocketsource_reading:
a166da43d4e8f9dfa7a2651d033c6bea02627ca6Mihai Codescu maxfd = ISC_MAX(maxfd, fd);
22b772f8753f0cdb4508ba460356c238de2ee375Jonathan von Schroeder FD_SET(fd, &reads);
7bbfb15142ab4286dfc6fcde2fc94a5512297e41Jonathan von Schroeder break;
f730570f7c284b252ad2e24cf23cc594021f9e25Jonathan von Schroeder }
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder }
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder }
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder source = ISC_LIST_NEXT(source, link);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder }
af6e92e4a9ca308f928f9909acee115f801c5db5Ewaryst Schulz
b47b1ea8a412f6e4c731779f6a572384e7cf06d8Christian Maeder if (maxfd < 0)
26b1c101b72100b69045effdfaab3889de6c8c93Christian Maeder return (-1);
c4076ff1721f8901a30e4b7aa004479ecb2631e0Felix Gabriel Mance
a68ff26ddb1d300f7e16097edef615f130fcd5ceChristian Maeder cc = select(maxfd + 1, &reads, &writes, NULL, NULL);
9f226cec9f978edaba67aee4c4e04e3d3b994b87Daniel Calegari if (cc < 0)
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder return (-1);
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
2353f65833a3da763392f771223250cd50b8d873Christian Maeder return (cc);
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder}
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maederstatic void
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maederdestroyfilesource(isc_entropyfilesource_t *source) {
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder (void)close(source->handle);
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder}
897a04683fb30873e84dc3360dea770a4435971cChristian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maederstatic void
b53688bfed888214b485cf76439d57262d80e0a7Christian Maederdestroyusocketsource(isc_entropyusocketsource_t *source) {
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder close(source->handle);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder}
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder/*
12324a24aa5aa42edc749c7473fcf5264d4a81e4Christian Maeder * Make a fd non-blocking
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder */
12aef5992d3af07dee81a4e02cf4be65a83f28bcChristian Maederstatic isc_result_t
12324a24aa5aa42edc749c7473fcf5264d4a81e4Christian Maedermake_nonblock(int fd) {
3753288339ad80053053d92409bd37b335a96197Christian Maeder int ret;
7bbfb15142ab4286dfc6fcde2fc94a5512297e41Jonathan von Schroeder int flags;
b47b1ea8a412f6e4c731779f6a572384e7cf06d8Christian Maeder char strbuf[ISC_STRERRORSIZE];
f730570f7c284b252ad2e24cf23cc594021f9e25Jonathan von Schroeder#ifdef USE_FIONBIO_IOCTL
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder int on = 1;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
818b228955ef40dd5a253bd942dd6ab8779ed713Christian Maeder ret = ioctl(fd, FIONBIO, (char *)&on);
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder#else
7ebcceae3d34771cae3bbb8c8060bef0b894376eChristian Maeder flags = fcntl(fd, F_GETFL, 0);
8a5c05062ef501bf725a86a370a5145a198e81fdKlaus Luettich flags |= PORT_NONBLOCK;
8a5c05062ef501bf725a86a370a5145a198e81fdKlaus Luettich ret = fcntl(fd, F_SETFL, flags);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder#endif
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
2360728d4185c0c04279c999941c64d36626af79Christian Maeder if (ret == -1) {
8a5c05062ef501bf725a86a370a5145a198e81fdKlaus Luettich isc__strerror(errno, strbuf, sizeof(strbuf));
8a5c05062ef501bf725a86a370a5145a198e81fdKlaus Luettich UNEXPECTED_ERROR(__FILE__, __LINE__,
7ebcceae3d34771cae3bbb8c8060bef0b894376eChristian Maeder#ifdef USE_FIONBIO_IOCTL
8a5c05062ef501bf725a86a370a5145a198e81fdKlaus Luettich "ioctl(%d, FIONBIO, &on): %s", fd,
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder#else
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder "fcntl(%d, F_SETFL, %d): %s", fd, flags,
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder#endif
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder strbuf);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder return (ISC_R_UNEXPECTED);
59aa5703ac7f3b99e97cd5926e77088b256c5f40Christian Maeder }
3ec3a22fe2b9c38a3575c98a82b4e3f988af64a6Eugen Kuksa
4c872eeb600fe8479dbda395405cf13c3d573c24Soeren D. Schulze return (ISC_R_SUCCESS);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder}
bc263f610d20a9cd3014ddfca903026127fa0d48Christian Maeder
f8cc2399c16fcda7e3bf9d901a0de0cc8a455f86Ewaryst Schulzisc_result_t
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maederisc_entropy_createfilesource(isc_entropy_t *ent, const char *fname) {
53a3042e1da2253fd3f103bfef4deb47fc0bf6a6Ewaryst Schulz int fd;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder struct stat _stat;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder isc_boolean_t is_usocket = ISC_FALSE;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder isc_boolean_t is_connected = ISC_FALSE;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder isc_result_t ret;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder isc_entropysource_t *source;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
c4076ff1721f8901a30e4b7aa004479ecb2631e0Felix Gabriel Mance REQUIRE(VALID_ENTROPY(ent));
c30231257d9116b514dce02703a515fe21cd427dTill Mossakowski REQUIRE(fname != NULL);
427ff3172ae2dfebe3c8fc972735158999997e8aChristian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder LOCK(&ent->lock);
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder if (stat(fname, &_stat) < 0) {
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder ret = isc__errno2result(errno);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder goto errout;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder }
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder /*
df86c42574168135e8e2af9cf468fae774874cd0Christian Maeder * Solaris 2.5.1 does not have support for sockets (S_IFSOCK),
3ec3a22fe2b9c38a3575c98a82b4e3f988af64a6Eugen Kuksa * but it does return type S_IFIFO (the OS believes that
4c872eeb600fe8479dbda395405cf13c3d573c24Soeren D. Schulze * the socket is a fifo). This may be an issue if we tell
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder * the program to look at an actual FIFO as its source of
bc263f610d20a9cd3014ddfca903026127fa0d48Christian Maeder * entropy.
f8cc2399c16fcda7e3bf9d901a0de0cc8a455f86Ewaryst Schulz */
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder#if defined(S_ISSOCK)
53a3042e1da2253fd3f103bfef4deb47fc0bf6a6Ewaryst Schulz if (S_ISSOCK(_stat.st_mode))
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder is_usocket = ISC_TRUE;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder#endif
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder#if defined(S_ISFIFO) && defined(sun)
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder if (S_ISFIFO(_stat.st_mode))
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder is_usocket = ISC_TRUE;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder#endif
c4076ff1721f8901a30e4b7aa004479ecb2631e0Felix Gabriel Mance if (is_usocket)
c30231257d9116b514dce02703a515fe21cd427dTill Mossakowski fd = socket(PF_UNIX, SOCK_STREAM, 0);
427ff3172ae2dfebe3c8fc972735158999997e8aChristian Maeder else
3490b73f69b58ab742417b0867d0e2d4a7778cc0Christian Maeder fd = open(fname, O_RDONLY | PORT_NONBLOCK, 0);
3490b73f69b58ab742417b0867d0e2d4a7778cc0Christian Maeder
59aa5703ac7f3b99e97cd5926e77088b256c5f40Christian Maeder if (fd < 0) {
4c872eeb600fe8479dbda395405cf13c3d573c24Soeren D. Schulze ret = isc__errno2result(errno);
427ff3172ae2dfebe3c8fc972735158999997e8aChristian Maeder goto errout;
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder }
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder
7968d3a131e5a684ec1ff0c6d88aae638549153dChristian Maeder ret = make_nonblock(fd);
3490b73f69b58ab742417b0867d0e2d4a7778cc0Christian Maeder if (ret != ISC_R_SUCCESS)
78c294da55788b25e175180168371c9536a6d440Christian Maeder goto closefd;
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder if (is_usocket) {
8a5c05062ef501bf725a86a370a5145a198e81fdKlaus Luettich struct sockaddr_un sname;
b76d27eba526ecac2a20400fa505ec5c642ae7d2Dominik Luecke
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder memset(&sname, 0, sizeof(sname));
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder sname.sun_family = AF_UNIX;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder strlcpy(sname.sun_path, fname, sizeof(sname.sun_path));
2360728d4185c0c04279c999941c64d36626af79Christian Maeder#ifdef ISC_PLATFORM_HAVESALEN
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder#if !defined(SUN_LEN)
7968d3a131e5a684ec1ff0c6d88aae638549153dChristian Maeder#define SUN_LEN(su) \
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
beff4152e9f0fe90885458d1a1733b183a2a8816Christian Maeder#endif
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder sname.sun_len = SUN_LEN(&sname);
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder#endif
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder if (connect(fd, (struct sockaddr *) &sname,
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder sizeof(struct sockaddr_un)) < 0) {
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder if (errno != EINPROGRESS) {
78c294da55788b25e175180168371c9536a6d440Christian Maeder ret = isc__errno2result(errno);
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder goto closefd;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder }
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder } else
78c294da55788b25e175180168371c9536a6d440Christian Maeder is_connected = ISC_TRUE;
78c294da55788b25e175180168371c9536a6d440Christian Maeder }
bc263f610d20a9cd3014ddfca903026127fa0d48Christian Maeder
511284753313165e629cedf508752d6818ccc4d2Christian Maeder source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t));
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder if (source == NULL) {
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder ret = ISC_R_NOMEMORY;
78c294da55788b25e175180168371c9536a6d440Christian Maeder goto closefd;
78c294da55788b25e175180168371c9536a6d440Christian Maeder }
78c294da55788b25e175180168371c9536a6d440Christian Maeder
78c294da55788b25e175180168371c9536a6d440Christian Maeder /*
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder * From here down, no failures can occur.
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder */
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder source->magic = SOURCE_MAGIC;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder source->ent = ent;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder source->total = 0;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder source->bad = ISC_FALSE;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder memset(source->name, 0, sizeof(source->name));
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder ISC_LINK_INIT(source, link);
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder if (is_usocket) {
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder source->sources.usocket.handle = fd;
8865728716566f42fa73e7e0bc080ba3225df764Christian Maeder if (is_connected)
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder source->sources.usocket.status =
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder isc_usocketsource_connected;
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder else
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder source->sources.usocket.status =
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder isc_usocketsource_connecting;
dff1de7ad15d1582e25d636c3724dd202874897fChristian Maeder source->sources.usocket.sz_to_recv = 0;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder source->type = ENTROPY_SOURCETYPE_USOCKET;
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder } else {
a3a7d8b3cdf05c8040c62dbcf9a15dc5042cd721Christian Maeder source->sources.file.handle = fd;
8bb80c9684e905de8dcfcfb1291542677e7d77b6Christian Maeder source->type = ENTROPY_SOURCETYPE_FILE;
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder }
91ba5d95b2472cb075646b6120a559dc6581a867Christian Maeder
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder /*
91ba5d95b2472cb075646b6120a559dc6581a867Christian Maeder * Hook it into the entropy system.
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder */
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder ISC_LIST_APPEND(ent->sources, source, link);
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder ent->nsources++;
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder UNLOCK(&ent->lock);
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder return (ISC_R_SUCCESS);
91ba5d95b2472cb075646b6120a559dc6581a867Christian Maeder
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder closefd:
91ba5d95b2472cb075646b6120a559dc6581a867Christian Maeder (void)close(fd);
b6ff72be73dad3d1394cf2c71e29e67624ff030bChristian Maeder
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder errout:
f03420e44d8204b2945edaab5c70a84e7c381892Christian Maeder UNLOCK(&ent->lock);
be43c3fa0292555bd126784ae27ff5c1d23438cbChristian Maeder
91ba5d95b2472cb075646b6120a559dc6581a867Christian Maeder return (ret);
dff1de7ad15d1582e25d636c3724dd202874897fChristian Maeder}
b53688bfed888214b485cf76439d57262d80e0a7Christian Maeder