1
2 /* doesn't use event.c ... isn't a full ypservd yet, just for tracing */
3 #define _GNU_SOURCE 1
4 #define _LARGEFILE64_SOURCE 1
5
6 #include <stdlib.h>
7 #include <string.h>
8 #include <stdarg.h>
9
10 #include <unistd.h>
11 #include <assert.h>
12 #define ASSERT assert
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <fcntl.h>
16 #include <sys/poll.h>
17 #include <netdb.h>
18 #include <sys/types.h>
19 #include <sys/socket.h>
20
21 #include <sys/time.h>
22 #include <time.h>
23
24 #include <socket_poll.h>
25 #include <vstr.h>
26
27 #define TRUE 1
28 #define FALSE 0
29
30 #define MY_MAX_PROTO_EVTS 4
31
32 static Vstr_base *rcpt = NULL;
33 static Vstr_base *rqst = NULL;
34 static Vstr_base *vuio_r = NULL;
35 static Vstr_base *vuio_w = NULL;
36
37 /* rfc1057 -> rfc1831
38 * -> rfc1832
39 * -> rfc1833
40 */
41
42 #define RPC_PORT_PORTMAP 111
43
44 #define RPC_MSG_VERSION 2
45
46 #define RPC_IS_CALL 0
47 #define RPC_IS_REPLY 1
48
49 #define RPC_MSG_RET_ACCEPTED 0
50 #define RPC_MSG_RET_DENIED 1
51
52 #define RPC_MSG_RET_A_SUCCESS 0 /* RPC executed successfully */
53 #define RPC_MSG_RET_A_PROG_UNAVAIL 1 /* remote hasn't exported program */
54 #define RPC_MSG_RET_A_PROG_MISMATCH 2 /* remote can't support version # */
55 #define RPC_MSG_RET_A_PROC_UNAVAIL 3 /* program can't support procedure */
56 #define RPC_MSG_RET_A_GARBAGE_ARGS 4 /* procedure can't decode params */
57
58 #define RPC_MSG_RET_D_VERS_MISMATCH 0 /* RPC version number != 2 */
59 #define RPC_MSG_RET_D_AUTH_ERROR 1 /* remote can't authenticate caller */
60
61 #define RPC_AUTH_FLAVOUR_NULL 0
62 #define RPC_AUTH_FLAVOUR_SYS 1
63 #define RPC_AUTH_FLAVOUR_SHORT 2
64 #define RPC_AUTH_FLAVOUR_DES 3
65
66 #define RPC_AUTH_RET_A_OK 0 /* success */
67
68 #define RPC_AUTH_RET_D_BADCRED 1 /* bad credentials (seal broken) */
69 #define RPC_AUTH_RET_D_REJECTEDCRED 2 /* client must begin new session */
70 #define RPC_AUTH_RET_D_BADVERF 3 /* bad verifier (seal broken) */
71 #define RPC_AUTH_RET_D_REJECTEDVERF 4 /* verifier expired or replayed */
72 #define RPC_AUTH_RET_D_TOOWEAK 5 /* rejected for security reasons */
73 #define RPC_AUTH_RET_D_INVALIDRESP 6 /* bogus response verifier */
74 #define RPC_AUTH_RET_D_FAILED 7 /* reason unknown */
75
76 #define RPC_PROG_PORTMAP 0x000186A0 /* 100000 */
77 #define RPC_PROG_NFS 0x000186A3
78 #define RPC_PROG_YPSERV 0x000186A4
79 #define RPC_PROG_MOUNTD 0x000186A5
80 #define RPC_PROG_YPBIND 0x000186A7
81
82 #define RPC_PROC_NULL 0 /* std. for all programs */
83
84 /* portmap */
85 #define RPC_PROG_PORTMAP_VERSION 2
86
87 #define RPC_PROG_PORTMAP_PROC_SET 1
88 #define RPC_PROG_PORTMAP_PROC_UNSET 2
89 #define RPC_PROG_PORTMAP_PROC_GETPORT 3
90 #define RPC_PROG_PORTMAP_PROC_DUMP 4
91 #define RPC_PROG_PORTMAP_PROC_CALLIT 5
92
93
94 /* ypserv */
95 #define RPC_PROG_YPSERV_VERSION 2
96
97 #define RPC_PROG_YPSERV_PROC_DOMAIN 1
98 #define RPC_PROG_YPSERV_PROC_DOMAIN_NONACK 2
99 #define RPC_PROG_YPSERV_PROC_MATCH 3
100 #define RPC_PROG_YPSERV_PROC_FIRST 4
101 #define RPC_PROG_YPSERV_PROC_NEXT 5
102 #define RPC_PROG_YPSERV_PROC_XFR 6
103 #define RPC_PROG_YPSERV_PROC_CLEAR 7
104 #define RPC_PROG_YPSERV_PROC_ALL 8
105 #define RPC_PROG_YPSERV_PROC_MASTER 9
106 #define RPC_PROG_YPSERV_PROC_ORDER 10
107 #define RPC_PROG_YPSERV_PROC_MAPLIST 11
108
109 /* ypbind */
110 #define RPC_PROG_YPBIND_VERSION 2
111
112 #define RPC_PROG_YPBIND_PROC_DOMAIN 1
113 #define RPC_PROG_YPBIND_PROC_SETDOM 2
114
115 static long my_rpc_xid = 0;
116
117 #define REPLY_EVNT_PORTMAP_UNSET 0
118 #define REPLY_EVNT_PORTMAP_SET1 1
119 #define REPLY_EVNT_PORTMAP_SET2 2
120 #define REPLY_EVNT_LOG 3 /* just log it */
121
122 static unsigned int udp_reply_evnt = REPLY_EVNT_PORTMAP_UNSET;
123
124 static short my_udp_port = 0;
125 static short my_tcp_port = 0;
126
127 unsigned int uio_r = 0;
128 unsigned int uio_w = 0;
129
130 unsigned int my_ignore_evnt = 0;
131
xdr_get_long(Vstr_base * s1,size_t * pos,size_t * len)132 static long xdr_get_long(Vstr_base *s1, size_t *pos, size_t *len)
133 {
134 long ret = 0;
135 char buf[4] = {0};
136
137 assert(s1 && pos && len);
138
139 if (*len < 4) /* hard coded */
140 return (0);
141
142 ret = vstr_sc_parse_b_uint32(s1, *pos);
143
144 *pos += 4;
145 *len -= 4;
146
147 return (ret);
148 }
149
xdr_put_long(Vstr_base * s1,size_t * pos,long val)150 static int xdr_put_long(Vstr_base *s1, size_t *pos, long val)
151 {
152 int ret = FALSE;
153
154 ASSERT(s1 && pos);
155
156 if ((ret = vstr_sc_add_b_uint32(s1, *pos, val)))
157 *pos += 4;
158
159 return (ret);
160 }
161
xdr_get_str_buf(Vstr_base * s1,size_t * pos,size_t * len,char * buf,size_t max_len)162 static size_t xdr_get_str_buf(Vstr_base *s1, size_t *pos, size_t *len,
163 char *buf, size_t max_len)
164 {
165 size_t pad_len = 0;
166 unsigned long buf_len = 0;
167
168 ASSERT(s1 && pos && len && buf);
169
170 buf_len = xdr_get_long(s1, pos, len);
171
172 if (!buf_len || (buf_len > *len))
173 return (0);
174
175 vstr_export_cstr_buf(s1, *pos, buf_len, buf, max_len);
176
177 *pos += buf_len;
178 *len -= buf_len;
179
180 if ((pad_len = (buf_len % 4)))
181 {
182 pad_len = 4 - pad_len; /*
183 * 1 % 4 = 1 == pad 3 bytes
184 * 2 % 4 = 2 == pad 2 bytes
185 * 3 % 4 = 3 == pad 1 bytes
186 */
187 if (pad_len > *len)
188 pad_len = *len;
189
190 *pos += pad_len;
191 *len -= pad_len;
192 }
193
194 return ((buf_len >= max_len) ? (max_len - 1) : buf_len);
195 }
196
xdr_put_str_buf(Vstr_base * s1,size_t * pos,const char * buf,size_t len,size_t max_len)197 static int xdr_put_str_buf(Vstr_base *s1, size_t *pos,
198 const char *buf, size_t len, size_t max_len)
199 {
200 int ret = FALSE;
201 size_t pad_len = 0;
202
203 ASSERT(s1 && pos && ((!buf && !len) || buf));
204
205 if (len > max_len)
206 len = max_len;
207
208 if (!xdr_put_long(s1, pos, len))
209 return (FALSE);
210
211 if (!len)
212 return (TRUE);
213
214 ret = vstr_add_buf(s1, *pos, buf, len); /* works negative */
215 if (ret) *pos += len;
216 if (ret && (pad_len = (len % 4)))
217 {
218 pad_len = 4 - pad_len; /*
219 * 1 % 4 = 1 == pad 3 bytes
220 * 2 % 4 = 2 == pad 2 bytes
221 * 3 % 4 = 3 == pad 1 bytes
222 */
223
224 ret = vstr_add_rep_chr(s1, *pos, 0, pad_len);
225 }
226
227 if (ret) *pos += pad_len;
228
229 ASSERT(ret);
230
231 return (ret);
232 }
233 #define XDR_PUT_CSTR_BUF(x, y, z, ML) xdr_put_str_buf(x, y, z, strlen(z), ML)
234
xdr_put_vstr(Vstr_base * s1,size_t * pos,Vstr_base * s2,size_t s2_pos,size_t len,size_t max_len)235 static int xdr_put_vstr(Vstr_base *s1, size_t *pos,
236 Vstr_base *s2, size_t s2_pos, size_t len,
237 size_t max_len)
238 {
239 int ret = FALSE;
240 size_t pad_len = 0;
241
242 ASSERT(s1 && pos && ((!s2 && !len) || s2) && s2_pos);
243
244 if (len > max_len)
245 len = max_len;
246
247 if (!xdr_put_long(s1, pos, len))
248 return (FALSE);
249
250 ret = vstr_add_vstr(s1, *pos, s2, s2_pos, len, 0);
251 if (ret) *pos += len;
252 if (ret && (pad_len = (len % 4)))
253 {
254 pad_len = 4 - pad_len;
255 ret = vstr_add_rep_chr(s1, *pos, 0, pad_len);
256 }
257 if (ret) *pos += pad_len;
258
259 ASSERT(ret);
260
261 return (ret);
262 }
263
xdr_put_list_long(Vstr_base * s1,size_t * pos,const long * list,size_t len,size_t max_len)264 static int xdr_put_list_long(Vstr_base *s1, size_t *pos,
265 const long *list, size_t len, size_t max_len)
266 {
267 int ret = FALSE;
268 size_t scan = 0;
269
270 ASSERT(s1 && pos && ((!list && !len) || list));
271
272 if (len > max_len)
273 len = max_len;
274
275 if (!xdr_put_long(s1, pos, len))
276 return (FALSE);
277
278 while (scan < len)
279 {
280 if (!(ret = xdr_put_long(s1, pos, list[scan])))
281 return (ret);
282 ++scan;
283 }
284
285 ASSERT(ret);
286
287 return (ret);
288 }
289
xdr_x_put_auth_null(Vstr_base * s1,size_t * pos)290 static int xdr_x_put_auth_null(Vstr_base *s1, size_t *pos)
291 {
292 int ret = FALSE;
293
294 ret |= !xdr_put_long(s1, pos, RPC_AUTH_FLAVOUR_NULL);
295 ret |= !xdr_put_long(s1, pos, 0);
296 ret |= !xdr_put_long(s1, pos, RPC_AUTH_FLAVOUR_NULL);
297 ret |= !xdr_put_long(s1, pos, 0);
298
299 return (!ret);
300 }
301
302 static int xdr_x_put_auth_sys_root(Vstr_base *s1, size_t *pos)
303 __attribute__((unused));
xdr_x_put_auth_sys_root(Vstr_base * s1,size_t * pos)304 static int xdr_x_put_auth_sys_root(Vstr_base *s1, size_t *pos)
305 { /* pretend we are root */
306 int ret = FALSE;
307 Vstr_base *tmp = vstr_make_base(NULL);
308 size_t tmp_pos = 0;
309 long extra_gids[7] = {0, 1, 2, 3, 4, 6, 10};
310
311 ret |= !xdr_put_long(s1, pos, RPC_AUTH_FLAVOUR_SYS);
312
313 /* BEG: tmp */
314 ret |= !xdr_put_long(tmp, &tmp_pos, time(NULL) ^ getpid()); /* stamp */
315 ret |= !XDR_PUT_CSTR_BUF(tmp, &tmp_pos, "code.and.org", 255);
316 ret |= !xdr_put_long(tmp, &tmp_pos, 0); /* euid */
317 ret |= !xdr_put_long(tmp, &tmp_pos, 0); /* egid */
318 ret |= !xdr_put_list_long(tmp, &tmp_pos, extra_gids, 7, 16);
319 /* END: tmp */
320
321 /* auth_length + above */
322 ret |= !xdr_put_vstr(s1, pos, tmp, 1, tmp->len, UINT_MAX);
323 vstr_free_base(tmp);
324
325 return (!ret);
326 }
327
xdr_x_put_portmap(Vstr_base * s1,size_t * pos,long proc)328 static int xdr_x_put_portmap(Vstr_base *s1, size_t *pos, long proc)
329 {
330 int ret = FALSE;
331
332 ret |= !xdr_put_long(s1, pos, ++my_rpc_xid);
333 ret |= !xdr_put_long(s1, pos, RPC_IS_CALL);
334 ret |= !xdr_put_long(s1, pos, RPC_MSG_VERSION);
335 ret |= !xdr_put_long(s1, pos, RPC_PROG_PORTMAP);
336 ret |= !xdr_put_long(s1, pos, RPC_PROG_PORTMAP_VERSION);
337 ret |= !xdr_put_long(s1, pos, proc);
338
339 return (!ret);
340 }
341
q_sendto(int fd,Vstr_base * s1,size_t pos,size_t len,struct sockaddr_in * to)342 static int q_sendto(int fd,
343 Vstr_base *s1, size_t pos, size_t len,
344 struct sockaddr_in *to)
345 {
346 int ret = -1;
347
348 if (!vstr_export_cstr_ptr(s1, pos, len))
349 return (FALSE);
350
351 ret = sendto(fd, vstr_export_cstr_ptr(s1, pos, len), len, 0,
352 (struct sockaddr *)to, sizeof(*to));
353 if (ret == -1)
354 return (FALSE);
355
356 return (TRUE);
357 }
358
udp_bind(const char * name,int port)359 static int udp_bind(const char *name, int port)
360 {
361 struct protoent *the_protocol = getprotobyname("udp");
362 struct sockaddr_in socket_bind_in;
363 int fd = -1;
364 int dummy = 1;
365
366 memset(&socket_bind_in, 0, sizeof(struct sockaddr_in));
367
368 socket_bind_in.sin_family = AF_INET;
369 {
370 struct hostent *tmp = gethostbyname(name);
371
372 if (!tmp)
373 exit (EXIT_FAILURE);
374 socket_bind_in.sin_addr = *(struct in_addr *) tmp->h_addr_list[0];
375 }
376
377 socket_bind_in.sin_port = htons(port);
378
379 if ((fd = socket(PF_INET, SOCK_DGRAM, the_protocol->p_proto)) == -1)
380 exit (EXIT_FAILURE);
381 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &dummy, sizeof(dummy)) == -1)
382 exit (EXIT_FAILURE);
383 if (fcntl(fd, F_SETFD, 1) == -1)
384 exit (EXIT_FAILURE);
385 if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1)
386 exit (EXIT_FAILURE);
387
388 if (bind(fd, (struct sockaddr *) &socket_bind_in,
389 sizeof(struct sockaddr_in)) == -1)
390 exit (EXIT_FAILURE);
391
392 return (fd);
393 }
394
tcp_bind(const char * name,int port)395 static int tcp_bind(const char *name, int port)
396 {
397 struct protoent *the_protocol = getprotobyname("ip"); /* generic */
398 struct sockaddr_in socket_bind_in;
399 int fd = -1;
400 int dummy = 1;
401
402 if (!the_protocol)
403 exit (EXIT_FAILURE);
404
405 memset(&socket_bind_in, 0, sizeof(struct sockaddr_in));
406
407 socket_bind_in.sin_family = AF_INET;
408 {
409 struct hostent *tmp = gethostbyname(name);
410
411 if (!tmp)
412 exit (EXIT_FAILURE);
413 socket_bind_in.sin_addr = *(struct in_addr *) tmp->h_addr_list[0];
414 }
415
416 socket_bind_in.sin_port = htons(port);
417
418 if ((fd = socket(PF_INET, SOCK_STREAM, the_protocol->p_proto)) == -1)
419 exit (EXIT_FAILURE);
420 if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &dummy, sizeof(dummy)) == -1)
421 exit (EXIT_FAILURE);
422 if (fcntl(fd, F_SETFD, 1) == -1)
423 exit (EXIT_FAILURE);
424 if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1)
425 exit (EXIT_FAILURE);
426
427 if (bind(fd, (struct sockaddr *) &socket_bind_in,
428 sizeof(struct sockaddr_in)) == -1)
429 exit (EXIT_FAILURE);
430
431 if (listen(fd, 64) == -1)
432 exit (EXIT_FAILURE);
433
434 return (fd);
435 }
436
rpc_call_unset_ypserv(int fd,struct sockaddr_in * to)437 static int rpc_call_unset_ypserv(int fd, struct sockaddr_in *to)
438 {
439 size_t rqst_pos = 0;
440
441 vstr_del(rqst, 1, rqst->len);
442
443 xdr_x_put_portmap(rqst, &rqst_pos, RPC_PROG_PORTMAP_PROC_UNSET);
444 xdr_x_put_auth_null(rqst, &rqst_pos);
445 xdr_put_long(rqst, &rqst_pos, RPC_PROG_YPSERV);
446 xdr_put_long(rqst, &rqst_pos, RPC_PROG_YPSERV_VERSION);
447 xdr_put_long(rqst, &rqst_pos, 0);
448 xdr_put_long(rqst, &rqst_pos, 0);
449
450 if (!q_sendto(fd, rqst, 1, rqst->len, to))
451 return (FALSE);
452
453 vstr_del(rqst, 1, rqst->len);
454
455 return (TRUE);
456 }
457
rpc_call_set_ypserv(int fd,struct sockaddr_in * to,long ypserv_proto,long ypserv_port)458 static int rpc_call_set_ypserv(int fd, struct sockaddr_in *to,
459 long ypserv_proto, long ypserv_port)
460 {
461 size_t rqst_pos = 0;
462
463 vstr_del(rqst, 1, rqst->len);
464
465 xdr_x_put_portmap(rqst, &rqst_pos, RPC_PROG_PORTMAP_PROC_SET);
466 xdr_x_put_auth_null(rqst, &rqst_pos);
467 xdr_put_long(rqst, &rqst_pos, RPC_PROG_YPSERV);
468 xdr_put_long(rqst, &rqst_pos, RPC_PROG_YPSERV_VERSION);
469 xdr_put_long(rqst, &rqst_pos, ypserv_proto);
470 xdr_put_long(rqst, &rqst_pos, ypserv_port);
471
472 if (!q_sendto(fd, rqst, 1, rqst->len, to))
473 return (FALSE);
474
475 vstr_del(rqst, 1, rqst->len);
476
477 return (TRUE);
478 }
479
srch_evnt(unsigned int * p_evt,unsigned int max_evts,unsigned int evnt)480 static unsigned int srch_evnt(unsigned int *p_evt, unsigned int max_evts,
481 unsigned int evnt)
482 {
483 unsigned int ret = 0;
484
485 while (ret < max_evts)
486 {
487 if (evnt == p_evt[ret])
488 return (ret);
489 ++ret;
490 }
491
492 ASSERT(FALSE);
493
494 return (0xFFFFFFFF);
495 }
496
del_evnt(unsigned int * p_evt,unsigned int * max_evts,unsigned int num)497 static void del_evnt(unsigned int *p_evt, unsigned int *max_evts,
498 unsigned int num)
499 {
500 close(SOCKET_POLL_INDICATOR(p_evt[num])->fd);
501 socket_poll_del(p_evt[num]);
502 --*max_evts;
503
504 if (num < *max_evts)
505 memmove(p_evt + num, p_evt + num + 1,
506 (*max_evts - num) * sizeof(unsigned int));
507 }
508
user_evts(unsigned int * passed_evts,unsigned int * p_u_evts,unsigned int * max_u_evts,unsigned int * p_t_evts,unsigned int * max_t_evts)509 static void user_evts(unsigned int *passed_evts,
510 unsigned int *p_u_evts, unsigned int *max_u_evts,
511 unsigned int *p_t_evts, unsigned int *max_t_evts)
512 {
513 unsigned int evts = *passed_evts;
514 struct sockaddr_in to_portmap;
515
516 to_portmap.sin_family = AF_INET;
517 to_portmap.sin_port = htons(RPC_PORT_PORTMAP);
518 to_portmap.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
519
520 if ((SOCKET_POLL_INDICATOR(uio_r)->revents &
521 (POLLERR|POLLHUP|POLLNVAL)) ||
522 (SOCKET_POLL_INDICATOR(uio_w)->revents &
523 (POLLERR|POLLHUP|POLLNVAL)))
524 {
525
526 if (!rpc_call_unset_ypserv(SOCKET_POLL_INDICATOR(p_u_evts[0])->fd,
527 &to_portmap))
528 return;
529
530 while (*max_u_evts)
531 del_evnt(p_u_evts, max_u_evts, *max_u_evts - 1);
532 while (*max_t_evts)
533 del_evnt(p_t_evts, max_t_evts, *max_t_evts - 1);
534
535 evts = 0;
536 }
537
538 if (evts && (SOCKET_POLL_INDICATOR(uio_r)->revents & POLLIN))
539 {
540 size_t endln_pos = 0;
541
542 --evts;
543
544 vstr_add_fmt(vuio_w, vuio_w->len, "\t User io event\n");
545
546 vstr_sc_read_iov_fd(vuio_r, vuio_r->len, SOCKET_POLL_INDICATOR(uio_r)->fd,
547 3, 32, NULL);
548
549 if ((endln_pos = vstr_srch_chr_fwd(vuio_r, 1, vuio_r->len, '\n')))
550 {
551 size_t vs_len = endln_pos - 1;
552 size_t endw_len = 0;
553 size_t tmp = 0;
554
555 tmp = VSTR_SPN_CSTR_CHRS_FWD(vuio_r, 1, vs_len, " \t");
556 vstr_del(vuio_r, 1, tmp);
557 vs_len -= tmp;
558
559 tmp = VSTR_CSPN_CSTR_CHRS_FWD(vuio_r, 1, vs_len, " \t");
560 endw_len = tmp;
561
562 if (0)
563 { ASSERT(FALSE); }
564 else if (VSTR_CMP_CSTR_EQ(vuio_r, 1, endw_len, "addudp"))
565 {
566 int fd = -1;
567
568 vstr_del(vuio_r, 1, endw_len);
569 vs_len -= endw_len;
570
571 tmp = VSTR_SPN_CSTR_CHRS_FWD(vuio_r, 1, vs_len, " \t");
572 vstr_del(vuio_r, 1, tmp);
573 vs_len -= tmp;
574
575 fd = udp_bind(vstr_export_cstr_ptr(vuio_r, 1, vs_len), my_udp_port);
576 p_u_evts[*max_u_evts] = socket_poll_add(fd);
577 SOCKET_POLL_INDICATOR(p_u_evts[*max_u_evts])->events = POLLIN;
578 ++*max_u_evts;
579
580 vstr_add_fmt(vuio_w, vuio_w->len, "\t Added udp interface -- %s -- "
581 "now has evnt -- %u --\n",
582 vstr_export_cstr_ptr(vuio_r, 1, vs_len),
583 p_u_evts[*max_u_evts - 1]);
584 }
585 else if (VSTR_CMP_CSTR_EQ(vuio_r, 1, endw_len, "addtcp"))
586 {
587 int fd = -1;
588
589 vstr_del(vuio_r, 1, endw_len);
590 vs_len -= endw_len;
591
592 tmp = VSTR_SPN_CSTR_CHRS_FWD(vuio_r, 1, vs_len, " \t");
593 vstr_del(vuio_r, 1, tmp);
594 vs_len -= tmp;
595
596 fd = tcp_bind(vstr_export_cstr_ptr(vuio_r, 1, vs_len), my_tcp_port);
597 p_t_evts[*max_t_evts] = socket_poll_add(fd);
598 SOCKET_POLL_INDICATOR(p_t_evts[*max_t_evts])->events = POLLIN;
599 ++*max_t_evts;
600
601 vstr_add_fmt(vuio_w, vuio_w->len, "\t Added tcp interface -- %s -- "
602 "now has evnt -- %u --\n",
603 vstr_export_cstr_ptr(vuio_r, 1, vs_len),
604 p_t_evts[*max_t_evts - 1]);
605 }
606 else if (VSTR_CMP_CSTR_EQ(vuio_r, 1, endw_len, "deludp"))
607 {
608 unsigned int evnt_num = 0;
609 unsigned int off_num = 0;
610
611 vstr_del(vuio_r, 1, endw_len);
612 vs_len -= endw_len;
613
614 tmp = VSTR_SPN_CSTR_CHRS_FWD(vuio_r, 1, vs_len, " \t");
615 vstr_del(vuio_r, 1, tmp);
616 vs_len -= tmp;
617
618 evnt_num = vstr_parse_uint(vuio_r, 1, vs_len, 10, NULL, NULL);
619
620 if ((off_num = srch_evnt(p_u_evts, *max_u_evts, evnt_num)) != 0xFFFFFFFF)
621 {
622 vstr_add_fmt(vuio_w, vuio_w->len, "\t Deleted udp evnt -- %d --\n",
623 evnt_num);
624 del_evnt(p_u_evts, max_u_evts, off_num);
625 }
626 else
627 vstr_add_fmt(vuio_w, vuio_w->len,
628 "\t **** Can't delete evnt -- %u -- "
629 "not a UDP event\n",
630 evnt_num);
631 }
632 else if (VSTR_CMP_CSTR_EQ(vuio_r, 1, endw_len, "deltcp"))
633 {
634 unsigned int evnt_num = 0;
635 unsigned int off_num = 0;
636
637 vstr_del(vuio_r, 1, endw_len);
638 vs_len -= endw_len;
639
640 tmp = VSTR_SPN_CSTR_CHRS_FWD(vuio_r, 1, vs_len, " \t");
641 vstr_del(vuio_r, 1, tmp);
642 vs_len -= tmp;
643
644 evnt_num = vstr_parse_uint(vuio_r, 1, vs_len, 10, NULL, NULL);
645
646 if ((off_num = srch_evnt(p_t_evts, *max_t_evts, evnt_num)) != 0xFFFFFFFF)
647 {
648 vstr_add_fmt(vuio_w, vuio_w->len, "\t Deleted tcp evnt -- %d --\n",
649 evnt_num);
650 del_evnt(p_t_evts, max_t_evts, off_num);
651 }
652 else
653 vstr_add_fmt(vuio_w, vuio_w->len,
654 "\t **** Can't delete evnt -- %u -- "
655 "not a TCP event\n",
656 evnt_num);
657 }
658 else if (VSTR_CMP_CSTR_EQ(vuio_r, 1, endw_len, "ignore"))
659 {
660 unsigned int evnt_num = 0;
661
662 vstr_del(vuio_r, 1, endw_len);
663 vs_len -= endw_len;
664
665 tmp = VSTR_SPN_CSTR_CHRS_FWD(vuio_r, 1, vs_len, " \t");
666 vstr_del(vuio_r, 1, tmp);
667 vs_len -= tmp;
668
669 evnt_num = vstr_parse_uint(vuio_r, 1, vs_len, 10, NULL, NULL);
670
671 if (my_ignore_evnt)
672 vstr_add_fmt(vuio_w, vuio_w->len,
673 "\t **** Can't ignore evnt -- %u -- "
674 "already ignoring evnt -- %u --\n",
675 evnt_num, my_ignore_evnt);
676 else
677 {
678 vstr_add_fmt(vuio_w, vuio_w->len, "\t Ignoring evnt -- %d --\n",
679 evnt_num);
680 my_ignore_evnt = evnt_num;
681 }
682
683 }
684 else if (VSTR_CMP_CSTR_EQ(vuio_r, 1, endw_len, "unignore"))
685 {
686 unsigned int evnt_num = 0;
687
688 vstr_del(vuio_r, 1, endw_len);
689 vs_len -= endw_len;
690
691 tmp = VSTR_SPN_CSTR_CHRS_FWD(vuio_r, 1, vs_len, " \t");
692 vstr_del(vuio_r, 1, tmp);
693 vs_len -= tmp;
694
695 evnt_num = vstr_parse_uint(vuio_r, 1, vs_len, 10, NULL, NULL);
696
697 if (!my_ignore_evnt)
698 vstr_add_fmt(vuio_w, vuio_w->len,
699 "\t **** Can't unignore evnt -- %u -- "
700 "not ignoring any evnts.\n",
701 evnt_num);
702 else if (my_ignore_evnt != evnt_num)
703 vstr_add_fmt(vuio_w, vuio_w->len,
704 "\t **** Can't unignore evnt -- %u -- "
705 "ignoring evnt -- %u --\n",
706 evnt_num, my_ignore_evnt);
707 else
708 {
709 vstr_add_fmt(vuio_w, vuio_w->len, "\t Unignoring evnt -- %d --\n",
710 evnt_num);
711 my_ignore_evnt = 0;
712 }
713
714 }
715 else if (VSTR_CMP_CSTR_EQ(vuio_r, 1, endw_len, "help"))
716 {
717 vstr_add_fmt(vuio_w, vuio_w->len, "%s", "\t List of all commands:\n");
718 vstr_add_fmt(vuio_w, vuio_w->len, "%s", "\t\t help\n");
719 vstr_add_fmt(vuio_w, vuio_w->len, "%s", "\t\t list\n");
720 vstr_add_fmt(vuio_w, vuio_w->len, "%s", "\t\t ignore <event>\n");
721 vstr_add_fmt(vuio_w, vuio_w->len, "%s", "\t\t unignore <event>\n");
722 vstr_add_fmt(vuio_w, vuio_w->len, "%s", "\t\t deludp <udpevent>\n");
723 vstr_add_fmt(vuio_w, vuio_w->len, "%s", "\t\t deltcp <tcpevent>\n");
724 vstr_add_fmt(vuio_w, vuio_w->len, "%s", "\t\t addudp <interface>\n");
725 vstr_add_fmt(vuio_w, vuio_w->len, "%s", "\t\t addtcp <interface>\n");
726 vstr_add_fmt(vuio_w, vuio_w->len, "%s", "\t\t quit\n");
727 }
728 else if (VSTR_CMP_CSTR_EQ(vuio_r, 1, endw_len, "list"))
729 {
730 unsigned int scan = 0;
731
732 vstr_add_fmt(vuio_w, vuio_w->len, "%s", "\t List of all evnts:\n");
733
734 vstr_add_fmt(vuio_w, vuio_w->len, "\t\t %s%*s %4u\n",
735 uio_r == my_ignore_evnt ? "*" : " ",
736 -16, "USER_IO_R", uio_r);
737 vstr_add_fmt(vuio_w, vuio_w->len, "\t\t %s%*s %4u\n",
738 uio_w == my_ignore_evnt ? "*" : " ",
739 -16, "USER_IO_W", uio_w);
740
741 scan = 0;
742 while (scan < *max_u_evts)
743 {
744 struct sockaddr_in sa[1];
745 socklen_t socklen = sizeof(sa);
746
747 getpeername(SOCKET_POLL_INDICATOR(p_u_evts[scan])->fd, sa, &socklen);
748 vstr_add_fmt(vuio_w, vuio_w->len, "\t\t %s%*s %4u ${ipv4.p:%p}:%hu\n",
749 p_u_evts[scan] == my_ignore_evnt ? "*" : " ",
750 -16, "UDP", p_u_evts[scan],
751 &sa->sin_addr, ntohs(sa->sin_port));
752 ++scan;
753 }
754
755 scan = 0;
756 while (scan < *max_t_evts)
757 {
758 struct sockaddr_in sa[1];
759 socklen_t socklen = sizeof(sa);
760
761 getsockname(SOCKET_POLL_INDICATOR(p_t_evts[scan])->fd, sa, &socklen);
762 vstr_add_fmt(vuio_w, vuio_w->len, "\t\t %s%*s %4u ${ipv4.p:%p}:%hu\n",
763 p_t_evts[scan] == my_ignore_evnt ? "*" : " ",
764 -16, "TCP", p_t_evts[scan],
765 &sa->sin_addr, ntohs(sa->sin_port));
766 ++scan;
767 }
768 }
769 else if (VSTR_CMP_CSTR_EQ(vuio_r, 1, endw_len, "quit"))
770 {
771 if (!rpc_call_unset_ypserv(SOCKET_POLL_INDICATOR(p_u_evts[0])->fd,
772 &to_portmap))
773 return;
774
775 while (*max_u_evts)
776 del_evnt(p_u_evts, max_u_evts, *max_u_evts - 1);
777 while (*max_t_evts)
778 del_evnt(p_t_evts, max_t_evts, *max_t_evts - 1);
779
780 vstr_add_fmt(vuio_w, vuio_w->len, "\t QUIT\n");
781
782 evts = 0;
783 }
784
785 vstr_del(vuio_r, 1, vs_len + 1);
786 }
787 }
788
789 *passed_evts = evts;
790 }
791
loop_do_proto_evts(unsigned int * passed_evts,unsigned int * p_evt,unsigned int * passed_max_evts,int tcp)792 static void loop_do_proto_evts(unsigned int *passed_evts,
793 unsigned int *p_evt,
794 unsigned int *passed_max_evts, int tcp)
795 {
796 unsigned int scan = 0;
797 unsigned int max_evts = *passed_max_evts;
798 unsigned int evts = *passed_evts;
799
800
801 while (evts && (scan < max_evts))
802 {
803 if (SOCKET_POLL_INDICATOR(p_evt[scan])->revents &
804 (POLLERR|POLLHUP|POLLNVAL))
805 {
806 --evts;
807 vstr_add_fmt(vuio_w, vuio_w->len, "%s",
808 "\tevent = (POLLERR|POLLHUP|POLLNVAL)\n");
809
810 del_evnt(p_evt, &max_evts, scan);
811 continue;
812 }
813
814 if (SOCKET_POLL_INDICATOR(p_evt[scan])->revents & POLLIN)
815 {
816 char buf[1024];
817 struct sockaddr_in from;
818 socklen_t len = sizeof(from);
819 ssize_t ret = -1;
820 int fd = SOCKET_POLL_INDICATOR(p_evt[scan])->fd;
821
822 --evts;
823 if (tcp)
824 while ((fd = accept(fd, (struct sockaddr *)&from, &len)) != -1)
825 {
826 size_t data_len = 0;
827
828 while ((ret = read(fd, buf, sizeof(buf))) != -1)
829 data_len += ret;
830 close(fd);
831
832 vstr_add_fmt(vuio_w, vuio_w->len, "\tevent = POLLIN_tcp(%d), len = %zu\n",
833 p_evt[scan], (size_t)ret);
834 }
835 else
836 while ((ret = recvfrom(fd, buf, sizeof(buf), 0,
837 (struct sockaddr *)&from, &len)) != -1)
838 {
839 vstr_add_fmt(vuio_w, vuio_w->len, "\tevent = POLLIN_udp(%d), len = %zu\n",
840 p_evt[scan], (size_t)ret);
841 /* deal with RPC request ... */
842
843 if (ret < 16) continue; /* min size */
844
845 if (my_ignore_evnt == p_evt[scan])
846 continue; /* just drop the request */
847
848 assert(!rcpt->len);
849 vstr_del(rcpt, 1, rcpt->len);
850 vstr_add_ptr(rcpt, rcpt->len, buf, ret);
851
852 {
853 size_t rcpt_len = rcpt->len;
854 size_t rcpt_pos = 1;
855 size_t rqst_pos = 0;
856 /* BEG: generic RPC header... */
857 long xid = xdr_get_long(rcpt, &rcpt_pos, &rcpt_len);
858 long direction = xdr_get_long(rcpt, &rcpt_pos, &rcpt_len);
859 long rpcvers = 0;
860 long prog = 0;
861 long progvers = 0;
862 long proc = 0;
863 long auth_flavour = 0;
864 unsigned long auth_length = 0;
865
866 if (direction == RPC_IS_REPLY)
867 {
868
869 vstr_add_fmt(vuio_w, vuio_w->len, "\t got reply %ld ",
870 my_rpc_xid - xid);
871
872 switch (udp_reply_evnt)
873 {
874 case REPLY_EVNT_PORTMAP_UNSET:
875 VSTR_ADD_CSTR_BUF(vuio_w, vuio_w->len, "PORTMAP_UNSET\n");
876 if (!rpc_call_set_ypserv(fd, &from, IPPROTO_UDP, my_udp_port))
877 abort();
878 if (!rpc_call_set_ypserv(fd, &from, IPPROTO_TCP, my_tcp_port))
879 abort();
880 udp_reply_evnt = REPLY_EVNT_PORTMAP_SET1;
881 break;
882
883 case REPLY_EVNT_PORTMAP_SET1:
884 VSTR_ADD_CSTR_BUF(vuio_w, vuio_w->len, "PORTMAP_SET1\n");
885 udp_reply_evnt = REPLY_EVNT_PORTMAP_SET2;
886 break;
887 case REPLY_EVNT_PORTMAP_SET2:
888 VSTR_ADD_CSTR_BUF(vuio_w, vuio_w->len, "PORTMAP_SET2\n");
889 udp_reply_evnt = REPLY_EVNT_LOG;
890 break;
891
892 case REPLY_EVNT_LOG:
893 VSTR_ADD_CSTR_BUF(vuio_w, vuio_w->len, "UNKNOWN\n");
894 break;
895
896 default:
897 abort();
898 }
899
900 goto fin; /* reply from portmapper */
901 }
902
903 ASSERT(direction == RPC_IS_CALL);
904
905 rpcvers = xdr_get_long(rcpt, &rcpt_pos, &rcpt_len);
906 prog = xdr_get_long(rcpt, &rcpt_pos, &rcpt_len);
907 progvers = xdr_get_long(rcpt, &rcpt_pos, &rcpt_len);
908 proc = xdr_get_long(rcpt, &rcpt_pos, &rcpt_len);
909
910 ASSERT(rpcvers == RPC_MSG_VERSION);
911 ASSERT(prog == RPC_PROG_YPSERV);
912 ASSERT(progvers == RPC_PROG_YPSERV_VERSION);
913
914 auth_flavour = xdr_get_long(rcpt, &rcpt_pos, &rcpt_len);
915 auth_length = xdr_get_long(rcpt, &rcpt_pos, &rcpt_len);
916 vstr_add_fmt(vuio_w, vuio_w->len, "\t got AUTH cred %lu %zu\n",
917 auth_length, rcpt_len);
918 if (auth_length > rcpt_len)
919 auth_length = rcpt_len;
920 rcpt_pos += auth_length;
921 rcpt_len -= auth_length;
922
923 auth_flavour = xdr_get_long(rcpt, &rcpt_pos, &rcpt_len);
924 auth_length = xdr_get_long(rcpt, &rcpt_pos, &rcpt_len);
925 vstr_add_fmt(vuio_w, vuio_w->len, "\t got AUTH %lu %zu\n",
926 auth_length, rcpt_len);
927 if (auth_length > rcpt_len)
928 auth_length = rcpt_len;
929 rcpt_pos += auth_length;
930 rcpt_len -= auth_length;
931 /* END: generic RPC header... */
932
933 rqst_pos = 0;
934 switch (proc)
935 {
936 case RPC_PROG_YPSERV_PROC_DOMAIN:
937 {
938 char dom[128 + 1];
939 size_t dom_len = 0;
940
941 dom_len = xdr_get_str_buf(rcpt, &rcpt_pos, &rcpt_len,
942 dom, sizeof(dom));
943
944 vstr_add_fmt(vuio_w, vuio_w->len, "\t got procedure %s\n",
945 "DOMAIN");
946 vstr_add_fmt(vuio_w, vuio_w->len, "\t\t dom = %zu:%s\n",
947 dom_len, dom);
948 vstr_add_fmt(vuio_w, vuio_w->len, "\t\t remain = %zu\n", rcpt_len);
949 /* BEG: send RPC reply */
950 xdr_put_long(rqst, &rqst_pos, xid);
951 xdr_put_long(rqst, &rqst_pos, RPC_IS_REPLY);
952 xdr_put_long(rqst, &rqst_pos, 0);
953 xdr_put_long(rqst, &rqst_pos, 0);
954 xdr_put_long(rqst, &rqst_pos, 0);
955 xdr_put_long(rqst, &rqst_pos, 0);
956 xdr_put_long(rqst, &rqst_pos, 1); /* YPBIND_SUCC_VAL */
957 /* END: send RPC reply */
958 }
959 break;
960
961 case RPC_PROG_YPSERV_PROC_DOMAIN_NONACK:
962 {
963 char dom[128 + 1];
964 size_t dom_len = 0;
965
966 dom_len = xdr_get_str_buf(rcpt, &rcpt_pos, &rcpt_len,
967 dom, sizeof(dom));
968
969 vstr_add_fmt(vuio_w, vuio_w->len, "\t got procedure %s\n",
970 "DOMAIN_NONACK");
971 vstr_add_fmt(vuio_w, vuio_w->len, "\t\t dom = %zu:%s\n",
972 dom_len, dom);
973 vstr_add_fmt(vuio_w, vuio_w->len, "\t\t remain = %zu\n", rcpt_len);
974
975 /* BEG: send RPC reply */
976 xdr_put_long(rqst, &rqst_pos, xid);
977 xdr_put_long(rqst, &rqst_pos, RPC_IS_REPLY);
978 xdr_put_long(rqst, &rqst_pos, 0);
979 xdr_put_long(rqst, &rqst_pos, 0);
980 xdr_put_long(rqst, &rqst_pos, 0);
981 xdr_put_long(rqst, &rqst_pos, 0);
982 xdr_put_long(rqst, &rqst_pos, 1);
983 /* END: send RPC reply */
984 }
985 break;
986
987 case RPC_PROG_YPSERV_PROC_MASTER:
988 {
989 char dom[128 + 1];
990 size_t dom_len = 0;
991 char serv[128 + 1];
992 size_t serv_len = 0;
993
994 dom_len = xdr_get_str_buf(rcpt, &rcpt_pos, &rcpt_len,
995 dom, sizeof(dom));
996 serv_len = xdr_get_str_buf(rcpt, &rcpt_pos, &rcpt_len,
997 serv, sizeof(serv));
998
999 vstr_add_fmt(vuio_w, vuio_w->len, "\t got procedure %s\n",
1000 "MASTER");
1001 vstr_add_fmt(vuio_w, vuio_w->len, "\t\t dom = %zu:%s\n",
1002 dom_len, dom);
1003 vstr_add_fmt(vuio_w, vuio_w->len, "\t\t serv = %zu:%s\n",
1004 serv_len, serv);
1005 vstr_add_fmt(vuio_w, vuio_w->len, "\t\t remain = %zu\n", rcpt_len);
1006
1007 /* BEG: send RPC reply */
1008 xdr_put_long(rqst, &rqst_pos, xid);
1009 xdr_put_long(rqst, &rqst_pos, RPC_IS_REPLY);
1010 xdr_put_long(rqst, &rqst_pos, 0);
1011 xdr_put_long(rqst, &rqst_pos, 0);
1012 xdr_put_long(rqst, &rqst_pos, 0);
1013 xdr_put_long(rqst, &rqst_pos, 0);
1014 xdr_put_long(rqst, &rqst_pos, -1);
1015 xdr_put_long(rqst, &rqst_pos, 0);
1016 /* END: send RPC reply */
1017 }
1018 break;
1019
1020 case RPC_PROG_YPSERV_PROC_MAPLIST:
1021 {
1022 char dom[128 + 1];
1023 size_t dom_len = 0;
1024
1025 dom_len = xdr_get_str_buf(rcpt, &rcpt_pos, &rcpt_len,
1026 dom, sizeof(dom));
1027
1028 vstr_add_fmt(vuio_w, vuio_w->len, "\t got procedure %s\n",
1029 "MAPLIST");
1030 vstr_add_fmt(vuio_w, vuio_w->len, "\t\t dom = %zu:%s\n",
1031 dom_len, dom);
1032 vstr_add_fmt(vuio_w, vuio_w->len, "\t\t remain = %zu\n",
1033 rcpt_len);
1034 }
1035 break;
1036
1037 default:
1038 vstr_add_fmt(vuio_w, vuio_w->len, "\t got UNKNOWN procedure %ld\n",
1039 proc);
1040 vstr_add_fmt(vuio_w, vuio_w->len, "\t\t remain = %zu\n", rcpt_len);
1041 break;
1042 }
1043
1044 vstr_del(rcpt, 1, rcpt->len);
1045
1046 if (!q_sendto(fd, rqst, 1, rqst->len, &from))
1047 goto fin;
1048 }
1049 fin:
1050 vstr_del(rcpt, 1, rcpt->len);
1051 vstr_del(rqst, 1, rqst->len);
1052 }
1053 }
1054
1055 ++scan;
1056 }
1057
1058 *passed_max_evts = max_evts;
1059 *passed_evts = evts;
1060 }
1061
rpc_setup(char * argv[],unsigned int p_u_evt[static4],unsigned int p_t_evt[static4])1062 static int rpc_setup(char *argv[],
1063 unsigned int p_u_evt[static 4],
1064 unsigned int p_t_evt[static 4])
1065 {
1066 struct sockaddr_in to;
1067
1068 my_rpc_xid = getpid() ^ time(NULL);
1069
1070 p_u_evt[0] = socket_poll_add(udp_bind(argv[1], my_udp_port = atoi(argv[2])));
1071 SOCKET_POLL_INDICATOR(p_u_evt[0])->events = POLLIN;
1072
1073 p_t_evt[0] = socket_poll_add(tcp_bind(argv[1], my_tcp_port = atoi(argv[3])));
1074 SOCKET_POLL_INDICATOR(p_t_evt[0])->events = POLLIN;
1075
1076 to.sin_family = AF_INET;
1077 to.sin_port = htons(RPC_PORT_PORTMAP);
1078 to.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1079
1080 if (!rpc_call_unset_ypserv(SOCKET_POLL_INDICATOR(p_u_evt[0])->fd, &to))
1081 goto fin;
1082
1083 return (TRUE);
1084
1085 fin:
1086 abort();
1087
1088 return (FALSE);
1089 }
1090
main(int argc,char * argv[])1091 int main(int argc, char *argv[])
1092 {
1093 unsigned int p_t_evt[MY_MAX_PROTO_EVTS];
1094 unsigned int p_u_evt[MY_MAX_PROTO_EVTS];
1095 unsigned int max_t_evts = 0;
1096 unsigned int max_u_evts = 0;
1097 struct stat stat_buf;
1098
1099 if (!socket_poll_init(4, SOCKET_POLL_TYPE_MAP_COMPRESSED))
1100 exit (EXIT_FAILURE);
1101
1102 if (!vstr_init())
1103 exit (EXIT_FAILURE);
1104
1105 if (fstat(1, &stat_buf) == -1)
1106 stat_buf.st_blksize = 4 * 1024;
1107 if (!stat_buf.st_blksize)
1108 stat_buf.st_blksize = 4 * 1024; /* defualt 4k -- proc etc. */
1109
1110 if (!vstr_sc_fmt_add_all(NULL) ||
1111 !vstr_cntl_conf(NULL, VSTR_CNTL_CONF_SET_FMT_CHAR_ESC, '$') ||
1112 !vstr_cntl_conf(NULL,
1113 VSTR_CNTL_CONF_SET_NUM_BUF_SZ, stat_buf.st_blksize) ||
1114 !vstr_make_spare_nodes(NULL, VSTR_TYPE_NODE_BUF, 32))
1115 exit (EXIT_FAILURE);
1116
1117 if (!(rcpt = vstr_make_base(NULL)))
1118 exit (EXIT_FAILURE);
1119
1120 if (!(rqst = vstr_make_base(NULL)))
1121 exit (EXIT_FAILURE);
1122
1123 if (!(vuio_r = vstr_make_base(NULL)))
1124 exit (EXIT_FAILURE);
1125 if (!(vuio_w = vstr_make_base(NULL)))
1126 exit (EXIT_FAILURE);
1127
1128 if (argc < 4)
1129 {
1130 vstr_add_fmt(vuio_w, vuio_w->len, " Format: ex_ypservd <host> <udpport> <tcpport>\n");
1131 goto boot_failed;
1132 }
1133
1134 if (!(uio_r = socket_poll_add(0)))
1135 {
1136 vstr_add_fmt(vuio_w, vuio_w->len, "Can't speak to user via. stdin\n");
1137 goto boot_failed;
1138 }
1139 SOCKET_POLL_INDICATOR(uio_r)->events = POLLIN;
1140 if (!(uio_w = socket_poll_add(1)))
1141 {
1142 vstr_add_fmt(vuio_w, vuio_w->len, "Can't speak to user via. stdout\n");
1143 goto boot_failed;
1144 }
1145
1146 if (!rpc_setup(argv, p_u_evt, p_t_evt))
1147 goto boot_failed;
1148 max_t_evts = 1;
1149 max_u_evts = 1;
1150
1151 vstr_add_fmt(vuio_w, vuio_w->len, "STARTED\n");
1152 while (max_u_evts && max_t_evts)
1153 {
1154 int evts = socket_poll_update_all(-1);
1155
1156 vstr_add_fmt(vuio_w, vuio_w->len, "events = %d\n", evts);
1157
1158 user_evts(&evts, p_u_evt, &max_u_evts, p_t_evt, &max_t_evts);
1159
1160 loop_do_proto_evts(&evts, p_u_evt, &max_u_evts, FALSE);
1161 loop_do_proto_evts(&evts, p_t_evt, &max_t_evts, TRUE);
1162
1163 while (vuio_w->len)
1164 vstr_sc_write_fd(vuio_w, 1, vuio_w->len, 1, NULL);
1165 }
1166 vstr_add_fmt(vuio_w, vuio_w->len, "ENDED\n");
1167
1168 while (vuio_w->len)
1169 vstr_sc_write_fd(vuio_w, 1, vuio_w->len, 1, NULL);
1170
1171 exit (EXIT_SUCCESS);
1172
1173 boot_failed:
1174 while (vuio_w->len)
1175 vstr_sc_write_fd(vuio_w, 1, vuio_w->len, 1, NULL);
1176
1177 exit (EXIT_FAILURE);
1178 }
1179