ni_status ni2_mergedirprop(void *domain, ni_id *dir, const ni_name key, ni_namelist values) { /* mergeprop given a directory rather than a pathname */ ni_status ret; ni_property p; ni_namelist nl; ni_index where, whereval; int i; /* need to be talking to the master */ ni_needwrite(domain, 1); /* fetch list of property keys from directory */ NI_INIT(&nl); ret = ni_listprops(domain, dir, &nl); if (ret != NI_OK) { return ret; } /* check for existing property with this key */ where = ni_namelist_match(nl, key); ni_namelist_free(&nl); /* if property doesn't exist, create it */ if (where == NI_INDEX_NULL) { NI_INIT(&p); p.nip_name = ni_name_dup(key); p.nip_val = ni_namelist_dup(values); ret = ni_createprop(domain, dir, p, NI_INDEX_NULL); ni_prop_free(&p); return ret; } /* property exists: replace the existing values */ /* fetch existing namelist for this property */ NI_INIT(&nl); ret = ni_readprop(domain, dir, where, &nl); if (ret != NI_OK) { return ret; } /* merge new values */ for (i = 0; i < values.ni_namelist_len; i++) { whereval = ni_namelist_match(nl, values.ni_namelist_val[i]); if (whereval == NI_INDEX_NULL) { ni_namelist_insert(&nl, values.ni_namelist_val[i], NI_INDEX_NULL); } } /* write the new list back */ ret = ni_writeprop(domain, dir, where, nl); ni_namelist_free(&nl); return ret; }
ni_status ni2_destroydirval(void *domain, ni_id *dir, const ni_name key, ni_namelist values) { /* destroyval given a directory rather than a pathname */ ni_status ret; ni_namelist nl; ni_index where, whereval; int i; /* need to be talking to the master */ ni_needwrite(domain, 1); /* fetch list of property keys from directory */ NI_INIT(&nl); ret = ni_listprops(domain, dir, &nl); if (ret != NI_OK) { return ret; } /* check for existing property with this key */ where = ni_namelist_match(nl, key); ni_namelist_free(&nl); /* if property doesn't exist, nothing to do */ if (where == NI_INDEX_NULL) { return NI_OK; } /* fetch existing namelist for this property */ NI_INIT(&nl); ret = ni_readprop(domain, dir, where, &nl); if (ret != NI_OK) { return ret; } /* delete values */ for (i = 0; i < values.ni_namelist_len; i++) { whereval = ni_namelist_match(nl, values.ni_namelist_val[i]); while (whereval != NI_INDEX_NULL) { ni_namelist_delete(&nl, whereval); whereval = ni_namelist_match(nl, values.ni_namelist_val[i]); } } /* write the new list back */ ret = ni_writeprop(domain, dir, where, nl); ni_namelist_free(&nl); return ret; }
static int secure_passwords() { void *d, *d1; int status; ni_index where; ni_id dir; ni_namelist nl; status = ni_open(NULL, ".", &d); while (status == NI_OK) { dir.nii_object = 0; status = ni_lookupprop(d, &dir, "security_options", &nl); if (status == NI_OK) { where = ni_namelist_match(nl, "secure_passwords"); if (where != NI_INDEX_NULL) { ni_free(d); return 1; } } d1 = d; status = ni_open(d1, "..", &d); ni_free(d1); } return 0; }
ni_status ni2_statpropdir(void *domain, ni_id *dir, const ni_name key, ni_index *where) { /* statprop given a directory rather than a pathname */ ni_status ret; ni_namelist nl; /* assume there's no match */ *where = NI_INDEX_NULL; /* fetch list of property keys from directory */ NI_INIT(&nl); ret = ni_listprops(domain, dir, &nl); if (ret != NI_OK) { return ret; } /* check for property with this key */ *where = ni_namelist_match(nl, key); ni_namelist_free(&nl); /* if property doesn't exist, no match */ if (*where == NI_INDEX_NULL) { return NI_NOPROP; } return NI_OK; }
ni_status ni2_renamedirprop(void *domain, ni_id *dir, const ni_name oldname, const ni_name newname) { /* renameprop given a directory rather than a pathname */ ni_status ret; ni_index where; ni_namelist nl; /* need to be talking to the master */ ni_needwrite(domain, 1); /* fetch list of property keys from directory */ NI_INIT(&nl); ret = ni_listprops(domain, dir, &nl); if (ret != NI_OK) { return ret; } /* look up old name */ where = ni_namelist_match(nl, oldname); ni_namelist_free(&nl); /* if it's not there, return an error */ if (where == NI_INDEX_NULL) { return NI_NOPROP; } return ni_renameprop(domain, dir, where, newname); }
ni_status ni2_statvaldir(void *domain, ni_id *dir, const ni_name key, const ni_name value, ni_index *where) { /* statval given a directory rather than a pathname */ ni_status ret; ni_namelist nl; ni_index wh; /* assume there's no match */ *where = NI_INDEX_NULL; /* fetch list of property keys from directory */ NI_INIT(&nl); ret = ni_listprops(domain, dir, &nl); if (ret != NI_OK) { return ret; } /* check for property with this key */ wh = ni_namelist_match(nl, key); ni_namelist_free(&nl); /* if property doesn't exist, no match */ if (wh == NI_INDEX_NULL) { return NI_NOPROP; } /* fetch existing namelist for this property */ NI_INIT(&nl); ret = ni_readprop(domain, dir, wh, &nl); if (ret != NI_OK) { return ret; } /* check for this value */ wh = ni_namelist_match(nl, value); ni_namelist_free(&nl); /* if value doesn't exist, no match */ if (wh == NI_INDEX_NULL) { return NI_NONAME; } *where = wh; return NI_OK; }
ni_status ni2_destroydirprop(void *domain, ni_id *dir, ni_namelist keys) { /* destroyprop given a directory rather than a pathname */ ni_status ret; ni_index where; ni_namelist nl; int i; /* need to be talking to the master */ ni_needwrite(domain, 1); /* fetch list of property keys from directory */ NI_INIT(&nl); ret = ni_listprops(domain, dir, &nl); if (ret != NI_OK) { return ret; } /* destroy all occurrences of each key */ for (i = 0; i < keys.ni_namelist_len; i++) { where = ni_namelist_match(nl, keys.ni_namelist_val[i]); /* keep looking for all occurrences */ while (where != NI_INDEX_NULL) { ret = ni_destroyprop(domain, dir, where); if (ret != NI_OK) { ni_namelist_free(&nl); return ret; } /* update the namelist */ ni_namelist_delete(&nl, where); where = ni_namelist_match(nl, keys.ni_namelist_val[i]); } } ni_namelist_free(&nl); return NI_OK; }
void nipl_mergeprop(ni_proplist *l, const ni_name n, const ni_name v) { /* property list utility */ /* merge a value into a property in a property list */ ni_index where; where = ni_proplist_match(*l, n, NULL); if (where == NI_INDEX_NULL) { nipl_createprop(l, n); where = ni_proplist_match(*l, n, NULL); } where = ni_namelist_match(l->nipl_val[where].nip_val, v); if (where == NI_INDEX_NULL) { ni_namelist_insert(&(l->nipl_val[where].nip_val), v, NI_INDEX_NULL); } }
ni_status ni2_reappropdir(void *domain, ni_id *dir, const ni_name key) { /* reapprop given a directory rather than a pathname */ ni_status ret; ni_namelist nl; ni_index where; /* fetch list of property keys from directory */ NI_INIT(&nl); ret = ni_listprops(domain, dir, &nl); if (ret != NI_OK) { return ret; } /* check for property with this key */ where = ni_namelist_match(nl, key); ni_namelist_free(&nl); /* if property doesn't exist, return */ if (where == NI_INDEX_NULL) { return NI_OK; } /* fetch existing namelist for this property */ NI_INIT(&nl); ret = ni_readprop(domain, dir, where, &nl); if (ret != NI_OK) { return ret; } /* if the property contains any values, leave it alone */ if (nl.ni_namelist_len > 0) { ni_namelist_free(&nl); return NI_OK; } /* property is empty, delete it */ ni_namelist_free(&nl); return ni_destroyprop(domain, dir, where); }
ni_status ni2_createdirprop(void *domain, ni_id *dir, const ni_name key, ni_namelist values) { /* createprop given a directory rather than a pathname */ ni_status ret; ni_property p; ni_namelist nl; ni_index where; /* need to be talking to the master */ ni_needwrite(domain, 1); /* fetch list of property keys from directory */ NI_INIT(&nl); ret = ni_listprops(domain, dir, &nl); if (ret != NI_OK) { return ret; } /* check for existing property with this key */ where = ni_namelist_match(nl, key); ni_namelist_free(&nl); /* if property doesn't exist, create it */ if (where == NI_INDEX_NULL) { NI_INIT(&p); p.nip_name = ni_name_dup(key); p.nip_val = ni_namelist_dup(values); ret = ni_createprop(domain, dir, p, NI_INDEX_NULL); ni_prop_free(&p); return ret; } /* property exists: replace the existing values */ ret = ni_writeprop(domain, dir, where, values); return ret; }
ni_status checkserves(unsigned long masteraddr, ni_name mastertag, unsigned long myaddr, ni_name mytag) { struct sockaddr_in mastersin; struct in_addr myinaddr; char myserves[MAXPATHLEN + 16]; ni_index where; int status; int sock; CLIENT *cl; struct timeval tv; nibind_getregister_res res; ni_id_res id_res; ni_lookup_res lu_res; ni_lookup_args childdir; ni_namelist_res prop_res; ni_prop_args pa; mastersin.sin_addr.s_addr = masteraddr; mastersin.sin_port = 0; mastersin.sin_family = AF_INET; myinaddr.s_addr = myaddr; /* connect to master hosts's nibindd */ sock = socket_connect(&mastersin, NIBIND_PROG, NIBIND_VERS); if (sock < 0) { system_log(LOG_WARNING, "sanitycheck can't connect to %s/%s - %m", inet_ntoa(mastersin.sin_addr), mastertag); return NI_FAILED; } FD_SET(sock, &clnt_fdset); /* protect client socket */ cl = clnttcp_create(&mastersin, NIBIND_PROG, NIBIND_VERS, &sock, 0, 0); if (cl == NULL) { socket_close(sock); FD_CLR(sock, &clnt_fdset); /* unprotect client socket */ return NI_FAILED; } tv.tv_sec = READALL_TIMEOUT; tv.tv_usec = 0; /* get the ports for master's tag */ bzero((char *)&res, sizeof(res)); if (clnt_call(cl, NIBIND_GETREGISTER, xdr_ni_name, &mastertag, xdr_nibind_getregister_res, &res, tv) != RPC_SUCCESS) { /* call failed */ socket_lock(); clnt_destroy(cl); (void)close(sock); socket_unlock(); FD_CLR(sock, &clnt_fdset); /* unprotect client socket */ return NI_FAILED; } socket_lock(); clnt_destroy(cl); (void)close(sock); socket_unlock(); FD_CLR(sock, &clnt_fdset); /* unprotect client socket */ if (res.status != NI_OK) { /* no server for the master's tag */ system_log(LOG_ERR, "tag %s: master's tag %s is not served at master's addresss", mytag, mastertag); return res.status; } /* connect to the master */ mastersin.sin_port = htons(res.nibind_getregister_res_u.addrs.tcp_port); xdr_free(xdr_nibind_getregister_res, (void *)&res); sock = socket_connect(&mastersin, NI_PROG, NI_VERS); if (sock < 0) { system_log(LOG_WARNING, "sanitycheck can't connect to " "%s/%s - %m", inet_ntoa(mastersin.sin_addr), mastertag); return NI_FAILED; } FD_SET(sock, &clnt_fdset); /* protect client socket */ cl = clnttcp_create(&mastersin, NI_PROG, NI_VERS, &sock, 0, 0); if (cl == NULL) { /* can't connect to master */ socket_close(sock); FD_CLR(sock, &clnt_fdset); /* unprotect client socket */ return NI_FAILED; } FD_SET(sock, &clnt_fdset); /* protect client socket */ /* get root directory */ bzero((char *)&id_res, sizeof(id_res)); status = clnt_call(cl, _NI_ROOT, xdr_void, NULL, xdr_ni_id_res, &id_res, tv); if (status != NI_OK) { /* can't get root! */ socket_lock(); clnt_destroy(cl); (void)close(sock); socket_unlock(); FD_CLR(sock, &clnt_fdset); /* unprotect client socket */ system_log(LOG_ERR, "tag %s: can't get master's root directory", mytag); return status; } if (id_res.status != NI_OK) { /* can't get root! */ socket_lock(); clnt_destroy(cl); (void)close(sock); socket_unlock(); FD_CLR(sock, &clnt_fdset); /* unprotect client socket */ system_log(LOG_ERR, "tag %s: master has no root directory", mytag); return status; } childdir.key = malloc(16); childdir.value = malloc(16); /* get machines subdirectory */ childdir.id = id_res.ni_id_res_u.id; xdr_free(xdr_ni_id_res, (void *)&id_res); strcpy(childdir.key,"name"); strcpy(childdir.value,"machines"); bzero((char *)&lu_res, sizeof(lu_res)); status = clnt_call(cl, _NI_LOOKUP, xdr_ni_lookup_args, &childdir, xdr_ni_lookup_res, &lu_res, tv); if (status != NI_OK) { /* can't get /machines! */ free(childdir.key); free(childdir.value); socket_lock(); clnt_destroy(cl); (void)close(sock); socket_unlock(); FD_CLR(sock, &clnt_fdset); /* unprotect client socket */ system_log(LOG_ERR, "tag %s: can't get master's /machines directory", mytag); return status; } if (lu_res.status != NI_OK) { /* no /machines! */ free(childdir.key); free(childdir.value); socket_lock(); clnt_destroy(cl); (void)close(sock); socket_unlock(); FD_CLR(sock, &clnt_fdset); /* unprotect client socket */ system_log(LOG_ERR, "tag %s: can't get master's /machines directory", mytag); return lu_res.status; } if (lu_res.ni_lookup_res_u.stuff.idlist.ni_idlist_len == 0) { /* no /machines! */ xdr_free(xdr_ni_lookup_res, (void *)&lu_res); free(childdir.key); free(childdir.value); socket_lock(); clnt_destroy(cl); (void)close(sock); socket_unlock(); FD_CLR(sock, &clnt_fdset); /* unprotect client socket */ system_log(LOG_ERR, "tag %s: master has no /machines directory", mytag); return NI_NODIR; } /* get my subdirectory */ childdir.id.nii_object = lu_res.ni_lookup_res_u.stuff.idlist.ni_idlist_val[0]; xdr_free(xdr_ni_lookup_res, (void *)&lu_res); strcpy(childdir.key,"ip_address"); strcpy(childdir.value,(char *)inet_ntoa(myinaddr)); bzero((char *)&lu_res, sizeof(lu_res)); status = clnt_call(cl, _NI_LOOKUP, xdr_ni_lookup_args, &childdir, xdr_ni_lookup_res, &lu_res, tv); if (status != NI_OK) { /* can't get /machines/ip_address=<myaddr>! */ free(childdir.key); free(childdir.value); socket_lock(); clnt_destroy(cl); (void)close(sock); socket_unlock(); FD_CLR(sock, &clnt_fdset); /* unprotect client socket */ system_log(LOG_ERR, "tag %s: can't get master's /machines/ip_address=%s directory", mytag,(char *)inet_ntoa(myinaddr)); return status; } if (lu_res.status != NI_OK) { /* no /machines! */ free(childdir.key); free(childdir.value); socket_lock(); clnt_destroy(cl); (void)close(sock); socket_unlock(); FD_CLR(sock, &clnt_fdset); /* unprotect client socket */ system_log(LOG_ERR, "tag %s: can't get master's /machines/ip_address=%s directory", mytag,(char *)inet_ntoa(myinaddr)); return lu_res.status; } if (lu_res.ni_lookup_res_u.stuff.idlist.ni_idlist_len == 0) { /* can't get /machines/ip_address=<myaddr>! */ xdr_free(xdr_ni_lookup_res, (void *)&lu_res); free(childdir.key); free(childdir.value); socket_lock(); clnt_destroy(cl); (void)close(sock); socket_unlock(); FD_CLR(sock, &clnt_fdset); /* unprotect client socket */ system_log(LOG_ERR, "tag %s: master has no /machines/ip_address=%s directory", mytag,(char *)inet_ntoa(myinaddr)); return NI_NODIR; } /* list properties */ prop_res.ni_namelist_res_u.stuff.values.ni_namelist_val = NULL; childdir.id.nii_object = lu_res.ni_lookup_res_u.stuff.idlist.ni_idlist_val[0]; xdr_free(xdr_ni_lookup_res, (void *)&lu_res); bzero((char *)&prop_res, sizeof(prop_res)); status = clnt_call(cl, _NI_LISTPROPS, xdr_ni_id, &childdir.id, xdr_ni_namelist_res, &prop_res, tv); if (status != NI_OK) { /* can't get proplist! */ free(childdir.key); free(childdir.value); socket_lock(); clnt_destroy(cl); (void)close(sock); socket_unlock(); FD_CLR(sock, &clnt_fdset); /* unprotect client socket */ system_log(LOG_ERR, "tag %s: can't get master's property list for /machines/ip_address=%s", mytag,(char *)inet_ntoa(myinaddr)); return status; } free(childdir.key); free(childdir.value); if (prop_res.status != NI_OK) { /* no /machines! */ socket_lock(); clnt_destroy(cl); (void)close(sock); socket_unlock(); FD_CLR(sock, &clnt_fdset); /* unprotect client socket */ system_log(LOG_ERR, "tag %s: can't get master's property list for /machines/ip_address=%s", mytag,(char *)inet_ntoa(myinaddr)); return prop_res.status; } if (prop_res.ni_namelist_res_u.stuff.values.ni_namelist_len == 0) { /* can't get proplist! */ xdr_free(xdr_ni_namelist_res, (void *)&prop_res); socket_lock(); clnt_destroy(cl); (void)close(sock); socket_unlock(); FD_CLR(sock, &clnt_fdset); /* unprotect client socket */ system_log(LOG_ERR, "tag %s: master has no property list for /machines/ip_address=%s", mytag,(char *)inet_ntoa(myinaddr)); return NI_NOPROP; } /* find "serves" property */ where = ni_namelist_match(prop_res.ni_namelist_res_u.stuff.values, "serves"); xdr_free(xdr_ni_namelist_res, (void *)&prop_res); if (where == NI_INDEX_NULL) { /* no serves property! */ socket_lock(); clnt_destroy(cl); (void)close(sock); socket_unlock(); FD_CLR(sock, &clnt_fdset); /* unprotect client socket */ system_log(LOG_ERR, "tag %s: master has no serves property for /machines/ip_address=%s", mytag,(char *)inet_ntoa(myinaddr)); return NI_NOPROP; } /* fetch serves property */ pa.id = childdir.id; pa.prop_index = where; bzero((char *)&prop_res, sizeof(prop_res)); status = clnt_call(cl, _NI_READPROP, xdr_ni_prop_args, &pa, xdr_ni_namelist_res, &prop_res, tv); if (status != NI_OK) { /* can't get proplist! */ socket_lock(); clnt_destroy(cl); (void)close(sock); socket_unlock(); FD_CLR(sock, &clnt_fdset); /* unprotect client socket */ system_log(LOG_ERR, "tag %s: can't get master's serves property for /machines/ip_address=%s", mytag,(char *)inet_ntoa(myinaddr)); return status; } if (prop_res.status != NI_OK) { /* can't get proplist! */ socket_lock(); clnt_destroy(cl); (void)close(sock); socket_unlock(); FD_CLR(sock, &clnt_fdset); /* unprotect client socket */ system_log(LOG_ERR, "tag %s: can't get master's serves property for /machines/ip_address=%s", mytag,(char *)inet_ntoa(myinaddr)); return prop_res.status; } if (prop_res.ni_namelist_res_u.stuff.values.ni_namelist_len == 0) { /* no values in serves property! */ xdr_free(xdr_ni_namelist_res, (void *)&prop_res); socket_lock(); clnt_destroy(cl); (void)close(sock); socket_unlock(); FD_CLR(sock, &clnt_fdset); /* unprotect client socket */ system_log(LOG_ERR, "tag %s: master has no values for serves property in /machines/ip_address=%s", mytag,(char *)inet_ntoa(myinaddr)); return NI_NOPROP; } /* find my "serves" property */ sprintf(myserves, "./%s", mytag); where = ni_namelist_match(prop_res.ni_namelist_res_u.stuff.values, myserves); xdr_free(xdr_ni_namelist_res, (void *)&prop_res); if (where == NI_INDEX_NULL) { /* no serves property! */ socket_lock(); clnt_destroy(cl); (void)close(sock); socket_unlock(); FD_CLR(sock, &clnt_fdset); /* unprotect client socket */ system_log(LOG_ERR, "tag %s: master has no serves ./%s property in /machines/ip_address=%s", mytag,mytag,(char *)inet_ntoa(myinaddr)); return NI_NONAME; } socket_lock(); clnt_destroy(cl); (void)close(sock); socket_unlock(); FD_CLR(sock, &clnt_fdset); /* unprotect client socket */ return NI_OK; }
int main(int argc, char *argv[]) { SVCXPRT *utransp, *ttransp; struct sockaddr_in addr; DIR *dp; struct direct *d; ni_name tag = NULL; ni_namelist nl; ni_index i; int pid, localonly, nctoken = -1; int log_pri = LOG_NOTICE; struct rlimit rlim; char *netinfod_argv[16]; /* XXX */ int netinfod_argc, x; union wait wait_stat; pid_t child_pid; char *pri; #ifdef _UNIX_BSD_43_ int ttyfd; #endif localonly = 1; netinfod_argc = 0; netinfod_argv[netinfod_argc++] = (char *)NETINFO_PROG; debug = 0; for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-n")) { netinfod_argv[netinfod_argc++] = argv[i]; } if (!strcmp(argv[i], "-d")) { debug = 1; log_pri = LOG_DEBUG; if ((argc > (i+1)) && (argv[i+1][0] != '-')) debug = atoi(argv[++i]); } if (!strcmp(argv[i], "-l")) { if ((argc > (i+1)) && (argv[i+1][0] != '-')) log_pri = atoi(argv[++i]); } if (!strcmp(argv[i], "-D")) { netinfod_argv[netinfod_argc++] = "-d"; if ((argc > (i+1)) && (argv[i+1][0] != '-')) { netinfod_argv[netinfod_argc++] = argv[i]; } } if (!strcmp(argv[i], "-L")) { netinfod_argv[netinfod_argc++] = "-l"; if ((argc > (i+1)) && (argv[i+1][0] != '-')) { netinfod_argv[netinfod_argc++] = argv[i]; } else { pri = malloc(sizeof("999")); sprintf(pri, "%d", LOG_DEBUG); netinfod_argv[netinfod_argc++] = pri; } } } if (debug == 1) { system_log_open("nibindd", LOG_NDELAY | LOG_PID, LOG_NETINFO, stderr); system_log_set_max_priority(log_pri); system_log(LOG_DEBUG, "version %s - debug mode\n", _PROJECT_VERSION_); } else { closeall(); system_log_open("nibindd", LOG_NDELAY | LOG_PID, LOG_NETINFO, NULL); system_log_set_max_priority(log_pri); system_log(LOG_DEBUG, "version %s - starting\n", _PROJECT_VERSION_); child_pid = fork(); if (child_pid == -1) { system_log(LOG_ALERT, "fork() failed: %m, aborting"); system_log_close(); exit(1); } else if (child_pid > 0) { signal(SIGTERM, parentexit); system_log(LOG_DEBUG, "parent waiting for child to start"); wait4(child_pid, (_WAIT_TYPE_ *)&wait_stat, 0, 0); if (WIFEXITED(wait_stat)) { system_log(LOG_DEBUG, "unexpected child exit, status=%d", WEXITSTATUS(wait_stat)); } else { system_log(LOG_DEBUG, "unexpected child exit, received signal=%d", WTERMSIG(wait_stat)); } system_log_close(); exit(1); } } restart = 0; rlim.rlim_cur = rlim.rlim_max = RLIM_INFINITY; setrlimit(RLIMIT_CORE, &rlim); signal(SIGCHLD, catchchild); signal(SIGTERM, killchildren); signal(SIGHUP, catchhup); signal(SIGINT, SIG_IGN); notify_register_signal(NETWORK_CHANGE_NOTIFICATION, SIGHUP, &nctoken); writepid(); /* * cd to netinfo directory, find out which databases should * be served and lock the directory before registering service. */ if (chdir(NETINFO_DIR) < 0) { killparent(); system_log(LOG_ALERT, "cannot chdir to netinfo directory"); exit(1); } dp = opendir(NETINFO_DIR); if (dp == NULL) { killparent(); system_log(LOG_ALERT, "cannot open netinfo directory"); exit(1); } MM_ZERO(&nl); while ((d = readdir(dp))) { if (isnidir(d->d_name, &tag)) { if (ni_namelist_match(nl, tag) == NI_INDEX_NULL) { system_log(LOG_DEBUG, "found database: %s", tag); ni_namelist_insert(&nl, tag, NI_INDEX_NULL); if (strcmp(tag, "local")) localonly = 0; } ni_name_free(&tag); } } #ifdef _NETINFO_FLOCK_ /* * Do not close the directory: keep it locked so another nibindd * won't run. */ if (flock(dp->dd_fd, LOCK_EX|LOCK_NB) < 0) { killparent(); system_log(LOG_ALERT, "nibindd already running"); exit(1); } fcntl(dp->dd_fd, F_SETFD, 1); #else closedir(dp); #endif /* * Register as a SUNRPC service */ memset(&addr, 0, sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; if (localonly == 1) addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); pmap_unset(NIBIND_PROG, NIBIND_VERS); utransp = svcudp_bind(RPC_ANYSOCK, addr); if (utransp == NULL) { killparent(); system_log(LOG_ALERT, "cannot start udp service"); exit(1); } if (!svc_register(utransp, NIBIND_PROG, NIBIND_VERS, nibind_prog_1, IPPROTO_UDP)) { killparent(); system_log(LOG_ALERT, "cannot register udp service"); exit(1); } udp_sock = utransp->xp_sock; ttransp = svctcp_bind(RPC_ANYSOCK, addr, 0, 0); if (ttransp == NULL) { killparent(); system_log(LOG_ALERT, "cannot start tcp service"); exit(1); } if (!svc_register(ttransp, NIBIND_PROG, NIBIND_VERS, nibind_prog_1, IPPROTO_TCP)) { killparent(); system_log(LOG_ALERT, "cannot register tcp service"); exit(1); } waitreg = 0; for (i = 0; i < nl.ninl_len; i++) { netinfod_argv[netinfod_argc] = nl.ninl_val[i]; netinfod_argv[netinfod_argc + 1] = NULL; system_log(LOG_DEBUG, "starting netinfod %s", nl.ninl_val[i]); system_log(LOG_DEBUG, "execv debug 0: %s", NETINFO_PROG); for (x = 0; netinfod_argv[x] != NULL; x++) { system_log(LOG_DEBUG, "execv debug %d: %s", x, netinfod_argv[x]); } pid = fork(); if (pid == 0) { /* child */ execv(NETINFO_PROG, netinfod_argv); exit(-1); } #ifdef DEBUG system_log(LOG_DEBUG, "netinfod %s pid = %d", nl.ninl_val[i], pid); #endif if (pid > 0) { waitreg++; storepid(pid, nl.ninl_val[i]); } else { system_log(LOG_ERR, "server for tag %s failed to start", nl.ninl_val[i]); } } ni_namelist_free(&nl); /* * Detach from controlling tty. * Do this AFTER starting netinfod so "type c to continue..." works. */ #ifdef _UNIX_BSD_43_ ttyfd = open("/dev/tty", O_RDWR, 0); if (ttyfd > 0) { ioctl(ttyfd, TIOCNOTTY, NULL); close(ttyfd); } setpgrp(0, getpid()); #else if (setsid() < 0) syslog(LOG_ERR, "nibindd: setsid() failed: %m"); #endif system_log(LOG_DEBUG, "starting RPC service"); nibind_svc_run(); system_log(LOG_ALERT, "svc_run returned"); system_log_close(); exit(1); }