1 /* rndegd.c - interface to the EGD
2 * Copyright (C) 1999-2012 Free Software Foundation, Inc.
4 * This file is part of Libgcrypt.
6 * Libgcrypt is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as
8 * published by the Free Software Foundation; either version 3 of
9 * the License, or (at your option) any later version.
11 * Libgcrypt is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>
32 #include <sys/types.h>
33 #include <sys/socket.h>
36 #include <gnutls_int.h>
37 #include <gnutls_str.h>
38 #include <gnutls_errors.h>
41 # define LOCAL_SOCKET_TYPE AF_UNIX
43 # define LOCAL_SOCKET_TYPE AF_LOCAL
47 #define offsetof(type, member) ((size_t) &((type *)0)->member)
50 static int egd_socket
= -1;
53 do_write (int fd
, void *buf
, size_t nbytes
)
55 size_t nleft
= nbytes
;
60 nwritten
= write (fd
, buf
, nleft
);
68 buf
= (char *) buf
+ nwritten
;
74 do_read (int fd
, void *buf
, size_t nbytes
)
83 n
= read (fd
, (char *) buf
+ nread
, nbytes
);
85 while (n
== -1 && errno
== EINTR
);
97 while (nread
< nbytes
);
101 static const char *egd_names
[] = {
119 if (stat (egd_names
[i
], &st
) != 0)
122 if (st
.st_mode
& S_IFSOCK
)
128 while (egd_names
[++i
] != NULL
);
133 /* Connect to the EGD and return the file descriptor. Return -1 on
134 error. With NOFAIL set to true, silently fail and return the
135 error, otherwise print an error message and die. */
137 _rndegd_connect_socket (void)
141 struct sockaddr_un addr
;
144 if (egd_socket
!= -1)
150 name
= find_egd_name ();
152 if (strlen (name
) + 1 >= sizeof addr
.sun_path
)
154 _gnutls_debug_log ("EGD socketname is too long\n");
158 memset (&addr
, 0, sizeof addr
);
159 addr
.sun_family
= LOCAL_SOCKET_TYPE
;
160 _gnutls_str_cpy (addr
.sun_path
, sizeof(addr
.sun_path
), name
);
161 addr_len
= (offsetof (struct sockaddr_un
, sun_path
)
162 + strlen (addr
.sun_path
));
164 fd
= socket (LOCAL_SOCKET_TYPE
, SOCK_STREAM
, 0);
167 _gnutls_debug_log ("can't create unix domain socket: %s\n",
171 else if (connect (fd
, (struct sockaddr
*) &addr
, addr_len
) == -1)
173 _gnutls_debug_log ("can't connect to EGD socket `%s': %s\n",
174 name
, strerror (errno
));
185 * Note: We always use the highest level.
186 * To boost the performance we may want to add some
187 * additional code for level 1
189 * Using a level of 0 should never block and better add nothing
190 * to the pool. So this is just a dummy for EGD.
193 _rndegd_read (int *fd
, void *_output
, size_t _length
)
196 uint8_t buffer
[256 + 2];
199 unsigned char *output
= _output
;
200 ssize_t length
= (ssize_t
)_length
;
206 if (*fd
== -1 || do_restart
)
207 *fd
= _rndegd_connect_socket ();
211 nbytes
= length
< 255 ? length
: 255;
212 /* First time we do it with a non blocking request */
213 buffer
[0] = 1; /* non blocking */
216 if (do_write (*fd
, buffer
, 2) == -1)
217 _gnutls_debug_log ("can't write to the EGD: %s\n", strerror (errno
));
219 n
= do_read (*fd
, buffer
, 1);
222 _gnutls_debug_log ("read error on EGD: %s\n", strerror (errno
));
230 n
= do_read (*fd
, buffer
, n
);
233 _gnutls_debug_log ("read error on EGD: %s\n", strerror (errno
));
240 _gnutls_debug_log ("read error on EGD: returned more bytes!\n");
244 memcpy (output
, buffer
, n
);
251 nbytes
= length
< 255 ? length
: 255;
253 buffer
[0] = 2; /* blocking */
255 if (do_write (*fd
, buffer
, 2) == -1)
256 _gnutls_debug_log ("can't write to the EGD: %s\n", strerror (errno
));
257 n
= do_read (*fd
, buffer
, nbytes
);
260 _gnutls_debug_log ("read error on EGD: %s\n", strerror (errno
));
267 _gnutls_debug_log ("read error on EGD: returned more bytes!\n");
271 memcpy (output
, buffer
, n
);
276 return _length
; /* success */