1 /* rndegd.c - interface to the EGD
2 * Copyright (C) 1999, 2000, 2002, 2003, 2010 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 2.1 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
17 * License along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
29 #include <sys/types.h>
30 #include <sys/socket.h>
34 #include <gnutls_errors.h>
37 #define offsetof(type, member) ((size_t) &((type *)0)->member)
40 static int egd_socket
= -1;
43 do_write (int fd
, void *buf
, size_t nbytes
)
45 size_t nleft
= nbytes
;
50 nwritten
= write (fd
, buf
, nleft
);
58 buf
= (char *) buf
+ nwritten
;
64 do_read (int fd
, void *buf
, size_t nbytes
)
72 n
= read (fd
, (char *) buf
+ nread
, nbytes
);
74 while (n
== -1 && errno
== EINTR
);
76 return nread
? nread
: -1;
82 while (nread
< nbytes
);
86 static const char *egd_names
[] = {
104 if (stat (egd_names
[i
], &st
) != 0)
107 if (st
.st_mode
& S_IFSOCK
)
113 while (egd_names
[++i
] != NULL
);
118 /* Connect to the EGD and return the file descriptor. Return -1 on
119 error. With NOFAIL set to true, silently fail and return the
120 error, otherwise print an error message and die. */
122 _rndegd_connect_socket (void)
126 struct sockaddr_un addr
;
129 if (egd_socket
!= -1)
135 name
= find_egd_name ();
137 if (strlen (name
) + 1 >= sizeof addr
.sun_path
)
139 _gnutls_debug_log ("EGD socketname is too long\n");
143 memset (&addr
, 0, sizeof addr
);
144 addr
.sun_family
= AF_LOCAL
;
145 strcpy (addr
.sun_path
, name
);
146 addr_len
= (offsetof (struct sockaddr_un
, sun_path
)
147 + strlen (addr
.sun_path
));
149 fd
= socket (AF_LOCAL
, SOCK_STREAM
, 0);
152 _gnutls_debug_log ("can't create unix domain socket: %s\n",
156 else if (connect (fd
, (struct sockaddr
*) &addr
, addr_len
) == -1)
158 _gnutls_debug_log ("can't connect to EGD socket `%s': %s\n",
159 name
, strerror (errno
));
170 * Note: We always use the highest level.
171 * To boost the performance we may want to add some
172 * additional code for level 1
174 * Using a level of 0 should never block and better add nothing
175 * to the pool. So this is just a dummy for EGD.
178 _rndegd_read (int *fd
, void *_output
, size_t _length
)
181 uint8_t buffer
[256 + 2];
184 unsigned char *output
= _output
;
185 size_t length
= _length
;
192 if (*fd
== -1 || do_restart
)
193 *fd
= _rndegd_connect_socket ();
197 nbytes
= length
< 255 ? length
: 255;
198 /* First time we do it with a non blocking request */
199 buffer
[0] = 1; /* non blocking */
202 if (do_write (*fd
, buffer
, 2) == -1)
203 _gnutls_debug_log ("can't write to the EGD: %s\n", strerror (errno
));
205 n
= do_read (*fd
, buffer
, 1);
208 _gnutls_debug_log ("read error on EGD: %s\n", strerror (errno
));
216 n
= do_read (*fd
, buffer
, n
);
219 _gnutls_debug_log ("read error on EGD: %s\n", strerror (errno
));
226 _gnutls_debug_log ("read error on EGD: returned more bytes!\n");
230 memcpy (output
, buffer
, n
);
237 nbytes
= length
< 255 ? length
: 255;
239 buffer
[0] = 2; /* blocking */
241 if (do_write (*fd
, buffer
, 2) == -1)
242 _gnutls_debug_log ("can't write to the EGD: %s\n", strerror (errno
));
243 n
= do_read (*fd
, buffer
, nbytes
);
246 _gnutls_debug_log ("read error on EGD: %s\n", strerror (errno
));
253 _gnutls_debug_log ("read error on EGD: returned more bytes!\n");
257 memcpy (output
, buffer
, n
);
262 return _length
; /* success */