Esempio n. 1
0
static bool record_match_all(struct record *re, char **matches)
{
    while (*matches != NULL) {
        if (!record_match(re, *matches))
            return false;
        matches++;
    }
    return true;
}
Esempio n. 2
0
int index_match(struct index *src, struct index *dest,
                const struct match *match)
{
    int n;
    struct record *re;

    index_blank(dest);

    for (n = 0; n < src->entries; n++) {
        re = src->record[n];

        if (record_match(re, match)) {
            if (index_reserve(dest, 1) == -1)
                return -1;
            index_add(dest, re);
        }
    }

    return 0;
}
Esempio n. 3
0
/*
 * Internal version lookup routine used by both lookup_dn() and
 * update_dn(); same semantics as lookup_dn() except that the `partial'
 * argument has been generalized into a `flags' field.
 */
static int
find_dn(int fd, uint_t flags, uint_t query, int count, const dn_rec_t *targetp,
    dn_rec_list_t **recordsp, uint_t *nrecordsp)
{
	int		retval = DSVC_SUCCESS;
	char		*fields[DNF_FIELDS];
	uint_t		nrecords;
	dn_rec_t	dn, *recordp;
	dn_rec_list_t	*records, *new_records;
	unsigned int	nfields;
	struct stat	st;
	struct in_addr	cip_nbo;
	char		*ent0, *ent, *entend;
	char		cip[INET_ADDRSTRLEN + 2];

	/*
	 * Page the whole container into memory via mmap() so we can scan it
	 * quickly; map it MAP_PRIVATE so that we can change newlines to
	 * NULs without changing the actual container itself.
	 */
	if (fstat(fd, &st) == -1 || st.st_size < 1)
		return (DSVC_INTERNAL);

	ent0 = mmap(0, st.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
	if (ent0 == MAP_FAILED)
		return (DSVC_INTERNAL);

	/*
	 * NUL-terminate the last byte (which should be a newline) so that
	 * we can safely use string functions on the mapped container.
	 */
	ent0[st.st_size - 1] = '\0';

	/*
	 * If we're searching by client IP address, then build a target
	 * string we can use to find it quickly.
	 */
	if (DSVC_QISEQ(query, DN_QCIP)) {
		cip[0] = '\n';
		cip_nbo.s_addr = htonl(targetp->dn_cip.s_addr);
		(void) inet_ntop(AF_INET, &cip_nbo, cip + 1, INET_ADDRSTRLEN);
		(void) strlcat(cip, "|", sizeof (cip));
	}

	records = NULL;
	ent = ent0;
	for (nrecords = 0; count < 0 || nrecords < count; ent = entend + 1) {
		/*
		 * Bail if we've reached the end of the container.
		 */
		if (ent - ent0 >= st.st_size)
			break;

		/*
		 * If we're searching by client IP address, locate it
		 * quickly using strstr(3C); if we can't find it by this
		 * technique then it's not in the container.
		 */
		if (DSVC_QISEQ(query, DN_QCIP)) {
			/*
			 * If we've already found the DN_QCIP record, bail.
			 */
			if (nrecords > 0)
				break;

			ent = strstr(ent, cip);
			if (ent == NULL)
				break;
			ent++;
		}

		/*
		 * Find the end of the record and change it a NUL byte so
		 * that it is interpreted correctly with field_split() and
		 * record_match() below.  If we can't find a trailing
		 * newline, then it must be the last record (whose newline
		 * we already changed to a NUL above).
		 */
		entend = strchr(ent, '\n');
		if (entend != NULL)
			*entend = '\0';
		else
			entend = &ent0[st.st_size - 1];

		/*
		 * Skip pure comment lines; for now this just skips the
		 * header information at the top of the container.
		 */
		if (ent[0] == DNF_COMMENT_CHAR)
			continue;

		/*
		 * Split the buffer up into DNF_FIELDS fields.
		 */
		nfields = field_split(ent, DNF_FIELDS, fields, "|");
		if (nfields < DNF_FIELDS)
			continue;

		/*
		 * See if we've got a match, filling in dnf.dnf_rec as
		 * we go.  If record_match() succeeds, dnf.dnf_rec will
		 * be completely filled in.
		 */
		if (!record_match(fields, &dn, targetp, query))
			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 (dn_recpos_t) record.
		 */
		if (flags & FIND_POSITION)
			recordp = malloc(sizeof (dn_recpos_t));
		else
			recordp = malloc(sizeof (dn_rec_t));

		if (recordp == NULL) {
			if ((flags & FIND_PARTIAL) == 0)
				retval = DSVC_NO_MEMORY;
			break;
		}

		/*
		 * Fill in record; do a structure copy from our automatic
		 * dn.  If FIND_POSITION flag is on, pass back additional
		 * position information.
		 */
		*recordp = dn;
		if (flags & FIND_POSITION) {
			((dn_recpos_t *)recordp)->dnp_off = ent - ent0;
			((dn_recpos_t *)recordp)->dnp_size = entend - ent + 1;
		}

		/*
		 * Chuck the record on the list; up the counter.
		 */
		new_records = add_dnrec_to_list(recordp, records);
		if (new_records == NULL) {
			free(recordp);
			if ((flags & FIND_PARTIAL) == 0)
				retval = DSVC_NO_MEMORY;
			break;
		}

		records = new_records;
		nrecords++;
	}

	(void) munmap(ent0, st.st_size);

	if (retval == DSVC_SUCCESS) {
		*nrecordsp = nrecords;
		if (recordsp != NULL)
			*recordsp = records;
		return (DSVC_SUCCESS);
	}

	if (records != NULL)
		free_dnrec_list(records);

	return (retval);
}