static int get_local_ordernum(char *domain, char *map, u_int32_t *lordernum) { char map_path[MAXPATHLEN], order[MAX_LAST_LEN+1]; char order_key[] = YP_LAST_KEY; struct stat finfo; datum k, v; int status; DBM *db; /* This routine returns YPPUSH_SUCC or YPPUSH_NODOM */ status = YPPUSH_SUCC; snprintf(map_path, sizeof map_path, "%s/%s", YP_DB_PATH, domain); if (!((stat(map_path, &finfo) == 0) && S_ISDIR(finfo.st_mode))) { fprintf(stderr, "ypxfr: domain %s not found locally\n", domain); status = YPPUSH_NODOM; goto bail; } snprintf(map_path, sizeof map_path, "%s/%s/%s%s", YP_DB_PATH, domain, map, YPDB_SUFFIX); if (!(stat(map_path, &finfo) == 0)) { status = YPPUSH_NOMAP; goto bail; } snprintf(map_path, sizeof map_path, "%s/%s/%s", YP_DB_PATH, domain, map); db = ypdb_open(map_path, O_RDONLY, 0444); if (db == NULL) { status = YPPUSH_DBM; goto bail; } k.dptr = (char *)&order_key; k.dsize = YP_LAST_LEN; v = ypdb_fetch(db, k); if (v.dptr == NULL) { *lordernum = 0; } else { strlcpy(order, v.dptr, sizeof order); *lordernum = (u_int32_t)atol(order); } ypdb_close(db); bail: if (status == YPPUSH_NOMAP || status == YPPUSH_DBM) { *lordernum = 0; status = YPPUSH_SUCC; } return (status); }
/* * Close specified map. */ void ypdb_close_map(struct opt_map *map) { CIRCLEQ_REMOVE(&maps, map, mapsq); /* remove from LRU circleq */ LIST_REMOVE(map, mapsl); /* remove from domain list */ #ifdef DEBUG syslog(LOG_DEBUG, "ypdb_close_map: closing map %s in domain %s [db=%p]", map->map, map->dom->domain, map->db); #endif ypdb_close(map->db); /* close DB */ free(map->map); /* free map name */ free(map); /* free map */ }
int main(int argc, char *argv[]) { int eflag = 0, dflag = 0, nflag = 0; int uflag = 0, vflag = 0, Eflag = 0; int status, ch, fd; char *input = NULL, *output = NULL; DBM *db; datum key, val; DBM *new_db = NULL; static char mapname[] = "ypdbXXXXXXXXXX"; char db_mapname[PATH_MAX], db_outfile[PATH_MAX]; char db_tempname[PATH_MAX]; char user[4096], host[4096]; /* XXX: DB bsize = 4096 in ypdb.c */ char myname[HOST_NAME_MAX+1], datestr[11], *slash; while ((ch = getopt(argc, argv, "Edensuv")) != -1) switch (ch) { case 'E': eflag = 1; /* Check hostname */ Eflag = 1; /* .. even check MX records */ break; case 'd': dflag = 1; /* Don't check DNS hostname */ break; case 'e': eflag = 1; /* Check hostname */ break; case 'n': nflag = 1; /* Capitalize name parts */ break; case 's': /* Ignore */ break; case 'u': uflag = 1; /* Don't check UUCP hostname */ break; case 'v': vflag = 1; /* Verbose */ break; default: usage(); break; } if (optind == argc) usage(); input = argv[optind++]; if (optind < argc) output = argv[optind++]; if (optind < argc) usage(); db = ypdb_open(input, O_RDONLY, 0444); if (db == NULL) { err(1, "Unable to open input database %s", input); /* NOTREACHED */ } if (output != NULL) { if (strlen(output) + strlen(YPDB_SUFFIX) > PATH_MAX) { errx(1, "%s: file name too long", output); /* NOTREACHED */ } snprintf(db_outfile, sizeof(db_outfile), "%s%s", output, YPDB_SUFFIX); slash = strrchr(output, '/'); if (slash != NULL) slash[1] = 0; /* truncate to dir */ else *output = 0; /* eliminate */ /* note: output is now directory where map goes ! */ if (strlen(output) + strlen(mapname) + strlen(YPDB_SUFFIX) > PATH_MAX) { errx(1, "%s: directory name too long", output); /* NOTREACHED */ } snprintf(db_tempname, sizeof(db_tempname), "%s%s%s", output, mapname, YPDB_SUFFIX); fd = mkstemps(db_tempname, 3); if (fd == -1) goto fail; close(fd); strncpy(db_mapname, db_tempname, strlen(db_tempname) - 3); db_mapname[sizeof(db_mapname) - 1] = '\0'; new_db = ypdb_open(db_mapname, O_RDWR|O_TRUNC, 0444); if (new_db == NULL) { fail: if (fd != -1) unlink(db_tempname); err(1, "Unable to open output database %s", db_outfile); /* NOTREACHED */ } } for (key = ypdb_firstkey(db); key.dptr != NULL; key = ypdb_nextkey(db)) { val = ypdb_fetch(db, key); if (val.dptr == NULL) continue; /* No value */ if (*key.dptr == '@' && key.dsize == 1) continue; /* Sendmail token */ if (strncmp(key.dptr, "YP_", 3)==0) /* YP token */ continue; if (memchr(val.dptr, ',', val.dsize)) continue; /* List... */ if (memchr(val.dptr, '|', val.dsize)) continue; /* Pipe... */ if (!(memchr(val.dptr, '@', val.dsize) || memchr(val.dptr, '!', val.dsize))) continue; /* Skip local users */ split_address(val.dptr, val.dsize, user, host); if (eflag && check_host(val.dptr, val.dsize, host, dflag, uflag, Eflag)) { warnx("Invalid host %s in %*.*s:%*.*s", host, key.dsize, key.dsize, key.dptr, val.dsize, val.dsize, val.dptr); continue; } if (nflag) capitalize(key.dptr, key.dsize); if (new_db != NULL) { status = ypdb_store(new_db, val, key, YPDB_INSERT); if (status != 0) { warnx("problem storing %*.*s %*.*s", val.dsize, val.dsize, val.dptr, key.dsize, key.dsize, key.dptr); } } if (vflag) { printf("%*.*s --> %*.*s\n", val.dsize, val.dsize, val.dptr, key.dsize, key.dsize, key.dptr); } } if (new_db != NULL) { snprintf(datestr, sizeof datestr, "%010lld", (long long)time(NULL)); key.dptr = YP_LAST_KEY; key.dsize = strlen(YP_LAST_KEY); val.dptr = datestr; val.dsize = strlen(datestr); status = ypdb_store(new_db, key, val, YPDB_INSERT); if (status != 0) { warnx("problem storing %*.*s %*.*s", key.dsize, key.dsize, key.dptr, val.dsize, val.dsize, val.dptr); } } if (new_db != NULL) { gethostname(myname, sizeof(myname)); key.dptr = YP_MASTER_KEY; key.dsize = strlen(YP_MASTER_KEY); val.dptr = myname; val.dsize = strlen(myname); status = ypdb_store(new_db, key, val, YPDB_INSERT); if (status != 0) { warnx("problem storing %*.*s %*.*s", key.dsize, key.dsize, key.dptr, val.dsize, val.dsize, val.dptr); } } ypdb_close(db); if (new_db != NULL) { ypdb_close(new_db); if (rename(db_tempname, db_outfile) < 0) { err(1, "rename %s -> %s failed", db_tempname, db_outfile); /* NOTREACHED */ } } return(0); }
/* * ypdb_open_db */ DBM * ypdb_open_db(const char *domain, const char *map, u_int *status, struct opt_map **map_info) { static const char *domain_key = YP_INTERDOMAIN_KEY; static const char *secure_key = YP_SECURE_KEY; char map_path[MAXPATHLEN]; struct stat finfo; struct opt_domain *d = NULL; struct opt_map *m = NULL; DBM *db; datum k, v; *status = YP_TRUE; /* defaults to true */ /* * check for illegal domain and map names */ if (_yp_invalid_domain(domain)) { *status = YP_NODOM; return (NULL); } if (_yp_invalid_map(map)) { *status = YP_NOMAP; return (NULL); } /* * check for domain, file. */ (void)snprintf(map_path, sizeof(map_path), "%s/%s", YP_DB_PATH, domain); if (stat(map_path, &finfo) < 0 || !S_ISDIR(finfo.st_mode)) { #ifdef DEBUG syslog(LOG_DEBUG, "ypdb_open_db: no domain %s (map=%s)", domain, map); #endif *status = YP_NODOM; } else { (void)snprintf(map_path, sizeof(map_path), "%s/%s/%s%s", YP_DB_PATH, domain, map, YPDB_SUFFIX); if (stat(map_path, &finfo) < 0) { #ifdef DEBUG syslog(LOG_DEBUG, "ypdb_open_db: no map %s (domain=%s)", map, domain); #endif *status = YP_NOMAP; } } /* * check for preloaded domain, map */ for (d = doms.lh_first; d != NULL; d = d->domsl.le_next) if (strcmp(domain, d->domain) == 0) break; if (d) for (m = d->dmaps.lh_first; m != NULL; m = m->mapsl.le_next) if (strcmp(map, m->map) == 0) break; /* * map found open? */ if (m) { #ifdef DEBUG syslog(LOG_DEBUG, "ypdb_open_db: cached open: domain=%s, map=%s, db=%p,", domain, map, m->db); syslog(LOG_DEBUG, "\tdbdev %d new %d; dbino %d new %d; dbmtime %ld new %ld", m->dbdev, finfo.st_dev, m->dbino, finfo.st_ino, (long) m->dbmtime, (long) finfo.st_mtime); #endif /* * if status != YP_TRUE, then this cached database is now * non-existent */ if (*status != YP_TRUE) { #ifdef DEBUG syslog(LOG_DEBUG, "ypdb_open_db: cached db is now unavailable - " "closing: status %s", yperr_string(ypprot_err(*status))); #endif ypdb_close_map(m); return (NULL); } /* * is this the same db? */ if (finfo.st_dev == m->dbdev && finfo.st_ino == m->dbino && finfo.st_mtime == m->dbmtime) { CIRCLEQ_REMOVE(&maps, m, mapsq); /* adjust LRU queue */ CIRCLEQ_INSERT_HEAD(&maps, m, mapsq); if (map_info) *map_info = m; return (m->db); } else { #ifdef DEBUG syslog(LOG_DEBUG, "ypdb_open_db: db changed; closing"); #endif ypdb_close_map(m); m = NULL; } } /* * not cached and non-existent, return */ if (*status != YP_TRUE) return (NULL); /* * open map */ (void)snprintf(map_path, sizeof(map_path), "%s/%s/%s", YP_DB_PATH, domain, map); #ifdef OPTIMIZE_DB retryopen: #endif /* OPTIMIZE_DB */ db = ypdb_open(map_path); #ifdef OPTIMIZE_DB if (db == NULL) { #ifdef DEBUG syslog(LOG_DEBUG, "ypdb_open_db: errno %d (%s)", errno, strerror(errno)); #endif /* DEBUG */ if ((errno == ENFILE) || (errno == EMFILE)) { ypdb_close_last(); goto retryopen; } } #endif /* OPTIMIZE_DB */ *status = YP_NOMAP; /* see note below */ if (db == NULL) { #ifdef DEBUG syslog(LOG_DEBUG, "ypdb_open_db: ypdb_open FAILED: map %s (domain=%s)", map, domain); #endif return (NULL); } /* * note: status now YP_NOMAP */ if (d == NULL) { /* allocate new domain? */ d = (struct opt_domain *) malloc(sizeof(*d)); if (d) d->domain = strdup(domain); if (d == NULL || d->domain == NULL) { syslog(LOG_ERR, "ypdb_open_db: MALLOC failed"); ypdb_close(db); if (d) free(d); return (NULL); } LIST_INIT(&d->dmaps); LIST_INSERT_HEAD(&doms, d, domsl); #ifdef DEBUG syslog(LOG_DEBUG, "ypdb_open_db: NEW DOMAIN %s", domain); #endif } /* * m must be NULL since we couldn't find a map. allocate new one */ m = (struct opt_map *) malloc(sizeof(*m)); if (m) m->map = strdup(map); if (m == NULL || m->map == NULL) { if (m) free(m); syslog(LOG_ERR, "ypdb_open_db: MALLOC failed"); ypdb_close(db); return (NULL); } m->db = db; m->dom = d; m->host_lookup = FALSE; m->dbdev = finfo.st_dev; m->dbino = finfo.st_ino; m->dbmtime = finfo.st_mtime; CIRCLEQ_INSERT_HEAD(&maps, m, mapsq); LIST_INSERT_HEAD(&d->dmaps, m, mapsl); if (strcmp(map, YP_HOSTNAME) == 0 || strcmp(map, YP_HOSTADDR) == 0) { if (!usedns) { k.dptr = domain_key; k.dsize = YP_INTERDOMAIN_LEN; v = ypdb_fetch(db, k); if (v.dptr) m->host_lookup = TRUE; } else m->host_lookup = TRUE; } m->secure = FALSE; k.dptr = secure_key; k.dsize = YP_SECURE_LEN; v = ypdb_fetch(db, k); if (v.dptr != NULL) m->secure = TRUE; *status = YP_TRUE; if (map_info) *map_info = m; #ifdef DEBUG syslog(LOG_DEBUG, "ypdb_open_db: NEW MAP domain=%s, map=%s, hl=%d, s=%d, db=%p", domain, map, m->host_lookup, m->secure, m->db); #endif return (m->db); }
int main(int argc, char *argv[]) { int cflag = 0, fflag = 0, Cflag = 0; char *domain, *host = NULL, *srcdomain = NULL; char *tid = NULL, *prog = NULL, *ipadd = NULL; char *port = NULL, *map = NULL; int status, xfr_status, ch, srvport; u_int32_t ordernum, new_ordernum; struct ypall_callback callback; CLIENT *client = NULL; extern char *optarg; yp_get_default_domain(&domain); while ((ch = getopt(argc, argv, "cd:fh:s:C:")) != -1) switch (ch) { case 'c': cflag++; break; case 'd': if (strchr(optarg, '/')) /* Ha ha, we are not listening */ break; domain = optarg; break; case 'f': fflag++; break; case 'h': host = optarg; break; case 's': if (strchr(optarg, '/')) /* Ha ha, we are not listening */ break; srcdomain = optarg; break; case 'C': if (optind + 3 >= argc) usage(); Cflag++; tid = optarg; prog = argv[optind++]; ipadd = argv[optind++]; port = argv[optind++]; break; default: usage(); break; } status = YPPUSH_SUCC; if (optind + 1 != argc) usage(); map = argv[optind]; if (status > 0) { ypopenlog(); yplog("ypxfr: Arguments:"); yplog("YP clear to local: %s", (cflag) ? "no" : "yes"); yplog(" Force transfer: %s", (fflag) ? "yes" : "no"); yplog(" domain: %s", domain); yplog(" host: %s", host); yplog(" source domain: %s", srcdomain); yplog(" transid: %s", tid); yplog(" prog: %s", prog); yplog(" port: %s", port); yplog(" ipadd: %s", ipadd); yplog(" map: %s", map); if (fflag != 0) { ordernum = 0; } else { status = get_local_ordernum(domain, map, &ordernum); } } if (status > 0) { yplog("Get Master"); if (host == NULL) { if (srcdomain == NULL) { status = yp_master(domain, map, &host); } else { status = yp_master(srcdomain, map, &host); } if (status == 0) { status = YPPUSH_SUCC; } else { status = -status; } } } /* XXX this is raceable if portmap has holes! */ if (status > 0) { yplog("Check for reserved port on host: %s", host); srvport = getrpcport(host, YPPROG, YPVERS, IPPROTO_TCP); if (srvport >= IPPORT_RESERVED) status = YPPUSH_REFUSED; } if (status > 0) { yplog("Connect host: %s", host); client = yp_bind_host(host, YPPROG, YPVERS, 0, 1); status = get_remote_ordernum(client, domain, map, ordernum, &new_ordernum); } if (status == YPPUSH_SUCC) { char tmpmapname[MAXPATHLEN]; int fd; /* Create temporary db */ snprintf(tmpmapname, sizeof tmpmapname, "%s/%s/ypdbXXXXXXXXXX", YP_DB_PATH, domain); fd = mkstemp(tmpmapname); if (fd == -1) status = YPPUSH_DBM; else close(fd); if (status > 0) { db = create_db(domain, map, tmpmapname); if (db == NULL) status = YPPUSH_DBM; } /* Add ORDER */ if (status > 0) status = add_order(db, new_ordernum); /* Add MASTER */ if (status > 0) status = add_master(client, domain, map, db); /* Add INTERDOMAIN */ if (status > 0) status = add_interdomain(client, domain, map, db); /* Add SECURE */ if (status > 0) status = add_secure(client, domain, map, db); if (status > 0) { callback.foreach = ypxfr_foreach; status = get_map(client, domain, map, &callback); } /* Close db */ if (db != NULL) ypdb_close(db); /* Rename db */ if (status > 0) { status = install_db(domain, map, tmpmapname); } else { unlink(tmpmapname); status = YPPUSH_SUCC; } } xfr_status = status; if (client != NULL) clnt_destroy(client); /* YP_CLEAR */ if (!cflag) { client = yp_bind_local(YPPROG, YPVERS); status = send_clear(client); clnt_destroy(client); } if (Cflag > 0) { /* Send Response */ client = yp_bind_host(ipadd, atoi(prog), 1, atoi(port), 0); status = send_reply(client, xfr_status, atoi(tid)); clnt_destroy(client); } return (0); }