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