ReactOS 0.4.15-dev-7788-g1ad9096
auth_time.c
Go to the documentation of this file.
1/*
2 * auth_time.c
3 *
4 * This module contains the private function __rpc_get_time_offset()
5 * which will return the difference in seconds between the local system's
6 * notion of time and a remote server's notion of time. This must be
7 * possible without calling any functions that may invoke the name
8 * service. (netdir_getbyxxx, getXbyY, etc). The function is used in the
9 * synchronize call of the authdes code to synchronize clocks between
10 * NIS+ clients and their servers.
11 *
12 * Note to minimize the amount of duplicate code, portions of the
13 * synchronize() function were folded into this code, and the synchronize
14 * call becomes simply a wrapper around this function. Further, if this
15 * function is called with a timehost it *DOES* recurse to the name
16 * server so don't use it in that mode if you are doing name service code.
17 *
18 * Copyright (c) 1992 Sun Microsystems Inc.
19 * All rights reserved.
20 *
21 * Side effects :
22 * When called a client handle to a RPCBIND process is created
23 * and destroyed. Two strings "netid" and "uaddr" are malloc'd
24 * and returned. The SIGALRM processing is modified only if
25 * needed to deal with TCP connections.
26 */
27
28//#include <sys/cdefs.h>
29#include <wintirpc.h>
30//#include <syslog.h>
31#include <string.h>
32#include <stdlib.h>
33//#include <unistd.h>
34//#include <netdb.h>
35//#include <sys/signal.h>
36#include <errno.h>
37//#include <sys/socket.h>
38//#include <netinet/in.h>
39//#include <arpa/inet.h>
40
41#include <rpc/rpc.h>
42#include <rpc/rpc_com.h>
43#include <rpc/rpcb_prot.h>
44//#include <clnt_soc.h>
45//#include <sys/select.h>
46#undef NIS
47#include <rpcsvc/nis.h>
48
49
50#ifdef TESTING
51#define msg(x) printf("ERROR: %s\n", x)
52/* #define msg(x) syslog(LOG_ERR, "%s", x) */
53#else
54#define msg(x)
55#endif
56
57static int saw_alarm = 0;
58
59static void
61 int s;
62{
63 saw_alarm = 1;
64 return;
65}
66
67/*
68 * The internet time server defines the epoch to be Jan 1, 1900
69 * whereas UNIX defines it to be Jan 1, 1970. To adjust the result
70 * from internet time-service time, into UNIX time we subtract the
71 * following offset :
72 */
73#define NYEARS (1970 - 1900)
74#define TOFFSET ((u_long)60*60*24*(365*NYEARS + (NYEARS/4)))
75
76
77/*
78 * Stolen from rpc.nisd:
79 * Turn a 'universal address' into a struct sockaddr_in.
80 * Bletch.
81 */
82static int uaddr_to_sockaddr(uaddr, sin)
83#ifdef foo
84 endpoint *endpt;
85#endif
86 char *uaddr;
87 struct sockaddr_in *sin;
88{
89 unsigned char p_bytes[2];
90 int i;
91 unsigned long a[6];
92
93 i = sscanf(uaddr, "%lu.%lu.%lu.%lu.%lu.%lu", &a[0], &a[1], &a[2],
94 &a[3], &a[4], &a[5]);
95
96 if (i < 6)
97 return(1);
98
99 for (i = 0; i < 4; i++)
100 sin->sin_addr.s_addr |= (a[i] & 0x000000FF) << (8 * i);
101
102 p_bytes[0] = (unsigned char)a[4] & 0x000000FF;
103 p_bytes[1] = (unsigned char)a[5] & 0x000000FF;
104
105 sin->sin_family = AF_INET; /* always */
106 bcopy((char *)&p_bytes, (char *)&sin->sin_port, 2);
107
108 return (0);
109}
110
111/*
112 * free_eps()
113 *
114 * Free the strings that were strduped into the eps structure.
115 */
116static void
118 endpoint eps[];
119 int num;
120{
121 int i;
122
123 for (i = 0; i < num; i++) {
124 free(eps[i].uaddr);
125 free(eps[i].proto);
126 free(eps[i].family);
127 }
128 return;
129}
130
131/*
132 * get_server()
133 *
134 * This function constructs a nis_server structure description for the
135 * indicated hostname.
136 *
137 * NOTE: There is a chance we may end up recursing here due to the
138 * fact that gethostbyname() could do an NIS search. Ideally, the
139 * NIS+ server will call __rpc_get_time_offset() with the nis_server
140 * structure already populated.
141 */
142static nis_server *
143get_server(sin, host, srv, eps, maxep)
144 struct sockaddr_in *sin;
145 char *host; /* name of the time host */
146 nis_server *srv; /* nis_server struct to use. */
147 endpoint eps[]; /* array of endpoints */
148 int maxep; /* max array size */
149{
150 char hname[256];
151 int num_ep = 0, i;
152 struct hostent *he;
153 struct hostent dummy;
154 char *ptr[2];
155
156 if (host == NULL && sin == NULL)
157 return (NULL);
158
159 if (sin == NULL) {
160 he = gethostbyname(host);
161 if (he == NULL)
162 return(NULL);
163 } else {
164 he = &dummy;
165 ptr[0] = (char *)&sin->sin_addr.s_addr;
166 ptr[1] = NULL;
167 dummy.h_addr_list = ptr;
168 }
169
170 /*
171 * This is lame. We go around once for TCP, then again
172 * for UDP.
173 */
174 for (i = 0; (he->h_addr_list[i] != NULL) && (num_ep < maxep);
175 i++, num_ep++) {
176 struct in_addr *a;
177
178 a = (struct in_addr *)he->h_addr_list[i];
179 snprintf(hname, sizeof(hname), "%s.0.111", inet_ntoa(*a));
180 eps[num_ep].uaddr = strdup(hname);
181 eps[num_ep].family = strdup("inet");
182 eps[num_ep].proto = strdup("tcp");
183 }
184
185 for (i = 0; (he->h_addr_list[i] != NULL) && (num_ep < maxep);
186 i++, num_ep++) {
187 struct in_addr *a;
188
189 a = (struct in_addr *)he->h_addr_list[i];
190 snprintf(hname, sizeof(hname), "%s.0.111", inet_ntoa(*a));
191 eps[num_ep].uaddr = strdup(hname);
192 eps[num_ep].family = strdup("inet");
193 eps[num_ep].proto = strdup("udp");
194 }
195
196 srv->name = (nis_name) host;
197 srv->ep.ep_len = num_ep;
198 srv->ep.ep_val = eps;
199 srv->key_type = NIS_PK_NONE;
200 srv->pkey.n_bytes = NULL;
201 srv->pkey.n_len = 0;
202 return (srv);
203}
204
205/*
206 * __rpc_get_time_offset()
207 *
208 * This function uses a nis_server structure to contact the a remote
209 * machine (as named in that structure) and returns the offset in time
210 * between that machine and this one. This offset is returned in seconds
211 * and may be positive or negative.
212 *
213 * The first time through, a lot of fiddling is done with the netconfig
214 * stuff to find a suitable transport. The function is very aggressive
215 * about choosing UDP or at worst TCP if it can. This is because
216 * those transports support both the RCPBIND call and the internet
217 * time service.
218 *
219 * Once through, *uaddr is set to the universal address of
220 * the machine and *netid is set to the local netid for the transport
221 * that uaddr goes with. On the second call, the netconfig stuff
222 * is skipped and the uaddr/netid pair are used to fetch the netconfig
223 * structure and to then contact the machine for the time.
224 *
225 * td = "server" - "client"
226 */
227int
228__rpc_get_time_offset(td, srv, thost, uaddr, netid)
229 struct timeval *td; /* Time difference */
230 nis_server *srv; /* NIS Server description */
231 char *thost; /* if no server, this is the timehost */
232 char **uaddr; /* known universal address */
233 struct sockaddr_in *netid; /* known network identifier */
234{
235 CLIENT *clnt; /* Client handle */
236 endpoint *ep, /* useful endpoints */
237 *useep = NULL; /* endpoint of xp */
238 char *useua = NULL; /* uaddr of selected xp */
239 int epl, i; /* counters */
240 enum clnt_stat status; /* result of clnt_call */
241 long thetime;
242 long delta;
243 int needfree = 0;
244 struct timeval tv;
245 int time_valid;
246 int udp_ep = -1, tcp_ep = -1;
247 int a1, a2, a3, a4;
248 char ut[64], ipuaddr[64];
249 endpoint teps[32];
250 nis_server tsrv;
251#ifndef __REACTOS__
252 void (*oldsig)() = NULL; /* old alarm handler */
253#endif
254 struct sockaddr_in sin;
257 int type = 0;
258
259 td->tv_sec = 0;
260 td->tv_usec = 0;
261
262 /*
263 * First check to see if we need to find and address for this
264 * server.
265 */
266 if (*uaddr == NULL) {
267 if ((srv != NULL) && (thost != NULL)) {
268 msg("both timehost and srv pointer used!");
269 return (0);
270 }
271 if (! srv) {
272 srv = get_server(netid, thost, &tsrv, teps, 32);
273 if (srv == NULL) {
274 msg("unable to contruct server data.");
275 return (0);
276 }
277 needfree = 1; /* need to free data in endpoints */
278 }
279
280 ep = srv->ep.ep_val;
281 epl = srv->ep.ep_len;
282
283 /* Identify the TCP and UDP endpoints */
284 for (i = 0;
285 (i < epl) && ((udp_ep == -1) || (tcp_ep == -1)); i++) {
286 if (strcasecmp(ep[i].proto, "udp") == 0)
287 udp_ep = i;
288 if (strcasecmp(ep[i].proto, "tcp") == 0)
289 tcp_ep = i;
290 }
291
292 /* Check to see if it is UDP or TCP */
293 if (tcp_ep > -1) {
294 useep = &ep[tcp_ep];
295 useua = ep[tcp_ep].uaddr;
297 } else if (udp_ep > -1) {
298 useep = &ep[udp_ep];
299 useua = ep[udp_ep].uaddr;
301 }
302
303 if (useep == NULL) {
304 msg("no acceptable transport endpoints.");
305 if (needfree)
306 free_eps(teps, tsrv.ep.ep_len);
307 return (0);
308 }
309 }
310
311 /*
312 * Create a sockaddr from the uaddr.
313 */
314 if (*uaddr != NULL)
315 useua = *uaddr;
316
317 /* Fixup test for NIS+ */
318 sscanf(useua, "%d.%d.%d.%d.", &a1, &a2, &a3, &a4);
319 sprintf(ipuaddr, "%d.%d.%d.%d.0.111", a1, a2, a3, a4);
320 useua = &ipuaddr[0];
321
322 bzero((char *)&sin, sizeof(sin));
323 if (uaddr_to_sockaddr(useua, &sin)) {
324 msg("unable to translate uaddr to sockaddr.");
325 if (needfree)
326 free_eps(teps, tsrv.ep.ep_len);
327 return (0);
328 }
329
330 /*
331 * Create the client handle to rpcbind. Note we always try
332 * version 3 since that is the earliest version that supports
333 * the RPCB_GETTIME call. Also it is the version that comes
334 * standard with SVR4. Since most everyone supports TCP/IP
335 * we could consider trying the rtime call first.
336 */
337 clnt = clnttcp_create(&sin, RPCBPROG, RPCBVERS, &s, 0, 0);
338 if (clnt == NULL) {
339 msg("unable to create client handle to rpcbind.");
340 if (needfree)
341 free_eps(teps, tsrv.ep.ep_len);
342 return (0);
343 }
344
345 tv.tv_sec = 5;
346 tv.tv_usec = 0;
347 time_valid = 0;
349 (xdrproc_t)xdr_u_long, &thetime, tv);
350 /*
351 * The only error we check for is anything but success. In
352 * fact we could have seen PROGMISMATCH if talking to a 4.1
353 * machine (pmap v2) or TIMEDOUT if the net was busy.
354 */
355 if (status == RPC_SUCCESS)
356 time_valid = 1;
357 else {
358 int save;
359
360 /* Blow away possible stale CLNT handle. */
361 if (clnt != NULL) {
362 clnt_destroy(clnt);
363 clnt = NULL;
364 }
365
366 /*
367 * Convert PMAP address into timeservice address
368 * We take advantage of the fact that we "know" what
369 * the universal address looks like for inet transports.
370 *
371 * We also know that the internet timeservice is always
372 * listening on port 37.
373 */
374 sscanf(useua, "%d.%d.%d.%d.", &a1, &a2, &a3, &a4);
375 sprintf(ut, "%d.%d.%d.%d.0.37", a1, a2, a3, a4);
376
377 if (uaddr_to_sockaddr(ut, &sin)) {
378 msg("cannot convert timeservice uaddr to sockaddr.");
379 goto error;
380 }
381
382 s = socket(AF_INET, type, 0);
383 if (s == INVALID_SOCKET) {
384 msg("unable to open fd to network.");
385 goto error;
386 }
387
388 /*
389 * Now depending on whether or not we're talking to
390 * UDP we set a timeout or not.
391 */
392 if (type == SOCK_DGRAM) {
393 struct timeval timeout = { 20, 0 };
394 struct sockaddr_in from;
395 fd_set readfds;
396 int res;
397
398 if (sendto(s, (const char *)&thetime, sizeof(thetime), 0,
399 (struct sockaddr *)&sin, sizeof(sin)) == -1) {
400 msg("udp : sendto failed.");
401 goto error;
402 }
403 do {
404 FD_ZERO(&readfds);
405 FD_SET(s, &readfds);
406 res = select(_rpc_dtablesize(), &readfds,
407 (fd_set *)NULL, (fd_set *)NULL, &timeout);
408 } while (res == SOCKET_ERROR && WSAGetLastError() == WSAEINTR);
409 if (res == SOCKET_ERROR)
410 goto error;
411 len = sizeof(from);
412 res = recvfrom(s, (char *)&thetime, sizeof(thetime), 0,
413 (struct sockaddr *)&from, &len);
414 if (res == SOCKET_ERROR) {
415 msg("recvfrom failed on udp transport.");
416 goto error;
417 }
418 time_valid = 1;
419 } else {
420 int res;
421#ifndef _WIN32
422 oldsig = (void (*)())signal(SIGALRM, alarm_hndler);
423 saw_alarm = 0; /* global tracking the alarm */
424 alarm(20); /* only wait 20 seconds */
425#else
426 saw_alarm = 0;
427 /* XXX Need Windows signal/alarm stuff here XXX */
428#endif
429 res = connect(s, (struct sockaddr *)&sin, sizeof(sin));
430 if (res == SOCKET_ERROR) {
431 msg("failed to connect to tcp endpoint.");
432 goto error;
433 }
434 if (saw_alarm) {
435 msg("alarm caught it, must be unreachable.");
436 goto error;
437 }
438// res = read(s, (char *)&thetime, sizeof(thetime));
439 res = recv(s, (char *)&thetime, sizeof(thetime), 0);
440 if (res != sizeof(thetime)) {
441 if (saw_alarm)
442 msg("timed out TCP call.");
443 else
444 msg("wrong size of results returned");
445
446 goto error;
447 }
448 time_valid = 1;
449 }
450 save = WSAGetLastError();
452 errno = save;
453 s = RPC_ANYSOCK;
454
455 if (time_valid) {
456 thetime = ntohl(thetime);
457 thetime = thetime - TOFFSET; /* adjust to UNIX time */
458 } else
459 thetime = 0;
460 }
461
462 gettimeofday(&tv, 0);
463
464error:
465 /*
466 * clean up our allocated data structures.
467 */
468
469 if (s != RPC_ANYSOCK)
471
472 if (clnt != NULL)
473 clnt_destroy(clnt);
474
475#ifdef _WIN32
476 /* XXX Need Windows signal/alarm stuff here XXX */
477#else
478 alarm(0); /* reset that alarm if its outstanding */
479 if (oldsig) {
480 signal(SIGALRM, oldsig);
481 }
482#endif
483
484 /*
485 * note, don't free uaddr strings until after we've made a
486 * copy of them.
487 */
488 if (time_valid) {
489 if (*uaddr == NULL)
490 *uaddr = strdup(useua);
491
492 /* Round to the nearest second */
493 tv.tv_sec += (tv.tv_sec > 500000) ? 1 : 0;
494 delta = (thetime > tv.tv_sec) ? thetime - tv.tv_sec :
495 tv.tv_sec - thetime;
496 td->tv_sec = (thetime < tv.tv_sec) ? - delta : delta;
497 td->tv_usec = 0;
498 } else {
499 msg("unable to get the server's time.");
500 }
501
502 if (needfree)
503 free_eps(teps, tsrv.ep.ep_len);
504
505 return (time_valid);
506}
bool_t xdr_void(void)
Definition: xdr.c:92
bool_t xdr_u_long(XDR *xdrs, u_long *ulp)
Definition: xdr.c:186
_STLP_DECLSPEC complex< float > _STLP_CALL sin(const complex< float > &)
#define gettimeofday(tv, tz)
Definition: adns_win32.h:159
static nis_server * get_server(struct sockaddr_in *sin, char *host, nis_server *srv, eps, int maxep)
Definition: auth_time.c:143
#define TOFFSET
Definition: auth_time.c:74
static void alarm_hndler(int s)
Definition: auth_time.c:60
static void free_eps(eps, int num)
Definition: auth_time.c:117
static int uaddr_to_sockaddr(char *uaddr, struct sockaddr_in *sin)
Definition: auth_time.c:82
#define msg(x)
Definition: auth_time.c:54
int __rpc_get_time_offset(struct timeval *td, nis_server *srv, char *thost, char **uaddr, struct sockaddr_in *netid)
Definition: auth_time.c:228
static int saw_alarm
Definition: auth_time.c:57
#define bcopy(s1, s2, n)
Definition: various.h:25
#define bzero(s, n)
Definition: various.h:27
#define clnt_destroy(rh)
Definition: clnt.h:276
#define clnt_call(rh, proc, xargs, argsp, xres, resp, secs)
Definition: clnt.h:202
__BEGIN_DECLS CLIENT * clnttcp_create(struct sockaddr_in *, u_long, u_long, SOCKET *, u_int, u_int)
clnt_stat
Definition: clnt_stat.h:21
@ RPC_SUCCESS
Definition: clnt_stat.h:22
#define free
Definition: debug_ros.c:5
#define RPC_ANYSOCK
Definition: svc.h:327
#define NULL
Definition: types.h:112
unsigned char
Definition: typeof.h:29
INT WSAAPI recvfrom(IN SOCKET s, OUT CHAR FAR *buf, IN INT len, IN INT flags, OUT LPSOCKADDR from, IN OUT INT FAR *fromlen)
Definition: recv.c:87
INT WSAAPI recv(IN SOCKET s, OUT CHAR FAR *buf, IN INT len, IN INT flags)
Definition: recv.c:23
INT WSAAPI select(IN INT s, IN OUT LPFD_SET readfds, IN OUT LPFD_SET writefds, IN OUT LPFD_SET exceptfds, IN CONST struct timeval *timeout)
Definition: select.c:41
INT WSAAPI sendto(IN SOCKET s, IN CONST CHAR FAR *buf, IN INT len, IN INT flags, IN CONST struct sockaddr *to, IN INT tolen)
Definition: send.c:82
#define SOCK_STREAM
Definition: tcpip.h:118
#define AF_INET
Definition: tcpip.h:117
#define strcasecmp
Definition: fake.h:9
PHOSTENT WSAAPI gethostbyname(IN const char FAR *name)
Definition: getxbyxx.c:221
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLdouble s
Definition: gl.h:2039
GLuint res
Definition: glext.h:9613
GLuint GLuint num
Definition: glext.h:9618
GLenum GLsizei len
Definition: glext.h:6722
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
_Check_return_ _CRTIMP int __cdecl sscanf(_In_z_ const char *_Src, _In_z_ _Scanf_format_string_ const char *_Format,...)
#define inet_ntoa(addr)
Definition: inet.h:100
#define a
Definition: ke_i.h:78
#define error(str)
Definition: mkdosfs.c:1605
#define ntohl(x)
Definition: module.h:205
int socklen_t
Definition: tcp.c:35
static PVOID ptr
Definition: dispmode.c:27
#define sprintf(buf, format,...)
Definition: sprintf.c:55
static const struct update_accum a1
Definition: msg.c:578
static const struct update_accum a2
Definition: msg.c:586
static const struct update_accum a3
Definition: msg.c:600
static const struct update_accum a4
Definition: msg.c:2285
#define closesocket
Definition: ncftp.h:477
char * nis_name
Definition: nis.h:9
#define NIS_PK_NONE
Definition: nis.h:4
int _rpc_dtablesize(void)
#define RPCBPROG
Definition: rpcb_prot.h:626
#define RPCBPROC_GETTIME
Definition: rpcb_prot.h:697
#define RPCBVERS
Definition: rpcb_prot.h:627
#define errno
Definition: errno.h:18
_Check_return_ _CRTIMP char *__cdecl strdup(_In_opt_z_ const char *_Src)
int signal
Definition: except.c:82
SOCKET WSAAPI socket(IN INT af, IN INT type, IN INT protocol)
Definition: socklife.c:143
CardRegion * from
Definition: spigame.cpp:19
Definition: nis.h:10
char * uaddr
Definition: nis.h:11
Definition: winsock.h:66
char ** h_addr_list
Definition: winsock.h:138
Definition: tcpip.h:126
u_int n_len
Definition: xdr.h:333
char * n_bytes
Definition: xdr.h:334
Definition: nis.h:17
uint32_t key_type
Definition: nis.h:23
struct nis_server::@213 ep
netobj pkey
Definition: nis.h:24
nis_name name
Definition: nis.h:18
Definition: ps.c:97
Definition: dhcpd.h:245
unsigned long tv_sec
Definition: linux.h:1738
unsigned long tv_usec
Definition: linux.h:1739
char * host
Definition: whois.c:55
#define eps
#define WSAEINTR
Definition: winerror.h:1942
int PASCAL FAR WSAGetLastError(void)
Definition: dllmain.c:112
#define FD_ZERO(set)
Definition: winsock.h:96
#define INVALID_SOCKET
Definition: winsock.h:332
#define SOCK_DGRAM
Definition: winsock.h:336
UINT_PTR SOCKET
Definition: winsock.h:47
#define SOCKET_ERROR
Definition: winsock.h:333
#define FD_SET(fd, set)
Definition: winsock.h:89
#define snprintf
Definition: wintirpc.h:48
bool_t(* xdrproc_t)(XDR *,...)
Definition: xdr.h:144