/* * Internal version of lookup_dt() used by both lookup_dt() and * update_dt(); same semantics as lookup_dt() except that the `partial' * argument has been generalized into a `flags' field and the handle has * been turned into a FILE pointer. */ static int find_dt(FILE *fp, uint_t flags, uint_t query, int count, const dt_rec_t *targetp, dt_rec_list_t **recordsp, uint_t *nrecordsp) { int retval = DSVC_SUCCESS; char *buf = NULL, *fields[DTF_MAX_FIELDS]; uint_t nrecords; dt_rec_t *recordp; dt_rec_list_t *records, *new_records; unsigned int nfields; off_t recoff; if (fseek(fp, 0, SEEK_SET) == -1) return (DSVC_INTERNAL); records = NULL; for (nrecords = 0; count < 0 || nrecords < count; ) { free(buf); if (flags & FIND_POSITION) recoff = ftello(fp); buf = read_entry(fp); if (buf == NULL) { if (!feof(fp)) retval = DSVC_NO_MEMORY; break; } /* * Skip pure comment lines; for now this just skips the * header information at the top of the container. */ if (buf[0] == DTF_COMMENT_CHAR) continue; /* * Parse out the entry into the dt_rec_t */ nfields = field_split(buf, DTF_MAX_FIELDS, fields, " \t"); if (nfields < DTF_MAX_FIELDS) continue; /* * See if we've got a match. If so, allocate the new * record, fill it in, and continue. */ if (DSVC_QISEQ(query, DT_QTYPE) && targetp->dt_type != fields[DTF_TYPE][0]) continue; else if (DSVC_QISNEQ(query, DT_QTYPE) && targetp->dt_type == fields[DTF_TYPE][0]) continue; if (DSVC_QISEQ(query, DT_QKEY) && strcmp(targetp->dt_key, fields[DTF_KEY]) != 0) continue; else if (DSVC_QISNEQ(query, DT_QKEY) && strcmp(targetp->dt_key, fields[DTF_KEY]) == 0) continue; /* * Caller just wants a count of the number of matching * records, not the records themselves; continue. */ if (recordsp == NULL) { nrecords++; continue; } /* * Allocate record; if FIND_POSITION flag is set, then we * need to allocate an extended (dt_recpos_t) record. */ if (flags & FIND_POSITION) recordp = malloc(sizeof (dt_recpos_t)); else recordp = malloc(sizeof (dt_rec_t)); if (recordp == NULL) { if ((flags & FIND_PARTIAL) == 0) retval = DSVC_NO_MEMORY; break; } /* * Fill in record; if FIND_POSITION flag is set, then pass * back additional location information. */ (void) strlcpy(recordp->dt_key, fields[DTF_KEY], sizeof (recordp->dt_key)); recordp->dt_sig = 1; recordp->dt_type = fields[DTF_TYPE][0]; recordp->dt_value = strdup(fields[DTF_VALUE]); if (recordp->dt_value == NULL) { free(recordp); if ((flags & FIND_PARTIAL) == 0) retval = DSVC_NO_MEMORY; break; } if (flags & FIND_POSITION) { ((dt_recpos_t *)recordp)->dtp_off = recoff; ((dt_recpos_t *)recordp)->dtp_size = ftello(fp) - recoff; } /* * Chuck the record on the list; up the counter. */ new_records = add_dtrec_to_list(recordp, records); if (new_records == NULL) { free_dtrec(recordp); if ((flags & FIND_PARTIAL) == 0) retval = DSVC_NO_MEMORY; break; } records = new_records; nrecords++; } free(buf); if (retval == DSVC_SUCCESS) { *nrecordsp = nrecords; if (recordsp != NULL) *recordsp = records; return (DSVC_SUCCESS); } if (records != NULL) free_dtrec_list(records); return (retval); }
/* * Compares the fields in fields[] agains the fields in target `targetp', * using `query' to decide what fields to compare. Returns B_TRUE if `dnp' * matches `targetp', B_FALSE if not. On success, `dnp' is completely * filled in. */ static boolean_t record_match(char *fields[], dn_rec_t *dnp, const dn_rec_t *targetp, uint_t query) { unsigned int qflags[] = { DN_QFDYNAMIC, DN_QFAUTOMATIC, DN_QFMANUAL, DN_QFUNUSABLE, DN_QFBOOTP_ONLY }; unsigned int flags[] = { DN_FDYNAMIC, DN_FAUTOMATIC, DN_FMANUAL, DN_FUNUSABLE, DN_FBOOTP_ONLY }; unsigned int i; uint_t dn_cid_len; dnp->dn_cip.s_addr = ntohl(inet_addr(fields[DNF_CIP])); if (DSVC_QISEQ(query, DN_QCIP) && dnp->dn_cip.s_addr != targetp->dn_cip.s_addr) return (B_FALSE); if (DSVC_QISNEQ(query, DN_QCIP) && dnp->dn_cip.s_addr == targetp->dn_cip.s_addr) return (B_FALSE); dnp->dn_lease = atoi(fields[DNF_LEASE]); if (DSVC_QISEQ(query, DN_QLEASE) && targetp->dn_lease != dnp->dn_lease) return (B_FALSE); if (DSVC_QISNEQ(query, DN_QLEASE) && targetp->dn_lease == dnp->dn_lease) return (B_FALSE); /* * We use dn_cid_len since dnp->dn_cid_len is of type uchar_t but * hexascii_to_octet() expects an uint_t * */ dn_cid_len = DN_MAX_CID_LEN; if (hexascii_to_octet(fields[DNF_CID], strlen(fields[DNF_CID]), dnp->dn_cid, &dn_cid_len) != 0) return (B_FALSE); dnp->dn_cid_len = dn_cid_len; if (DSVC_QISEQ(query, DN_QCID) && (dnp->dn_cid_len != targetp->dn_cid_len || (memcmp(dnp->dn_cid, targetp->dn_cid, dnp->dn_cid_len) != 0))) return (B_FALSE); if (DSVC_QISNEQ(query, DN_QCID) && (dnp->dn_cid_len == targetp->dn_cid_len && (memcmp(dnp->dn_cid, targetp->dn_cid, dnp->dn_cid_len) == 0))) return (B_FALSE); dnp->dn_sip.s_addr = ntohl(inet_addr(fields[DNF_SIP])); if (DSVC_QISEQ(query, DN_QSIP) && dnp->dn_sip.s_addr != targetp->dn_sip.s_addr) return (B_FALSE); if (DSVC_QISNEQ(query, DN_QSIP) && dnp->dn_sip.s_addr == targetp->dn_sip.s_addr) return (B_FALSE); unescape('|', fields[DNF_MACRO], dnp->dn_macro, sizeof (dnp->dn_macro)); if (DSVC_QISEQ(query, DN_QMACRO) && strcmp(targetp->dn_macro, dnp->dn_macro) != 0) return (B_FALSE); if (DSVC_QISNEQ(query, DN_QMACRO) && strcmp(targetp->dn_macro, dnp->dn_macro) == 0) return (B_FALSE); dnp->dn_flags = atoi(fields[DNF_FLAGS]); for (i = 0; i < sizeof (qflags) / sizeof (unsigned int); i++) { if (DSVC_QISEQ(query, qflags[i]) && (dnp->dn_flags & flags[i]) != (targetp->dn_flags & flags[i])) return (B_FALSE); if (DSVC_QISNEQ(query, qflags[i]) && (dnp->dn_flags & flags[i]) == (targetp->dn_flags & flags[i])) return (B_FALSE); } dnp->dn_sig = atoll(fields[DNF_SIG]); unescape('|', fields[DNF_COMMENT], dnp->dn_comment, sizeof (dnp->dn_comment)); return (B_TRUE); }