enum clnt_stat handle_replies __P((void)); enum clnt_stat handle_ping __P((void)); int broadcast __P((struct _dom_binding *ypdb)); int ping __P((struct _dom_binding *ypdb));  char *domain;  struct _dom_binding *ypbindlist; int check;  #define YPSET_NO	0 #define YPSET_LOCAL	1 #define YPSET_ALL	2 int ypsetmode = YPSET_NO;  int rpcsock, pingsock; struct rmtcallargs rmtca; struct rmtcallres rmtcr; bool_t rmtcr_outval; u_long rmtcr_port; SVCXPRT *udptransp, *tcptransp; SVCXPRT *ludptransp, *ltcptransp;  struct _dom_binding *xid2ypdb __P((int xid)); int unique_xid __P((struct _dom_binding *ypdb));    void * ypbindproc_null_2x(transp, argp, clnt) SVCXPRT *transp; void *argp; CLIENT *clnt; { static char res;  memset(&res, 0, sizeof(res)); return (void *)&res; }  struct ypbind_resp * ypbindproc_domain_2x(transp, argp, clnt) SVCXPRT *transp; domainname *argp; CLIENT *clnt; { static struct ypbind_resp res; struct _dom_binding *ypdb; char path[MAXPATHLEN]; time_t now;  memset(&res, 0, sizeof res); res.ypbind_status = YPBIND_FAIL_VAL;  for (ypdb = ypbindlist; ypdb; ypdb = ypdb->dom_pnext) if (!strcmp(ypdb->dom_domain, *argp)) break;  if (ypdb == NULL) { ypdb = (struct _dom_binding *)malloc(sizeof *ypdb); memset(ypdb, 0, sizeof *ypdb); strncpy(ypdb->dom_domain, *argp, sizeof ypdb->dom_domain); ypdb->dom_vers = YPVERS; ypdb->dom_alive = 0; ypdb->dom_lockfd = -1; sprintf(path, "%s/%s.%d", BINDINGDIR, ypdb->dom_domain, (int)ypdb->dom_vers); unlink(path); ypdb->dom_xid = unique_xid(ypdb); ypdb->dom_pnext = ypbindlist; ypbindlist = ypdb; check++; return NULL; }  if (ypdb->dom_alive == 0) return NULL;  #ifdef HEURISTIC time(&now); if (now < ypdb->dom_ask_t + 5) {  if (ypdb->dom_check_t >= now) {  ypdb->dom_check_t = 0; check++; } } ypdb->dom_ask_t = now; #endif  res.ypbind_status = YPBIND_SUCC_VAL; memmove(&res.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr, &ypdb->dom_server_addr.sin_addr, sizeof(res.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr)); memmove(&res.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port, &ypdb->dom_server_port, sizeof(res.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port)); #ifdef DEBUG printf("domain %s at %s/%d\n", ypdb->dom_domain, inet_ntoa(ypdb->dom_server_addr.sin_addr), ntohs(ypdb->dom_server_addr.sin_port)); #endif return &res; }  bool_t * ypbindproc_setdom_2x(transp, argp, clnt) SVCXPRT *transp; struct ypbind_setdom *argp; CLIENT *clnt; { struct sockaddr_in *fromsin, bindsin; static bool_t res;  memset(&res, 0, sizeof(res)); fromsin = svc_getcaller(transp);  switch (ypsetmode) { case YPSET_LOCAL: if (transp != ludptransp && transp != ltcptransp) { syslog(LOG_WARNING, "attempted spoof of ypsetme"); return (bool_t *)NULL; } if (fromsin->sin_addr.s_addr != htonl(INADDR_LOOPBACK)) return (bool_t *)NULL; break; case YPSET_ALL: break; case YPSET_NO: default: return (bool_t *)NULL; }  if (ntohs(fromsin->sin_port) >= IPPORT_RESERVED) return &res;  if (argp->ypsetdom_vers != YPVERS) return &res;  memset(&bindsin, 0, sizeof bindsin); bindsin.sin_family = AF_INET; bindsin.sin_len = sizeof(bindsin); memcpy(&bindsin.sin_addr, &argp->ypsetdom_binding.ypbind_binding_addr, sizeof(argp->ypsetdom_binding.ypbind_binding_addr)); memcpy(&bindsin.sin_port, &argp->ypsetdom_binding.ypbind_binding_port, sizeof(argp->ypsetdom_binding.ypbind_binding_port)); rpc_received(argp->ypsetdom_domain, &bindsin, 1);  res = 1; return &res; }  static void ypbindprog_2(rqstp, transp) struct svc_req *rqstp; register SVCXPRT *transp; { union { domainname ypbindproc_domain_2_arg; struct ypbind_setdom ypbindproc_setdom_2_arg; } argument; struct authunix_parms *creds; char *result; bool_t (*xdr_argument)(), (*xdr_result)(); char *(*local)();  switch (rqstp->rq_proc) { case YPBINDPROC_NULL: xdr_argument = xdr_void; xdr_result = xdr_void; local = (char *(*)()) ypbindproc_null_2x; break;  case YPBINDPROC_DOMAIN: xdr_argument = xdr_domainname; xdr_result = xdr_ypbind_resp; local = (char *(*)()) ypbindproc_domain_2x; break;  case YPBINDPROC_SETDOM: switch (rqstp->rq_cred.oa_flavor) { case AUTH_UNIX: creds = (struct authunix_parms *)rqstp->rq_clntcred; if (creds->aup_uid != 0) { svcerr_auth(transp, AUTH_BADCRED); return; } break; default: svcerr_auth(transp, AUTH_TOOWEAK); return; }  xdr_argument = xdr_ypbind_setdom; xdr_result = xdr_void; local = (char *(*)()) ypbindproc_setdom_2x; break;  default: svcerr_noproc(transp); return; } memset(&argument, 0, sizeof(argument)); if (!svc_getargs(transp, xdr_argument, (caddr_t)&argument)) { svcerr_decode(transp); return; } result = (*local)(transp, &argument, rqstp); if (result != NULL && !svc_sendreply(transp, xdr_result, result)) { svcerr_systemerr(transp); } return; }  void usage() { fprintf(stderr, "usage: ypbind [-ypset] [-ypsetme]\n"); exit(0); }  int main(argc, argv) int argc; char *argv[]; { char path[MAXPATHLEN]; struct sockaddr_in sin; struct timeval tv; fd_set fdsr; int width, lockfd, len, lsock; int evil = 0, one = 1; DIR *dirp; struct dirent *dent;  yp_get_default_domain(&domain); if (domain[0] == '\0') { fprintf(stderr, "domainname not set. Aborting.\n"); exit(1); }  while (--argc) { ++argv; if (!strcmp("-ypset", *argv)) ypsetmode = YPSET_ALL; else if (!strcmp("-ypsetme", *argv)) ypsetmode = YPSET_LOCAL; else usage(); }   dirp = opendir(BINDINGDIR); if (dirp) { while ((dent = readdir(dirp))) { if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, "..")) continue; snprintf(path, sizeof(path), "%s/%s", BINDINGDIR, dent->d_name); (void) unlink(path); } closedir(dirp); } else { printf("Enabling yp client subsystem.\n"); printf("To disable: kill ypbind and remove %s\n", BINDINGDIR); (void)mkdir(BINDINGDIR, 0755); }  #ifdef O_SHLOCK if ((lockfd = open(YPBINDLOCK, O_CREAT|O_SHLOCK|O_RDWR|O_TRUNC, 0644)) == -1) { fprintf(stderr, "ypbind: cannot create %s\n", YPBINDLOCK); exit(1); } #else if ((lockfd = open(YPBINDLOCK, O_CREAT|O_RDWR|O_TRUNC, 0644)) == -1) { fprintf(stderr, "ypbind: cannot create %s\n", YPBINDLOCK); exit(1); } flock(lockfd, LOCK_SH); #endif  (void)pmap_unset(YPBINDPROG, YPBINDVERS);  udptransp = svcudp_create(RPC_ANYSOCK); if (udptransp == NULL) { fprintf(stderr, "cannot create udp service."); exit(1); } if (!svc_register(udptransp, YPBINDPROG, YPBINDVERS, ypbindprog_2, IPPROTO_UDP)) { fprintf(stderr, "unable to register (YPBINDPROG, YPBINDVERS, udp)."); exit(1); }  tcptransp = svctcp_create(RPC_ANYSOCK, 0, 0); if (tcptransp == NULL) { fprintf(stderr, "cannot create tcp service."); exit(1); } if (!svc_register(tcptransp, YPBINDPROG, YPBINDVERS, ypbindprog_2, IPPROTO_TCP)) { fprintf(stderr, "unable to register (YPBINDPROG, YPBINDVERS, tcp)."); exit(1); }  if (ypsetmode == YPSET_LOCAL) {  if ((lsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { syslog(LOG_ERR, "cannot create local udp socket: %m"); exit(1); } (void)setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one); len = sizeof(sin); if (getsockname(udptransp->xp_sock, (struct sockaddr *)&sin, &len) == -1) { syslog(LOG_ERR, "cannot getsockname local udp: %m"); exit(1); } sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); if (bind(lsock, (struct sockaddr *)&sin, len) != 0) { syslog(LOG_ERR, "cannot bind local udp: %m"); exit(1); } if ((ludptransp = svcudp_create(lsock)) == NULL) { fprintf(stderr, "cannot create udp service."); exit(1); }   if ((lsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { syslog(LOG_ERR, "cannot create udp socket: %m"); exit(1); } (void)setsockopt(lsock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof one); len = sizeof(sin); if (getsockname(tcptransp->xp_sock, (struct sockaddr *)&sin, &len) == -1) { syslog(LOG_ERR, "cannot getsockname udp: %m"); exit(1); } sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); if (bind(lsock, (struct sockaddr *)&sin, len) == -1) { syslog(LOG_ERR, "cannot bind udp: %m"); exit(1); } if ((ltcptransp = svctcp_create(lsock, 0, 0)) == NULL) { fprintf(stderr, "cannot create tcp service."); exit(1); } }  if ((rpcsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { perror("socket"); return -1; } if ((pingsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { perror("socket"); return -1; }  fcntl(rpcsock, F_SETFL, fcntl(rpcsock, F_GETFL, 0) | FNDELAY); fcntl(pingsock, F_SETFL, fcntl(rpcsock, F_GETFL, 0) | FNDELAY); setsockopt(rpcsock, SOL_SOCKET, SO_BROADCAST, &one, sizeof(one)); rmtca.prog = YPPROG; rmtca.vers = YPVERS; rmtca.proc = YPPROC_DOMAIN_NONACK; rmtca.xdr_args = NULL;		 rmtca.args_ptr = NULL;		 rmtcr.port_ptr = &rmtcr_port; rmtcr.xdr_results = xdr_bool; rmtcr.results_ptr = (caddr_t)&rmtcr_outval;   ypbindlist = (struct _dom_binding *)malloc(sizeof *ypbindlist); memset(ypbindlist, 0, sizeof *ypbindlist); strncpy(ypbindlist->dom_domain, domain, sizeof ypbindlist->dom_domain); ypbindlist->dom_vers = YPVERS; ypbindlist->dom_alive = 0; ypbindlist->dom_lockfd = -1; sprintf(path, "%s/%s.%d", BINDINGDIR, ypbindlist->dom_domain, (int)ypbindlist->dom_vers); (void)unlink(path);  checkwork();  while (1) { width = svc_maxfd; if (rpcsock > width) width = rpcsock; if (pingsock > width) width = pingsock; width++;  fdsr = svc_fdset; FD_SET(rpcsock, &fdsr); FD_SET(pingsock, &fdsr); tv.tv_sec = 1; tv.tv_usec = 0;  switch (select(width, &fdsr, NULL, NULL, &tv)) { case 0: checkwork(); break; case -1: perror("select\n"); break; default: if (FD_ISSET(rpcsock, &fdsr)) handle_replies(); if (FD_ISSET(pingsock, &fdsr)) handle_ping(); svc_getreqset(&fdsr); if (check) checkwork(); break; }  #ifdef DAEMON if (!evil && ypbindlist->dom_alive) { evil = 1; daemon(0, 0); } #endif } }   void checkwork() { struct _dom_binding *ypdb; time_t t;  time(&t); for (ypdb = ypbindlist; ypdb; ypdb = ypdb->dom_pnext) { if (ypdb->dom_check_t < t) { if (ypdb->dom_alive == 1) ping(ypdb); else broadcast(ypdb); time(&t); ypdb->dom_check_t = t + 5; } } check = 0; }  int ping(ypdb) struct _dom_binding *ypdb; { domainname dom = ypdb->dom_domain; struct rpc_msg msg; char buf[1400]; enum clnt_stat st; int outlen; AUTH *rpcua; XDR xdr;  memset(&xdr, 0, sizeof xdr); memset(&msg, 0, sizeof msg);  rpcua = authunix_create_default(); if (rpcua == (AUTH *)NULL) {  return RPC_SYSTEMERROR; } msg.rm_direction = CALL; msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; msg.rm_call.cb_prog = YPPROG; msg.rm_call.cb_vers = YPVERS; msg.rm_call.cb_proc = YPPROC_DOMAIN_NONACK; msg.rm_call.cb_cred = rpcua->ah_cred; msg.rm_call.cb_verf = rpcua->ah_verf;  msg.rm_xid = ypdb->dom_xid; xdrmem_create(&xdr, buf, sizeof buf, XDR_ENCODE); if (!xdr_callmsg(&xdr, &msg)) { st = RPC_CANTENCODEARGS; AUTH_DESTROY(rpcua); return st; } if (!xdr_domainname(&xdr, &dom)) { st = RPC_CANTENCODEARGS; AUTH_DESTROY(rpcua); return st; } outlen = (int)xdr_getpos(&xdr); xdr_destroy(&xdr); if (outlen < 1) { st = RPC_CANTENCODEARGS; AUTH_DESTROY(rpcua); return st; } AUTH_DESTROY(rpcua);  ypdb->dom_alive = 2; if (sendto(pingsock, buf, outlen, 0, (struct sockaddr *)&ypdb->dom_server_addr, sizeof ypdb->dom_server_addr) < 0) perror("sendto"); return 0;  }  int broadcast(ypdb) struct _dom_binding *ypdb; { domainname dom = ypdb->dom_domain; struct rpc_msg msg; char buf[1400], inbuf[8192]; char path[MAXPATHLEN]; enum clnt_stat st; int outlen, i, sock, len; struct sockaddr_in bindsin; struct ifconf ifc; struct ifreq ifreq, *ifr; struct in_addr in; AUTH *rpcua; XDR xdr;  rmtca.xdr_args = xdr_domainname; rmtca.args_ptr = (char *)&dom;  memset(&xdr, 0, sizeof xdr); memset(&msg, 0, sizeof msg);  rpcua = authunix_create_default(); if (rpcua == (AUTH *)NULL) {  return RPC_SYSTEMERROR; } msg.rm_direction = CALL; msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; msg.rm_call.cb_prog = PMAPPROG; msg.rm_call.cb_vers = PMAPVERS; msg.rm_call.cb_proc = PMAPPROC_CALLIT; msg.rm_call.cb_cred = rpcua->ah_cred; msg.rm_call.cb_verf = rpcua->ah_verf;  msg.rm_xid = ypdb->dom_xid; xdrmem_create(&xdr, buf, sizeof buf, XDR_ENCODE); if (!xdr_callmsg(&xdr, &msg)) { st = RPC_CANTENCODEARGS; AUTH_DESTROY(rpcua); return st; } if (!xdr_rmtcall_args(&xdr, &rmtca)) { st = RPC_CANTENCODEARGS; AUTH_DESTROY(rpcua); return st; } outlen = (int)xdr_getpos(&xdr); xdr_destroy(&xdr); if (outlen < 1) { st = RPC_CANTENCODEARGS; AUTH_DESTROY(rpcua); return st; } AUTH_DESTROY(rpcua);  if (ypdb->dom_lockfd != -1) { close(ypdb->dom_lockfd); ypdb->dom_lockfd = -1; sprintf(path, "%s/%s.%d", BINDINGDIR, ypdb->dom_domain, (int)ypdb->dom_vers); unlink(path); }  memset(&bindsin, 0, sizeof bindsin); bindsin.sin_family = AF_INET; bindsin.sin_len = sizeof(bindsin); bindsin.sin_port = htons(PMAPPORT);  if (ypdb->dom_alive == 2) {  bindsin.sin_addr = ypdb->dom_server_addr.sin_addr; if (sendto(rpcsock, buf, outlen, 0, (struct sockaddr *)&bindsin, sizeof bindsin) < 0) perror("sendto"); }  if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { perror("socket"); return -1; }  ifc.ifc_len = sizeof inbuf; ifc.ifc_buf = inbuf; if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) { close(sock); perror("ioctl(SIOCGIFCONF)"); return -1; } ifr = ifc.ifc_req; ifreq.ifr_name[0] = '\0'; for (i = 0; i < ifc.ifc_len; i += len, ifr = (struct ifreq *)((caddr_t)ifr + len)) { #if defined(BSD) && BSD >= 199103 len = sizeof ifr->ifr_name + ifr->ifr_addr.sa_len; #else len = sizeof ifc.ifc_len / sizeof(struct ifreq); #endif ifreq = *ifr; if (ifreq.ifr_addr.sa_family != AF_INET) continue; if (ioctl(sock, SIOCGIFFLAGS, &ifreq) < 0) { perror("ioctl(SIOCGIFFLAGS)"); continue; } if ((ifreq.ifr_flags & IFF_UP) == 0) continue;  ifreq.ifr_flags &= (IFF_LOOPBACK | IFF_BROADCAST); if (ifreq.ifr_flags == IFF_BROADCAST) { if (ioctl(sock, SIOCGIFBRDADDR, &ifreq) < 0) { perror("ioctl(SIOCGIFBRDADDR)"); continue; } } else if (ifreq.ifr_flags == IFF_LOOPBACK) { if (ioctl(sock, SIOCGIFADDR, &ifreq) < 0) { perror("ioctl(SIOCGIFADDR)"); continue; } } else continue;  in = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr; bindsin.sin_addr = in; if (sendto(rpcsock, buf, outlen, 0, (struct sockaddr *)&bindsin, sizeof bindsin) < 0) perror("sendto"); } close(sock); return 0; }  enum clnt_stat
handle_replies(){	char buf[1400];	int fromlen, inlen;	struct _dom_binding *ypdb;	struct sockaddr_in raddr;	struct rpc_msg msg;	XDR xdr;recv_again:	memset(&xdr, 0, sizeof(xdr));	memset(&msg, 0, sizeof(msg));	msg.acpted_rply.ar_verf = _null_auth;	msg.acpted_rply.ar_results.where = (caddr_t)&rmtcr;	msg.acpted_rply.ar_results.proc = xdr_rmtcallres;try_again:	fromlen = sizeof (struct sockaddr);	inlen = recvfrom(rpcsock, buf, sizeof buf, 0,	    (struct sockaddr *)&raddr, &fromlen);	if (inlen < 0) {		if (errno == EINTR)			goto try_again;		return RPC_CANTRECV;	}	if (inlen < sizeof(u_int32_t))		goto recv_again;	/*	 * see if reply transaction id matches sent id.	 * If so, decode the results.	 */	xdrmem_create(&xdr, buf, (u_int)inlen, XDR_DECODE);	if (xdr_replymsg(&xdr, &msg)) {		if ((msg.rm_reply.rp_stat == MSG_ACCEPTED) &&		    (msg.acpted_rply.ar_stat == SUCCESS)) {			raddr.sin_port = htons((u_short)rmtcr_port);			ypdb = xid2ypdb(msg.rm_xid);			if (ypdb)				rpc_received(ypdb->dom_domain, &raddr, 0);		}	}	xdr.x_op = XDR_FREE;	msg.acpted_rply.ar_results.proc = xdr_void;	xdr_destroy(&xdr);	return RPC_SUCCESS;}